1.双副本介绍
1.1 什么是双副本?
1.2 双副本的优越性
1.3 双副本的缺陷
2.Glusterfs双副本在虚拟化中的应用
3.Glusterfs双副本实现过程
3.1 同步写操作
1.对要写入的文件进行加锁操作,先尝试加上非阻塞锁,如果失败去掉之前加的非阻塞锁,加上阻塞锁。
原因:避免同时的更新,避免写和自修复的冲突,多个客户端的冲突。
2.在文件副本上标记“changelog”(扩展属性),表示pending write,这并不是真正的log,而是一个计数数组,在pre op操作中设置所有节点pending状态置位为1,上传到brick,将对应的文件的扩展属性加1。
3.在所有的副本上执行实际的写操作。
4.在op操作后将正常活着的节点对应的pending状态置为-1,其他为0,上传到brick,将对应的文件扩展属性进行减1或0。
5.当所有节点写操作和changelog减少完成时,释放锁。
Glusterfs写操作技巧点:
如果另一个写在执行则跳过changelog增加,同样的当前者的写操作完成时,略过changelog的减少。这被称为“changelog piggbacking”,因为这样让第二个写操作骑在(‘ride along”)第一个写操作的changelog增加上。
当写重叠(overlap)时忽略掉unlock和之后的lock,这被称为“eager locking”,它和change piggybacking类似,除了它是对lock 操作而不是changlog操作的优化。
使用了以上优化算法,最优的情况下一次写操作的网络通信次数可以从5次减少到1次,只剩下1次写操作。一般情况下write-behind在nfs服务端进程默认是打开的,使得这种访问模式更容易发生,另外,write-behind的缓冲机制(默认为1M)也很大的优化了写操作。
3.2 修复过程
3.2.1 触发事件
1.Heal进程检查到有节点上线,也就是child xlator重新连接上brick。
2.Glusterd命令操作。
3.写入操作。
4.第一次进入某个目录。
5.Heal进程启动定时器,默认10分钟检查同步。
6.……
3.2.2 修复内容
1.Metadata:元数据
2.Data:数据内容
3.Entry:目录项
3.2.3 修复模式
1.INDEX:一般默认修复模式,对应目录项修复不作深入递归修复。
2.INDEX_TO_BE_HEALED:
3,FULL:递归进行修复。
3.2.4 INDEX模式修复步骤简述
1.判断是否有另一个修复过程存在,如果存在,则退出;
2.创建一个event事件。
3.在INDEX模式下,需要修复的文件都存储在brick上index xlator对应的路径下,通过设置标记GF_XATTROP_INDEX_GFID和getxattr操作获取index对应的index gfid。
4.通过index gfid查找或创建一个inode附着于dir_loc中,通过lookup操作获取iattr,通过iattr->gfid更新dir_loc中的inode,到此,拿到了需要修复文件所在的目录对应的gfid。
5.通过更新后的dir_loc查找fd,如果查找不到通过dir_loc->inode创建一个index_fd。
6.通过index_fd进行read_dir操作,获取到需要修复的文件列表,存入链表,需要注意的是这里并不是一次性获取全部的文件,而是通过该offset作为标志,循环每次获取一部分的文件。
7.有了文件列表,逐步的对一个一个文件进行修复。
8.从文件链表中取出文件,通过文件的gfid查找或创建inode,并将inode关联到loc上,设置字典xdata的"attempt-self-heal"值为1,表示要进行修复,进行afr_lookup操作,获取两边brick的文件属性,类型等iattr信息,字典数据等信息,字典里可能包含了meta,data,entry的状态信息。
9.afr_lookup_cbk回调函数中判断前面步骤设置需要修复,这时候开始就进行修复了。
10.我们知道修复一个inode文件(这里所说的文件也包含了文件夹,ext2,ext3之后,把文件夹也算作一个inode,只是ia_type文件类型进行区分)可能需要修复meta,data,entry,但是照成这些不一致的可能性有多种,例如有一个节点文件没写完,文件破损,文件不存在,或者说两边brick相同路径下的文件的gfid却不一样,或者说两个文件的ia_type不一样,也就是文件类型不一样,等等。
11.接下来就是通过两边brick的lookup操作返回的信息确定需要进行哪些修复并设置,需要注意的事如果有一个节点返回值是-1的话,默认全部需要修复,这里的修复类型有:
1.do_data_self_heal:
2.do_metadata_self_heal:
3.do_entry_self_heal:
上面三个的情况比较多,例如可能是文件权限不同,文件拥有者不同,文件大小不同,文件类型不同,或者文件扩展属性里changelog的那三个字段数据不匹配规则,这里偷懒下,先不说了,先说下下面两个更不常见的。
4.do_gfid_self_heal:brick返回成功,但是获取iattr->ia_gfid却为null,照成这种错误的应用场景是什么呢?谁想到了告诉我下。
5.do_missing_entry_self_heal:两边brick都返回成功,但是获取iattr->ia_gfid却不相等,这样的应用场景比较好想到,例如一个节点1掉线,节点2创建了一个文件,节点2掉线,节点1上线,节点1创建了一个相同路径和名字的文件,导致通过文件却不同的gfid,这种情况很有可能脑裂了。
12.通过上面的设置,接下判断是否需要metadata的修复,如果需要元数据修复,先判断是否元数据脑裂,这里判断元数据是否脑裂的依据比较简单,简而言之,一句话:通过一定规则是否可以创建和确定metadata修复的source,确定不了就说明脑裂了。
13. Glusterfs这样获取source的,首先根据child的个数n创建一个n维数组矩阵matrix[n][n],每一维数组存储的事对应的brick通过lookup返回changelog的关于meta的数据段的值,上面有讲到brick的lookup操作会返回字典xdata,而字典里面存有文件changelog扩展属性,可以通过pending_key[j](trust.gfid.clie