专栏首页邵靖的专栏GlusterFS的数据分布(DHT)和文件副本(AFR)机制
原创

GlusterFS的数据分布(DHT)和文件副本(AFR)机制

GlusterFS简介

GlusterFS是一种分布式文件系统,项目中使用它作为数据文件冷备存储后台。GlusterFS的技术特点是采用无元数据中心的架构,采用Xlator以调用栈的形式组织各功能模块,Xlator之间通过RPC进行通信,客户端与服务端共用某些Xlator,下图就是Gluster客户端与服务端的Xlator栈示意图。

image.png

GlusterFS的部署模式

Distributed Volume 分布式卷

image.png

无冗余

Replicated Volume 副本卷

image.png

RAID-1

Striped Volume 条带卷

image.png

RAID-0

Distributed Replicated Volume 分布式副本卷

image.png

Distributed Striped Volume 分布式条带卷

image.png

由于GlusterFS采用了Xlator的架构,所以Distributed Replicated Volume在代码结构上是Distributed Xlator和Replicated Xlator的组合,Distributed Striped Volume类似。

GlusterFS的使用方式

  • FUSE方式 (mount -t glusterfs)
  • NFS方式 (mount -t nfs)
  • libgfapi方式

下图是FUSE模式下的GlusterFS I/O流

image.png

GlusterFS数据分布DHT

GlusterFS的分布式哈希表(Distributed Hash Tables DHT)机制是数据分布的核心,以目录作为文件分布的基本单位。

  • 当用户在挂载点内创建目录dir0,目录会在所有brick生成
  • GlusterFS将每个目录的哈希地址空间规定为0x00000000~0xffffffff的32位整数区间,然后按每个brick分割成一组连续的地址空间,每个brick对应的地址区间 (Layout)保存在对应目录的扩展文件属性(xattr)中
    • 扩展属性是文件系统提供的一个功能,通过Key-Value的方式将一些元数据信息同文件本体或目录存储在一起
    • Glusterfs能够通过brick的大小,对不同的brick分配不同大小的layout
  • 当在dir0目录下写文件时,根据所在目录GFID和文件名作为输入参数,通过D-M算法计算哈希值
  • 通过文件的哈希值确定文件位于哪一个brick
image.png
  • 如果创建其他目录dirx,那么会重新生成这个目录在每个brick上的划分区间,存储在扩展属性中(分布元数据保存在文件及目录中,体现去中心化),如果在目录dir0中再创建下级目录dir0/sub-dir1,类似6,会生成自己的哈希分布空间
  • Hash算法有一定概率,极端情况下会出现brick之间分布不均的情况,此时GlusterFS采用链接解决这种问题,文件读写时,客户端会先到源brick查找文件如果读取到的文件是链接形式,则通过文件的扩展属性定位到真实的brick,然后客户端会直接在真实brick读写文件。
image.png
  • 扩容,GlusterFS的扩容有两个步骤
    • 添加brick,现有的目录分布不会扩展到新brick;旧文件不会迁移到新brick;在现有的目录分布下创建新文件不会写到新brick
    • Reblance,修复现有的目录hash分布(Fix-Layout)并扩展到新brick;部分文件开始迁移到新brick(Migrate-Data);新创建的文件按照新的哈希分布确定存储位置。Gluster挂载目录(root)开始,深度优先遍历策略修复所有目录。
  • 缩容
    • 重新计算缩容后的hash分布,将被缩容brick的数据迁走,将被缩容brick从卷中摘除
image.png

分布式副本卷的数据读写

  • 写:采用一个文件同时写入多个副本的模式,当有一个副本成功写入就返回成功
    • 数据写入过程中,可能会发生有副本写入失败的情况
    • 更有甚者,各副本之间会发生脑裂(brain-split)
image.png
  • 读:从多个镜像副本中选取一个状态为正常的读取
    • 多个副本之中只要有一份是正常的,都可以正确读取
image.png

操作示例

  1. 创建一个replicate为2,共有6个brick的distributed replicate卷,数据目录分别为 /brick1~/brick6
  2. 挂载目标卷 /data/mount
  3. 创建目录 /data/mount/test,此时分别会生成/brick1/test~/brick6/test的文件目录,每个目录的扩展属性中记录了本test目录在本brick的hash分布区间
  4. 对于test目录,6个brick会分成3组,每组两个brick有着相同的分布区间,每组将存储相同的文件互为备份。
image.png
image.png

GlusterFS自动文件副本(AFR)

  • GlusterFS的自动文件副本(Automatic File Replication AFR)机制是实现Gluster故障恢复,自修复等高可用功能的基础。
  • GlusterFS利用文件/目录的扩展属性存储元数据信息(以trusted.afr开头)
  • 文件写入流程(from GlusterFS v3.7)一个完整的AFR Transaction
    • 下发Write操作
    • 文件加锁Lock
    • Pre-op设置文件扩展属性,changelog+1
    • 文件写入
    • Post-op如果写入成功,changelog-1, 如果失败就保持此属性
    • 解锁UnLock

扩展属性是由一个24位的十六进制数字构成,被分为三个8位十六进制段

  • 1-8位是数据内容(data)changelog
  • 9-16位是元数据(metadata)changelog
  • 17-24位是目录项(entry)changelog
image.png

下面是两副本文件写入属性变化示意图:

  • Pre-OP前
    image.png
  • 数据写入中
    image.png
  • 写入成功
    image.png
  • 副本b写入失败
    image.png
  • 数据写入Transaction完成后根据扩展属性changelog,文件存在以下几种状态:
    • WISE – 自身changelog全零,其他副本changelog非零
    • INNOCENT – 自身和其他changelog全为零
    • FOOL – 自身changelog非零
    • IGRANT – changelog丢失
    • 副本都为WISE – 脑裂 典型场景:数据写入时,brick-x服务宕机(进程停止、网络断连、系统卡死…),一段时间之后又恢复
  • Self-healing触发条件
    • Self-heal进程周期扫描 bricks/.glusterfs/indices/xattrop/目录
    • 目标文件访问
    • 通过命令 gluster volume heal <VOLNAME>
  • 当出现单个副本WISE,一般将WISE副本作为修复源节点,覆盖FOOL副本,并修改扩展属性

GlusterFS脑裂

  • 如果文件写入后,不同副本changelog都保持WISE状态(副本互相指责对方出现错误),这种情况即发生了脑裂(Brain Split)
  • 脑裂可能出现的典型场景(replica 2为例)
    • 文件X副本XA,XB分别位于svr1、svr2,分别由proc-a和proc-b进程管理,若客户端对X的写入过程中svr1,svr2间网络中断,那么proc-a和proc-b将分别负责各自副本的写入但看到的对方都异常,当网络恢复即发生脑裂
    • Svr1掉线,Svr2创建了一个文件,Svr2掉线,Svr1上线,Svr1创建了一个相同路径和名字的文件
  • 读取脑裂的文件会出现 Input/Output Error
  • 因为Changelog有三段,分别对应三种类型数据的状态,所以脑裂也有三种类型
    • Data脑裂 – 副本之间数据内容不一致
    • Metadata脑裂 – 副本之间元数据(文件权限,所属组,文件类型等)不一致
    • Entry/GFID脑裂 – 副本之间GFID不一致(无法使用命令行方法修复,需要手工介入)
  • 脑裂如何修复(GlusterFS > 3.3)人工介入通过一定策略选择正确的副本
  • 在GlusterFs集群节点上,通过命令行方式修复
    • 选择文件比较大的文件为正确副本
    • 选择修改时间mtime靠后的作为正确副本
    • 强制指定副本作为正确副本
  • 在挂载点,通过命令修复
  • 手工修复 https://docs.gluster.org/en/latest/Troubleshooting/resolving-splitbrain/
  • 如何预防脑裂
    • Client-Quorum机制,采用3个副本,3个副本写成功2个才返回成功(存储成本上升)
    • Arbiter Volume,采用3个brick,其中有一个特殊的副本仅存储元数据和目录结构信息

参考文献

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用 Apache PIG 统计积累型数据的差值

    线上运行的生产系统会定时采集一项丢包数据,这项数据与某个进程相关联,从进程启动开始就一直递增,每隔1分钟采集一次数据,当进程重启之后,这项数据会清零。现在要求使...

    邵靖
  • Python 字符串子串定位性能比较

    本文想探讨的是在给定了key字段在字段列表中开始下标和key字段个数后,如何在整行字符串中定位到key字符串的起始位置。

    邵靖
  • 一个基于 Docker 的负载均衡实例

    本文目地主要是给大家简单安利一下目前最火的容器产品 Docker 及其所涉及的相关技术,并通过一个实际例子演示一下容器技术的典型应用场景。

    邵靖
  • “无法从http://XXX/XXX.svc?wsdl获取元数据”错误的解决方法

    理解了文档内容,但无法进行处理。   - WSDL 文档包含无法解析的链接。   - 下载“http://admin-pc/IISHostService/Ser...

    跟着阿笨一起玩NET
  • 【JAVA零基础入门系列】Day2 Java集成开发环境IDEA

      开发环境搭建好之后,还需要一个集成开发环境也就是IDE来进行编程。这里推荐的IDE是IDEA,那个老掉牙的Eclipse还是先放一边吧,(手动滑稽)。   ...

    弗兰克的猫
  • 实现iOS图片等资源文件的热更新化(一): 从Images.xcassets导出合适的图片

    本文会基于一个已有的脚本工具自动导出所有的图片;最终给出的是一个从 Images.xcassets 到基于文件夹的精简 合适 的图片资源集的完整过程.难点在于从...

    ios122
  • 查找低效的sql语句

    SELECT  EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUF...

    阿新
  • python: mongodb应用示例

    1. 下载MongoDB http://downloads.mongodb.org/win32/mongodb-win32-i386-3.2.12.zip

    py3study
  • Python解决小需求--网站在线听歌歌词同步到本地

    喜欢工作时听歌,但又想知道唱的是什么,也就是看见歌词,但又要轻量级,不下载客户端音乐软件,于是在豆瓣FM,网易云音乐等在线音乐网站上听歌。

    MiaoGIS
  • centos 7 安装VCL播放器

    centos 自带播放器MP4都无法播放,因此安装VCL播放器 安装epel和remi的repository sudo yum localinstall --n...

    用户1680321

扫码关注云+社区

领取腾讯云代金券