内核参数overcommit_memory 

它是 内存分配策略

可选值:0、1、2。
0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

什么是Overcommit和OOM

        Linux对大部分申请内存的请求都回复”yes”,以便能跑更多更大的程序。因为申请内存后,并不会马上使用内存。这种技术叫做 Overcommit。当linux发现内存不足时,会发生OOM killer(OOM=out-of-memory)。它会选择杀死一些进程(用户态进程,不是内核线程),以便释放内存。
        当oom-killer发生时,linux会选择杀死哪些进程?选择进程的函数是oom_badness函数(在mm/oom_kill.c中),该 函数会计算每个进程的点数(0~1000)。点数越高,这个进程越有可能被杀死。每个进程的点数跟oom_score_adj有关,而且 oom_score_adj可以被设置(-1000最低,1000最高)。

解决方法:

     很简单,按提示的操作(将vm.overcommit_memory 设为1)即可:

     有三种方式修改内核参数,但要有root权限:

 (1)编辑/etc/sysctl.conf ,改vm.overcommit_memory=1,然后sysctl -p使配置文件生效

 (2)sysctl vm.overcommit_memory=1

 (3)echo 1 > /proc/sys/vm/overcommit_memory

Link: https://www.cnblogs.com/zxc2man/p/12911427.html

1、查看firewall服务状态

systemctl status firewalld

2、查看firewall的状态

firewall-cmd --state

3、开启、重启、关闭、firewalld.service服务

查看linux哪些程序正在使用互联网

firewall-cmd --permanent --list-services ssh dhcpv6-client

开启

service firewalld start

重启

service firewalld restart

关闭

service firewalld stop

4、查看防火墙规则

firewall-cmd --list-all 

5、查询、开放、关闭端口

查询端口是否开放

firewall-cmd --query-port=8080/tcp

开放80端口

firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=8080-8085/tcp

移除端口

firewall-cmd --permanent --remove-port=8080/tcp
查看防火墙的开放的端口
firewall-cmd --permanent --list-ports

重启防火墙(修改配置后要重启防火墙)

firewall-cmd --reload

参数解释

1、firwall-cmd:是Linux提供的操作firewall的一个工具;
2、--permanent:表示设置为持久;
3、--add-port:标识添加的端口;

Link: https://blog.csdn.net/qq_41153478/article/details/83033688

tcpdump是一个用于截取网络分组,并输出分组内容的工具。tcpdump凭借强大的功能和灵活的截取策略,使其成为类UNIX系统下用于网络分析和问题排查的首选工具。 

tcpdump提供了源代码,公开了接口,因此具备很强的可扩展性,对于网络维护和入侵者都是非常有用的工具。tcpdump存在于基本的Linux系统中,由于它需要将网络界面设置为混杂模式,普通用户不能正常执行,但具备root权限的用户可以直接执行它来获取网络上的信息。因此系统中存在网络分析工具主要不是对本机安全的威胁,而是对网络上的其他计算机的安全存在威胁。

选项

  • -A 以ASCII格式打印出所有分组,并将链路层的头最小化。 
  • -c 在收到指定的数量的分组后,tcpdump就会停止。 
  • -C 在将一个原始分组写入文件之前,检查文件当前的大小是否超过了参数file_size 中指定的大小。如果超过了指定大小,则关闭当前文件,然后在打开一个新的文件。参数 file_size 的单位是兆字节(是1,000,000字节,而不是1,048,576字节)。 
  • -d 将匹配信息包的代码以人们能够理解的汇编格式给出。 
  • -dd 将匹配信息包的代码以c语言程序段的格式给出。 
  • -ddd 将匹配信息包的代码以十进制的形式给出。 
  • -D 打印出系统中所有可以用tcpdump截包的网络接口。 
  • -e 在输出行打印出数据链路层的头部信息。 
  • -E 用spi@ipaddr algo:secret解密那些以addr作为地址,并且包含了安全参数索引值spi的IPsec ESP分组。 
  • -f 将外部的Internet地址以数字的形式打印出来。 
  • -F 从指定的文件中读取表达式,忽略命令行中给出的表达式。 
  • -i 指定监听的网络接口。 
  • -l 使标准输出变为缓冲行形式,可以把数据导出到文件。 
  • -L 列出网络接口的已知数据链路。 
  • -m 从文件module中导入SMI MIB模块定义。该参数可以被使用多次,以导入多个MIB模块。 
  • -M 如果tcp报文中存在TCP-MD5选项,则需要用secret作为共享的验证码用于验证TCP-MD5选选项摘要(详情可参考RFC 2385)。 
  • -b 在数据-链路层上选择协议,包括ip、arp、rarp、ipx都是这一层的。
  • -n 不把网络地址转换成名字。
  • -nn 不进行端口名称的转换。
  • -N 不输出主机名中的域名部分。例如,‘nic.ddn.mil‘只输出’nic‘。 
  • -t 在输出的每一行不打印时间戳。 
  • -O 不运行分组分组匹配(packet-matching)代码优化程序。 
  • -P 不将网络接口设置成混杂模式。 
  • -q 快速输出。只输出较少的协议信息。 
  • -r 从指定的文件中读取包(这些包一般通过-w选项产生)。 
  • -S 将tcp的序列号以绝对值形式输出,而不是相对值。 
  • -s 从每个分组中读取最开始的snaplen个字节,而不是默认的68个字节。 
  • -T 将监听到的包直接解释为指定的类型的报文,常见的类型有rpc远程过程调用)和snmp(简单网络管理协议;)。 
  • -t 不在每一行中输出时间戳。 
  • -tt 在每一行中输出非格式化的时间戳。 
  • -ttt 输出本行和前面一行之间的时间差。 
  • -tttt 在每一行中输出由date处理的默认格式的时间戳。 
  • -u 输出未解码的NFS句柄。 
  • -v 输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息。 
  • -vv 输出详细的报文信息。 
  • -w 直接将分组写入文件中,而不是不分析并打印出来。

1. dd命令

dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。

注意:指定数字的地方若以下列字符结尾,则乘以相应的数字:b=512;c=1; k=1024;w=2

参数注释:

  1. if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >
  2. of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >
  3. ibs=bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。
    obs=bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。
    bs=bytes:同时设置读入/输出的块大小为bytes个字节。
  4. cbs=bytes:一次转换bytes个字节,即指定转换缓冲区大小。
  5. skip=blocks:从输入文件开头跳过blocks个块后再开始复制。
  6. seek=blocks:从输出文件开头跳过blocks个块后再开始复制。
    注意:通常只用当输出文件是磁盘或磁带时才有效,即备份到磁盘或磁带时才有效。
  7. count=blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。
  8. conv=conversion:用指定的参数转换文件。
    • ascii:转换ebcdic为ascii
    • ebcdic:转换ascii为ebcdic
    • ibm:转换ascii为alternate ebcdic
    • block:把每一行转换为长度为cbs,不足部分用空格填充
    • unblock:使每一行的长度都为cbs,不足部分用空格填充
    • lcase:把大写字符转换为小写字符
    • ucase:把小写字符转换为大写字符
    • swab:交换输入的每对字节
    • noerror:出错时不停止
    • notrunc:不截短输出文件
    • sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。

2. dd应用实例

1. 将本地的/dev/hdb整盘备份到/dev/hdd

$ dd if=/dev/hdb of=/dev/hdd

2. 将/dev/hdb全盘数据备份到指定路径的image文件

$ dd if=/dev/hdb of=/root/image

3. 将备份文件恢复到指定盘

$ dd if=/root/image of=/dev/hdb

4. 备份/dev/hdb全盘数据,并利用gzip工具进行压缩,保存到指定路径

$ dd if=/dev/hdb | gzip > /root/image.gz

5. 将压缩的备份文件恢复到指定盘

$ gzip -dc /root/image.gz | dd of=/dev/hdb

6. 备份与恢复MBR

备份磁盘开始的512个字节大小的MBR信息到指定文件:

$ dd if=/dev/hda of=/root/image count=1 bs=512

count=1指仅拷贝一个块;bs=512指块大小为512个字节。

恢复:

$ dd if=/root/image of=/dev/had

将备份的MBR信息写到磁盘开始部分

7. 备份软盘

$ dd if=/dev/fd0 of=disk.img count=1 bs=1440k (即块大小为1.44M)

8. 拷贝内存内容到硬盘

$ dd if=/dev/mem of=/root/mem.bin bs=1024 (指定块大小为1k)

9. 拷贝光盘内容到指定文件夹,并保存为cd.iso文件

$ dd if=/dev/cdrom(hdc) of=/root/cd.iso

10. 增加swap分区文件大小

第一步:创建一个大小为256M的文件:

$ dd if=/dev/zero of=/swapfile bs=1024 count=262144

第二步:把这个文件变成swap文件:

$ mkswap /swapfile

第三步:启用这个swap文件:

$ swapon /swapfile

第四步:编辑/etc/fstab文件,使在每次开机时自动加载swap文件:

$ /swapfile swap swap default 0 0

11. 销毁磁盘数据

$ dd if=/dev/urandom of=/dev/hda1

注意:利用随机的数据填充硬盘,在某些必要的场合可以用来销毁数据。

12. 测试硬盘的写速度

$ dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file

通过以上命令输出的命令执行时间,可以计算出硬盘的写速度。

13. 测试硬盘的读速度

$ dd if=/root/1Gb.file bs=64k | dd of=/dev/null

通过以上命令输出的命令执行时间,可以计算出硬盘的读速度。

14. 确定硬盘的最佳块大小

$ dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file
$ dd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file
$ dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file
$ dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file

通过比较以上命令输出中所显示的命令执行时间,即可确定系统最佳的块大小。

15. 修复硬盘

$ dd if=/dev/sda of=/dev/sda

或者

$ dd if=/dev/hda of=/dev/hda

当硬盘较长时间(一年以上)放置不使用后,磁盘上会产生magnetic flux point,当磁头读到这些区域时会遇到困难,并可能导致I/O错误。当这种情况影响到硬盘的第一个扇区时,可能导致硬盘报废。上边的命令有可能使这些数 据起死回生。并且这个过程是安全、高效的。

16. 利用netcat远程备份

$ dd if=/dev/hda bs=16065b | netcat < targethost-IP > 1234

在源主机上执行此命令备份/dev/hda

netcat -l -p 1234 | dd of=/dev/hdc bs=16065b

在目的主机上执行此命令来接收数据并写入/dev/hdc

$ netcat -l -p 1234 | bzip2 > partition.img
$ netcat -l -p 1234 | gzip > partition.img

以上两条指令是目的主机指令的变化分别采用bzip2、gzip对数据进行压缩,并将备份文件保存在当前目录。

17. 将一个很大的视频文件中的第i个字节的值改成0x41(也就是大写字母A的ASCII值)

$ echo A | dd of=bigfile seek=$i bs=1 count=1 conv=notrunc

3. /dev/null和/dev/zero的区别

  • /dev/null,外号叫无底洞,你可以向它输出任何数据,它通吃,并且不会撑着!它是空设备,也称为位桶(bit bucket)。任何写入它的输出都会被抛弃。如果不想让消息以标准输出显示或写入文件,那么可以将消息重定向到位桶。
  • /dev/zero,是一个输入设备,你可你用它来初始化文件。该设备无穷尽地提供0,可以使用任何你需要的数目——设备提供的要多的多。他可以用于向设备或文件写入字符串0。

Link: http://www.linuxde.net/2013/03/12928.html

在cmake mysql源码的时候出现下面的错误:


[ 46%] Building CXX object sql/CMakeFiles/sql.dir/geometry_rtree.cc.o
c++: internal compiler error: Killed (program cc1plus)
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
make[2]: *** [sql/CMakeFiles/sql.dir/geometry_rtree.cc.o] Error 4
make[1]: *** [sql/CMakeFiles/sql.dir/all] Error 2
make: *** [all] Error 2   

通过查找,[可能是因为内存不够的原因](https://bitcointalk.org/index.php?topic=304389.0),使用`free -h`查看了下,发现DO的主机连Swap分区都没有,Swap分区是当物理内存不够用的时候,把物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到物理内存中。Swap的调整对Linux服务器,特别是Web服务器的性能至关重要,通过调整Swap,有时可以越过系统性能瓶颈,节省系统升级的费用。   SWAP分区设置多大是我们需要关心的问题,关于设置的规则可以参考下面,实际情况可以根据业务需求进行调整,选择合适的Swap分区大小:

4G以内的物理内存,SWAP 设置为内存的2倍。
4-8G的物理内存,SWAP 等于内存大小。
8-64G 的物理内存,SWAP 设置为8G。
64-256G物理内存,SWAP 设置为16G。   接下来我们看下如何设置Swap分区。 ## 检查是否存在Swap分区   输入`swapon -s`,如果没有任何的信息显示,也就是还没有划分Swap分区。 ## 检查文件系统   如果没有创建Swap分区,再看下硬盘还剩下多少空间可以使用,使用`df`命令查看。因为我先创建了1G的Swap分区,还是报错,于是我选择创建一个2GB大小的Swap分区。 ## 创建Swap分区文件   创建swap文件。

dd if=/dev/zero of=/swapfile bs=2048 count=1M 

该命令将创建一个大小为2GB,文件名为swapfile的Swap分区文件,`of=/swapfile`参数指定了文件的创建位置和文件名;`bs=2048`指定了文件的大小,`count=1M`代表单位。 ## 格式化swap分区


mkswap /swapfile

激活swap分区

swapon /swapfile

查询swap分区

swapon -s 

你会发现在重启之后Swap分区就没了,那是因为上面的设置是一次性的,想要一直启动Swap分区,可以编辑fstab文件。

nano /etc/fstab   在最后一行添加上下面一条:


/swapfile     swap     swap     defaults     0  0   

添加成功后给swap赋予相关权限:

chown root:root /swapfile
chmod 0600 /swapfile ## 配置swappiness   实际上,并不是等所有的物理内存都消耗完毕之后,才去使用swap的空间,什么时候使用是由swappiness 参数值控制。

cat /proc/sys/vm/swappiness   默认值是60,swappiness=0 的时候表示最大限度使用物理内存,然后才是Swap空间;swappiness=100 的时候表示积极的使用Swap分区,并且把内存上的数据及时的搬运到swap空间里面。 ### 临时性修改

sysctl vm.swappiness=10
cat /proc/sys/vm/swappiness   这里我们的修改已经生效,但是如果我们重启了系统,又会变成60。 ### 永久修改   在`/etc/sysctl.conf`文件里添加如下参数:`vm.swappiness=10`,保存重启就可以了。

http://jeremybai.github.io/blog/2015/08/01/centos-creat-swap

搭建了多次vpn服务,从最早的使用pptp到现在的strongswan。从安全角度上来看,strongswan更安全,且目前的设备基本都已支持。关于strongswan更多的信息请参考官方网站

注意:此方法基于Ubuntu版本16.0.4(<= 16.0.4)及以下

部署及安装步骤:

1. 安装strongswan及相关组件

1.1   apt-get install -y strongswan

1.2  apt-get install -y strongswan-plugin-xauth-*

2.  配置strongswan服务

2.1  配置/etc/ipsec.secrets文件

# This file holds shared secrets or RSA private keys for authentication.
# RSA private key for this host, authenticating it to any other host
# which knows the public part.
x.x.x.x %any : PSK "ps-key"
user1 : XAUTH "password1"
user2 : XAUTH "password2"

注:其中x.x.x.x你服务器的公网IP地址;ps-key为共享密码;user1,user2分别为vpn登陆用户名;password1,password2分别为vpn登陆密码;以上信息请修改为你想设置的用户名及密码即可。

       2.2  配置/etc/ipsec.conf文件

# ipsec.conf - strongSwan IPsec configuration file
# basic configuration
config setup
    cachecrls=yes
    uniqueids=yes

conn ios
    keyexchange=ikev1
    authby=xauthpsk
    xauth=server
    left=%defaultroute
    leftsubnet=0.0.0.0/0
    leftfirewall=yes
    right=%any
    rightsubnet=192.168.5.0/24
    rightsourceip=192.168.5.1/24
    rightdns=8.8.8.8
    auto=add

3. 配置网络

3.1 网络转发(iptables)

iptables -t nat -A POSTROUTING -s 192.168.5.0/24 -o eth0 -j MASQUERADE

3.2 将如下命令写入/etc/rc.local

echo 1 > /proc/sys/net/ipv4/ip_forward
echo 8192 > /proc/sys/net/ipv4/tcp_max_syn_backlog
echo 40000 > /proc/sys/net/ipv4/tcp_max_tw_buckets
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
echo 1 > /proc/sys/net/ipv4/tcp_syncookies

4. 重启服务器即可

PS:如果不方便重启服务器,也可以使用如下命令:

sysctl net.ipv4.ip_forward=1

重启strongswan服务:service strongswan stop  && service strongswan start

因/synchrony-proxy/resources/js/vendor/sockjs.min.js等502 Bad Gateway加载不出来,导致无法使用编辑页的解决方法:关闭掉Synchrony proxy即可。

具体方法:
1. 编辑<home-directory>/confluence.cfg.xml

    <property name="synchrony.proxy.enabled">true</property>

修改为

    <property name="synchrony.proxy.enabled">false</property> 

2. 重启Confluence。

背景

当今互联网,数据呈现爆炸式增长,社交网络、移动通信、网络视频、电子商务等各种应用往往能产生亿级甚至十亿、百亿级的海量小文件。由于在元数据管理、访问性能、存储效率等方面面临巨大的挑战,海量小文件问题成为了业界公认的难题。

业界的一些知名互联网公司,也对海量小文件提出了解决方案,例如:著名的社交网站Facebook,存储了超过600亿张图片,专门推出了Haystack系统,针对海量小图片进行定制优化的存储。

白山云存储CWN-X针对小文件问题,也推出独有的解决方案,我们称之为Haystack_plus。该系统提供高性能数据读写、数据快速恢复、定期重组合并等功能。

Facebook的Haystack

Facebook的Haystack对小文件的解决办法是合并小文件。将小文件数据依次追加到数据文件中,并且生成索引文件,通过索引来查找小文件在数据文件中的offset和size,对文件进行读取。

Haystack的数据文件部分

Haystack的数据文件,将每个小文件封装成一个needle,包含文件的key、size、data等数据信息。所有小文件按写入的先后顺序追加到数据文件中。

Haystack的索引文件部分

Haystack的索引文件保存每个needle的key,以及该needle在数据文件中的offset、size等信息。程序启动时会将索引加载到内存中,在内存中通过查找索引,来定位在数据文件中的偏移量和大小。

Haystack面临的问题

Facebook的Haystack特点是将文件的完整key都加载到内存中,进行文件定位。机器内存足够大的情况下,Facebook完整的8字节key可以全部加载到内存中。

但是现实环境下有两个主要问题:

  1. 存储服务器内存不会太大,一般为32G至64G;
  2. 小文件对应的key大小难控制,一般选择文件内容的MD5或SHA1作为该文件的key。

场景举例

  • 一台存储服务器有12块4T磁盘,内存为32GB左右。
  • 服务器上现需存储大小约为4K的头像、缩略图等文件,约为10亿个。
  • 文件的key使用MD5,加上offset和size字段,平均一个小文件对应的索引信息占用28字节。
  • 在这种情况下,索引占用内存接近30GB,磁盘仅占用4TB。内存消耗近100%,磁盘消耗只有8%。

所以索引优化是一个必须要解决的问题。

Haystack_plus

Haystack_plus的核心也由数据文件和索引文件组成。

1. Haystack_plus的数据文件

与Facebook的Haystack类似,Haystack_plus将多个小文件写入到一个数据文件中,每个needle保存key、size、data等信息。

2. Haystack_plus的索引文件

索引是我们主要优化的方向:

  • 索引文件只保存key的前四字节,而非完整的key;
  • 索引文件中的offset和size字段,通过512字节对齐,节省1个字节;并根据整个Haystack_plus数据文件实际大小计算offset和size使用的字节数。

3. Haystack_plus的不同之处

数据文件中的needle按照key的字母顺序存放。

由于索引文件的key,只保存前四字节,如果小文件key的前四字节相同,不顺序存放,就无法找到key的具体位置。可能出现如下情况:

例如:用户读取的文件key是0x ab cd ef ac ee,但由于索引文件中的key只保存前四字节,只能匹配0x ab cd ef ac这个前缀,此时无法定位到具体要读取的offset。

我们可以通过needle顺序存放,来解决这个问题:

例如:用户读取文件的key是0x ab cd ef ac bb,匹配到0x ab cd ef ac这个前缀,此时offset指向0x ab cd ef ac aa这个needle,第一次匹配未命中。

通过存放在needle header中的size,我们可以定位0x ab cd ef ac bb位置,匹配到正确needle,并将数据读取给用户。

4. 索引搜索流程为

5. 请求不存在的文件

问题:我们应用折半查找算法在内存查找key,时间复杂度为O(log(n)),其中n为needle数目。索引前缀相同时,需要在数据文件中继续查找。此时访问的文件不存在时,容易造成多次IO查找。

解决方法:在内存中,将存在的文件映射到bloom filter中。此时只需要通过快速搜索,就可以排除不存在的文件。

时间复杂度为O(k),k为一个元素需要的bit位数。当k为9.6时,误报率为1%,如果k再增加4.8,误报率将降低为0.1%。

6. 前缀压缩,效果如何

Haystack_plus与Facebook Haystack内存消耗的对比,场景举例,文件(如:头像、缩略图等)大小4K,key为MD5:

内存消耗对比

Key

offset

size

Haystack

全量key,16字节

8字节

4字节

Haystack_plus

4字节

4字节

1字节

注:Haystack的needle为追加写入,因此offset和size大小固定。Haystack_plus的key使用其前4字节,offset根据Haystack_plus数据文件的地址空间计算字节数,并按512字节对齐;size根据实际文件的大小计算字节数,并按512对齐。

从上图可以看出在文件数量为10亿的情况下,使用Facabook的Haystack消耗的内存超过26G,使用Haystack_plus仅消耗9G多内存,内存使用降低了2/3。

7.索引优化根本就停不下来

10亿个4K小文件,消耗内存超过9G。Key占用4字节,Offset占用4字节,还需要再小一些。

索引分层

根据文件key的前缀,进行分层,相同的前缀为一层。

分层的好处

减少key的字节数

通过分层,只保存一份重复的前缀,节省key的字节数。

减少offset的字节数

优化前的offset,偏移范围为整个Haystack_plus的数据文件的地址空间。

优化后,只需在数据文件中的层内进行偏移,根据最大的层地址空间可以计算所需字节数。

分层后的效果

从上图可以看出,进行分层后,内存消耗从优化前的9G多,降低到4G多,节省了一半的内存消耗。

Haystack_plus整体架构

1. Haystack_plus组织

每台服务器上,我们将所有文件分成多个group,每个group创建一个Haystack_plus。系统对所有的Haystack_plus进行统一管理。

读、写、删除等操作,都会在系统中定位操作某个Haystack_plus,然后通过索引定位具体的needle,进行操作。

2. 索引组织

之前已经介绍过,所有needle顺序存放,索引做前缀压缩,并分层。

3. 文件组成

  • chunk文件:小文件的实际数据被拆分保存在固定数量的chunk数据文件中,默认为12个数据块;
  • needle list文件:保存每个needle的信息(如文件名、offset等);
  • needle index和layer index文件:保存needle list在内存中的索引信息;
  • global version文件:保存版本信息,创建新version时自动将新版本信息追加到该文件中;
  • attribute文件:保存系统的属性信息(如chunk的SHA1等);
  • original filenames:保存所有文件原始文件名。

A、Haystack_plus数据文件被拆分为多个chunk组织,chunk1,chunk2,chunk3……

B、分成多个chunk的好处:

1. 数据损坏时,不影响其它chunk的数据;

2. 数据恢复时,只需恢复损坏的chunk。

C、每个chunk的SHA1值存放在attribute文件中。

4. 版本控制

由于needle在数据文件中按key有序存放,为不影响其顺序,新上传的文件无法加入Haystack_plus,而是首先被保存到hash目录下,再通过定期自动合并方式,将新文件加入到Haystack_plus中。

合并时将从needle_list文件中读取所有needle信息,将删除的needle剔除,并加入新上传的文件,同时重新排序,生成chunk数据文件、索引文件等。

重新合并时将生成一个新版本Haystack_plus。版本名称是所有用户的文件名排序的SHA1值的前4字节。

每半个月系统自动进行一次hash目录检查,查看是否有新文件,并计算下所有文件名集合的SHA1,查看与当前版本号是否相同,不同时说明有新文件上传,系统将重新合并生成新的数据文件。

同时,系统允许在hash目录下超过指定的文件数时,再重新创建新版本,从而减少重新合并次数。

版本的控制记录在global_version文件中,每次创建一个新版本,版本号和对应的crc32将追加到global_version文件(crc32用于查看版本号是否损坏)。

每次生成新版本时,自动通知程序重新载入索引文件、attribute文件等。

5. 数据恢复

用户的文件将保存成三副本存放,因此Haystack_plus也会存放在3台不同的机器上。

恢复场景一

当一个Haystack_plus的文件损坏时,会在副本机器上,查找是否有相同版本的Haystack_plus,如果版本相同,说明文件的内容都是一致,此时只需将要恢复的文件从副本机器下载下来,进行替换。

恢复场景二

如果副本机器没有相同版本的Haystack_plus,但存在更高版本,那此时可以将该版本的整个Haystack_plus从副本机器上拷贝下来,进行替换。

恢复场景三

如果前两种情况都不匹配,那就从另外两台副本机器上,将所有文件都读到本地上的hash目录下,并将未损坏的chunk中保存的文件也提取到hash目录下,用所有文件重新生成新版本的Haystack_plus。

Haystack_plus效果如何

在使用Haystack_plus后一段时间,我们发现小文件的整体性能有显著提高,RPS提升一倍多,机器的IO使用率减少了将近一倍。同时,因为优化了最小存储单元,碎片降低80%。

使用该系统我们可以为用户提供更快速地读写服务,并且节省了集群的资源消耗。

Link: http://www.infoq.com/cn/articles/solution-of-massive-small-files