glusterfs dht 层lookup 时lookupeverywhere 分析

glusterfs7 多次扩容后出现重复文件分析

背景

最近在做glusterfs7版本扩容操作测试的时候,发现偶尔会出现,文件丢失然后再重新创建文件会出现文件重复的现象。具体操作为 从一个节点扩容到10个节点,3副本,添加一个节点操作为probe node–>add-brick–>replace-brick–>rebalance-fix-layout, 添加至10个节点后,删除第1个节点,操作为:replace-brick–>detach node。fuse客户端操作,stat file,若file 不存在 则touch file,就有可能出现 两个重复的file 文件。

原理分析

glusterfs文件分布是同一个一致性hash 算法hash分布的,正常情况下我们查找一个文件,只需要在它的hash 节点上查找即可,如果查找不到就说明文件不存在。但是当glusterfs扩容或者缩减节点的时候hash分布会发生变化会导致查找一个文件可能不在它的hash 节点就需要lookupeverywhere 到所有节点上去查找,当做完rebalance 后修复目录了hash布局,就又可以只在hash节点上查找了,无需lookupeverywhere 。

经原理分析,很可能是扩容后,做了rebalance fix-layout,文件在原来的hash分布节点上,而新的hash 分布节点上没有,而dht 层在做lookup的时候没有去所有节点上查找,所以stat 不到文件,然后就在新的hsah 节点上创建了文件,然后对文件目录做ls 就会出现重复的文件。

源码分析

lookupeverywhere 条件判断

在dht 层dht_lookup_cbk 中如果在hash 节点查找文件返回不存在则通过dht_should_lookup_everywhere 函数判断是否是否要去所有hash 节点做lookup。

 if (!conf->defrag && loc->parent) {
            ret = dht_inode_ctx_layout_get(loc->parent, this, &parent_layout);
            if (!ret && parent_layout &&
            //父目录的commit_hash 值和conf的vol_commit_hash 值比较,不相等则lookup everywhere 
                (parent_layout->commit_hash == conf->vol_commit_hash)) {
                lookup_everywhere = _gf_false;
            }
        }

parent_layout->commit_hash 来源:

在dht_disk_layout_merge 函数体现,即父目录的扩展属性trused.glusterfs.dht 值的高位32位。

conf->vol_commit_hash 来源:

在dht_revalidate_cbk 函数体现,获取来自于brick 目录的扩展属性trusted.glusterfs.dht.commithash 值。

lookupeverywhere条件分析

parent_layout->commit_hash 值变化点:

(1)parent_layout->commit_hash (trused.glusterfs.dht)的高位32位 在目录创建的时候与brick 的conf->vol_commit_hash(trusted.glusterfs.dht.commithash) 值相同。

(2)在集群做reblance 时候会被修复为与brick 的conf->vol_commit_hash(trusted.glusterfs.dht.commithash) 值一样。

conf->vol_commit_hash 值变化点:

(1)做rebalance 的时候,glusterd 进程会生成commit hash 值 启动 rebalance进程会以参数的形式传递,rebalance 进程会设置所有brick 目录的扩展属性(trusted.glusterfs.dht.commithash)为commit hash值。

背景问题原因

在做rebalance fix layout 的时候,glusterd 进程给rebalance进程传递的commit hash 参数值为0,导致 conf->vol_commit_hash 为0与未add-brick 前创建的目录的扩展属性(trusted.glusterfs.dht.commithash)高位32位也为0 相等。导致fuse 客户端访问目录时候就会发现一些文件不存在,因为add-brick hash 范围变了,所以在hash 节点找不到文件,又没有触发 lookupeverywhere 条件,所以文件找不到,然后创建了相同的文件落在了hash 节点上。ls 目录的时候,就把两个文件都读到了,致使出现重复文件。

背景问题解决

解决办法有两种:

1.注释掉dht_should_lookup_everywhere 函数里面的commit hash 值判断,只要在hash 节点looup 返回不存在 就执行lookupeverywhere 。这个解决办法有点暴力,会导致查找判断一个不存在的文件变慢(因为多了一次lookupeverywhere )。

2.找到glusterd 进程给rebalance进程传递的commit hash 参数值为0的bug。这个是最佳解决办法。

总结

glusterfs 分布式文件系统查找文件是在hash 节点上查找,但是扩容和缩减后hash 分布变化后,通过文件父目录的扩展属性(trusted.glusterfs.dht.commithash)高位32位值和brick 目录的扩展属性(trusted.glusterfs.dht.commithash)值来判断如果文件不在hash节点是否需要去所有节点查找文件。这样来优化了文件的查找。这也得出结论扩容和缩减后只做fix-layout,以前的老目录查找文件如果文件不在hash 节点就需要去所有节点查找,做rebalance后所有文件查找就只会在hash 节点查找。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章