GlusterFS数据存储脑裂修复方案最全解析

本文档介绍了glusterfs中可用于监视复制卷状态的heal info命令以及解决脑裂的方法

一. 概念解析

常见术语

名称 解释
Brick GlusterFS 的基本存储单元,由可信存储池中服务器上对外输出的目录表示。存储目录的格式由服务器和目录的绝对路径构成 SERVER:EXPORT
Volume 一个卷,在逻辑上由N个bricks组成
Fuse Unix-like OS上的可动态加载的模块,允许用户不用修改内核即可创建自己的文件系统
Glusterd Gluster management daemon,glusterfs 后台进程,运行在所有Glusterfs 节点上
CLI Command LineInterface 控制台,命令行界面
AFR Automatic FileReplication 自动文件复制
GFID glusterfs内部文件标识符,是一个uuid,每个文件唯一
ReplicateVolume 副本卷
Client 客户端,挂载服务端的存储
Server 存储节点服务器,存储数据的位置

1.1 什么是脑裂

脑裂是指文件的两个或多个复制副本内容出现差异的情况。当文件处于脑裂状态时,副本的brick之间文件的数据或元数据不一致,此时尽管所有brick都存在,却没有足够的信息来权威地选择一个原始副本并修复不良的副本。对于目录,还存在一个条目脑裂,其中内部的文件在副本的各个brick中具有不同的gfid文件类型;当Gluster AFR无法确定复制集中哪个副本是正确时,此时将会产生脑裂。

1.2 脑裂类型

  • 数据脑裂:文件中的数据在副本集中的brick上不同;
  • 元数据脑裂:brick上的元数据不同;
  • 条目裂脑:当文件在每个副本对上具有不同的gfid时,会发生这种情况;此时是不能自动治愈的。

1.3 查看脑裂信息

gluster volume heal <VOLNAME> info

此命令将会列出所有需要修复的文件(并由self-heal守护进程处理)。执行以后将会输出文件路径或者GFID。

heal info命令原理概述

当调用此命令时,将生成一个glfsheal进程,该进程将读取/<brick-path>/.glusterfs/indices/下的各个子目录中(它可以连接到的)所有brick条目;这些条目是需要修复文件的gfid;一旦从一个brick中获得GFID条目,就根据该文件在副本集和trusted.afr.*扩展属性的每个brick上进行查找,确定文件是否需要修复,是否处于脑裂或其他状态。

命令输出示例

[root@gfs ~]# gluster volume heal test info
Brick \<hostname:brickpath-b1>
<gfid:aaca219f-0e25-4576-8689-3bfd93ca70c2> - Is in split-brain
<gfid:39f301ae-4038-48c2-a889-7dac143e82dd> - Is in split-brain
<gfid:c3c94de2-232d-4083-b534-5da17fc476ac> - Is in split-brain
<gfid:6dc78b20-7eb6-49a3-8edb-087b90142246>

Number of entries: 4

Brick <hostname:brickpath-b2>
/dir/file2
/dir/file1 - Is in split-brain
/dir - Is in split-brain
/dir/file3
/file4 - Is in split-brain
/dir/a

Number of entries: 6
命令输出解释

此命令输出中列出的所有文件都需要修复;列出的文件将会附带以下标记:

1)Is in split-brain

数据或元数据脑裂的文件将在其路径/GFID后面附加ls in split-brain,例如,对/file4文件的输出;但是,对于GFID脑裂中的文件,文件的父目录显示为脑裂,文件本身显示为需要修复,例如,上面的/dir为文件/dir/a的GFID脑裂。脑裂中的文件如果不解决脑裂问题就无法自愈。

2) Is possibly undergoing heal

运行heal info命令时,将会锁定存储中的每个文件,以查找是否需要修复。但是,如果自我修复守护程序已经开始修复文件,则它将不会被glfsheal锁定。在这种情况下,它将会输出此消息。另一个可能的情况是多个glfsheal进程同时运行(例如,多个用户同时运行heal info命令)并争夺相同的锁。

示例

我们使用两块brick b1和b2在复制卷test上;关闭self heal守护程序,挂载点为/mnt。

# gluster volume heal test info
Brick \<hostname:brickpath-b1>
<gfid:aaca219f-0e25-4576-8689-3bfd93ca70c2> - Is in split-brain
<gfid:39f301ae-4038-48c2-a889-7dac143e82dd> - Is in split-brain
<gfid:c3c94de2-232d-4083-b534-5da17fc476ac> - Is in split-brain
<gfid:6dc78b20-7eb6-49a3-8edb-087b90142246>

Number of entries: 4

Brick <hostname:brickpath-b2>
/dir/file2
/dir/file1 - Is in split-brain
/dir - Is in split-brain
/dir/file3
/file4 - Is in split-brain
/dir/a

Number of entries: 6
输出结果分析

brick b1,有四项需要修复:

1)gfid为6dc78b20-7eb6-49a3-8edb-087b90142246的文件需要修复
2)aaca219f-0e25-4576-8689-3bfd93ca70c2
39f301ae-4038-48c2-a889-7dac143e82ddc3c94de2-232d-4083-b534-5da17fc476ac 处于脑裂状态

brick b2,有六项需要修复:

1)afile2file3需要修复
2)file1file4/dir处于脑裂状态

二. 修复脑裂

命令语句

gluster volume heal <VOLNAME> info split-brain

输出结果示例

# gluster volume heal test info split-brain
Brick <hostname:brickpath-b1>
<gfid:aaca219f-0e25-4576-8689-3bfd93ca70c2>
<gfid:39f301ae-4038-48c2-a889-7dac143e82dd>
<gfid:c3c94de2-232d-4083-b534-5da17fc476ac>
Number of entries in split-brain: 3

Brick <hostname:brickpath-b2>
/dir/file1
/dir
/file4
Number of entries in split-brain: 3

注意,heal info命令,对于GFID split brains(相同的文件名但不同的GFID)
他们的父目录处于脑裂中状态。

2.1 使用gluster命令行工具解决脑裂问题

一旦确定了脑裂中的文件,就可以使用多种策略从gluster命令行完成其修复。此方法不支持Entry/GFID脑裂修复;可以使用以下策略来修复数据和元数据脑裂:

2.1.1 选择较大的文件作为源文件

此命令对于已知/确定要将较大的文件视为源文件的文件修复非常有用。

gluster volume heal <VOLNAME> split-brain bigger-file <FILE>

在这里,<FILE>可以是从卷的根目录中看到的完整文件名(也可以是文件的GFID字符串),一旦执行此命令,将会使用最大的<FILE>副本,并以该brick作为源完成修复。

示例:

在修复文件之前,需注意文件大小和md5校验和:

在brick b1:

[brick1]# stat b1/dir/file1
  File: ‘b1/dir/file1’
  Size: 17              Blocks: 16         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 919362      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-03-06 13:55:40.149897333 +0530
Modify: 2015-03-06 13:55:37.206880347 +0530
Change: 2015-03-06 13:55:37.206880347 +0530
 Birth: -
[brick1]#
[brick1]# md5sum b1/dir/file1
040751929ceabf77c3c0b3b662f341a8  b1/dir/file1

在brick b2:

[brick2]# stat b2/dir/file1
  File: ‘b2/dir/file1’
  Size: 13              Blocks: 16         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 919365      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-03-06 13:54:22.974451898 +0530
Modify: 2015-03-06 13:52:22.910758923 +0530
Change: 2015-03-06 13:52:22.910758923 +0530
 Birth: -
[brick2]#
[brick2]# md5sum b2/dir/file1
cb11635a45d45668a403145059c2a0d5  b2/dir/file1

使用以下命令修复file1:

gluster volume heal test split-brain bigger-file /dir/file1

修复完成后,两个brick上的md5校验和和文件大小应该相同。

在brick b1查看:

[brick1]# stat b1/dir/file1
  File: ‘b1/dir/file1’
  Size: 17              Blocks: 16         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 919362      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-03-06 14:17:27.752429505 +0530
Modify: 2015-03-06 13:55:37.206880347 +0530
Change: 2015-03-06 14:17:12.880343950 +0530
 Birth: -
[brick1]#
[brick1]# md5sum b1/dir/file1
040751929ceabf77c3c0b3b662f341a8  b1/dir/file1

在brick b2查看:

[brick2]# stat b2/dir/file1
  File: ‘b2/dir/file1’
  Size: 17              Blocks: 16         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 919365      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-03-06 14:17:23.249403600 +0530
Modify: 2015-03-06 13:55:37.206880000 +0530
Change: 2015-03-06 14:17:12.881343955 +0530
 Birth: -
[brick2]#
[brick2]# md5sum b2/dir/file1
040751929ceabf77c3c0b3b662f341a8  b2/dir/file1

2.1.2 选择以最新修改时间为源的文件

命令语句

gluster volume heal <VOLNAME> split-brain latest-mtime <FILE>

该命令使用对<FILE>具有最新修改时间的brick作为修复源。

2.1.3 选择副本中的一个brick作为特定文件的源

命令语句

gluster volume heal <VOLNAME> split-brain source-brick <HOSTNAME:BRICKNAME> <FILE>

在这里,<HOSTNAME:BRICKNAME>被选择为源brick,使用存在于源brick中的文件作为修复源。

示例:

注意在修复前后的md5校验和和文件大小。

修复前

在brick b1:

[brick1]# stat b1/file4
  File: ‘b1/file4’
  Size: 4               Blocks: 16         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 919356      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-03-06 13:53:19.417085062 +0530
Modify: 2015-03-06 13:53:19.426085114 +0530
Change: 2015-03-06 13:53:19.426085114 +0530
 Birth: -
[brick1]#
[brick1]# md5sum b1/file4
b6273b589df2dfdbd8fe35b1011e3183  b1/file4

在brick b2:

[brick2]# stat b2/file4
  File: ‘b2/file4’
  Size: 4               Blocks: 16         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 919358      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-03-06 13:52:35.761833096 +0530
Modify: 2015-03-06 13:52:35.769833142 +0530
Change: 2015-03-06 13:52:35.769833142 +0530
 Birth: -
[brick2]#
[brick2]# md5sum b2/file4
0bee89b07a248e27c83fc3d5951213c1  b2/file4

使用下述命令修复带有gfid c3c94de2-232d-4083-b534-5da17fc476ac的文件:

gluster volume heal test split-brain source-brick test-host:/test/b1 gfid:c3c94de2-232d-4083-b534-5da17fc476ac

修复后:

在brick b1查看:

# stat b1/file4
  File: ‘b1/file4’
  Size: 4               Blocks: 16         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 919356      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-03-06 14:23:38.944609863 +0530
Modify: 2015-03-06 13:53:19.426085114 +0530
Change: 2015-03-06 14:27:15.058927962 +0530
 Birth: -
# md5sum b1/file4
b6273b589df2dfdbd8fe35b1011e3183  b1/file4

在brick b2查看:

# stat b2/file4
 File: ‘b2/file4’
  Size: 4               Blocks: 16         IO Block: 4096   regular file
Device: fd03h/64771d    Inode: 919358      Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2015-03-06 14:23:38.944609000 +0530
Modify: 2015-03-06 13:53:19.426085000 +0530
Change: 2015-03-06 14:27:15.059927968 +0530
 Birth: -
# md5sum b2/file4
b6273b589df2dfdbd8fe35b1011e3183  b2/file4

2.1.4 选择一个brick作为所有文件的源

场景:许多文件都处于脑裂状态,使用一个brick作为源

命令语句

gluster volume heal <VOLNAME> split-brain source-brick <HOSTNAME:BRICKNAME>

上述命令的结果是,选择<HOSTNAME:BRICKNAME>中的所有脑裂文件作为源文件并将其修复到集群中。

示例:

一个卷中有三个文件a,b和c发生脑裂。

# gluster volume heal test split-brain source-brick test-host:/test/b1
Healed gfid:944b4764-c253-4f02-b35f-0d0ae2f86c0f.
Healed gfid:3256d814-961c-4e6e-8df2-3a3143269ced.
Healed gfid:b23dd8de-af03-4006-a803-96d8bc0df004.
Number of healed entries: 3

如上所述,此方法不支持Entry/GFID脑裂修复不支持使用CLI修复脑裂。修复/dir将失败,因为它在entry split-brain

# gluster volume heal test split-brain source-brick test-host:/test/b1 /dir
Healing /dir failed:Operation not permitted.
Volume heal failed.

但是此种问题可以通过从该brick之外的所有brick中删除文件来修复。参见下文修复目录脑裂。

2.2 从客户端修复脑裂

使用getfattrsetfattr命令,检测文件的数据和元数据脑裂状态,并从客户端修复脑裂。

使用具有brick b0,b1,b2和b3test卷进行测试。

# gluster volume info test

Volume Name: test
Type: Distributed-Replicate
Volume ID: 00161935-de9e-4b80-a643-b36693183b61
Status: Started
Number of Bricks: 2 x 2 = 4
Transport-type: tcp
Bricks:
Brick1: test-host:/test/b0
Brick2: test-host:/test/b1
Brick3: test-host:/test/b2
Brick4: test-host:/test/b3

brick的目录结构如下:

# tree -R /test/b?
/test/b0
├── dir
│   └── a
└── file100

/test/b1
├── dir
│   └── a
└── file100

/test/b2
├── dir
├── file1
├── file2
└── file99

/test/b3
├── dir
├── file1
├── file2
└── file99

查看处于脑裂状态的文件

# gluster v heal test info split-brain
Brick test-host:/test/b0/
/file100
/dir
Number of entries in split-brain: 2

Brick test-host:/test/b1/
/file100
/dir
Number of entries in split-brain: 2

Brick test-host:/test/b2/
/file99
<gfid:5399a8d1-aee9-4653-bb7f-606df02b3696>
Number of entries in split-brain: 2

Brick test-host:/test/b3/
<gfid:05c4b283-af58-48ed-999e-4d706c7b97d5>
<gfid:5399a8d1-aee9-4653-bb7f-606df02b3696>
Number of entries in split-brain: 2

可以通过以下命令查看文件的数据/元数据脑裂状态

getfattr -n replica.split-brain-status <path-to-file>

如果文件位于数据/元数据脑裂中,则从客户端执行的上述命令可提供一些信息;还提供了要分析的信息,以获得有关该文件的更多信息。此命令不适用于gfid目录脑裂。

示例:

1) file100元数据脑裂。

# getfattr -n replica.split-brain-status file100
file: file100
replica.split-brain-status="data-split-brain:no    metadata-split-brain:yes    Choices:test-client-0,test-client-1"

2) file1数据脑裂。

# getfattr -n replica.split-brain-status file1
file: file1
replica.split-brain-status="data-split-brain:yes    metadata-split-brain:no    Choices:test-client-2,test-client-3"

3) file99数据和元数据同时脑裂。

# getfattr -n replica.split-brain-status file99
file: file99
replica.split-brain-status="data-split-brain:yes    metadata-split-brain:yes    Choices:test-client-2,test-client-3"

4) dir是目录脑裂,但如前所述,上述命令不适用于这种脑裂。

# getfattr -n replica.split-brain-status dir
file: dir
replica.split-brain-status="The file is not under data or metadata split-brain"

5) file2脑裂但不存在于任何卷中。

# getfattr -n replica.split-brain-status file2
file: file2
replica.split-brain-status="The file is not under data or metadata split-brain"

分析数据和元数据脑裂的文件

在客户端对脑裂中的文件执行操作(比如cat、getfatter等)会出现input/output error错误。为了能够分析这些文件,glusterfs提供了setfattr命令,可以在安装glusterfs后直接使用。

# setfattr -n replica.split-brain-choice -v "choiceX" <path-to-file>

使用这个命令,可以选择一个特定的brick来访问脑裂的文件。

示例:

1) “file1”脑裂。试图从文件中读取会出现input/output error错误。

# cat file1
cat: file1: Input/output error

file1在test-client-2和test-client-3上发生脑裂。

将test-client-2设置为file1的split brain choice,可以从b2读取文件。

# setfattr -n replica.split-brain-choice -v test-client-2 file1

对文件执行读取操作。

# cat file1
xyz

同样,要从其他客户端查看文件,replica.split-brain-choice设置为test-client-3。

从错误的选择中检查文件会出错

要撤消已设置的脑裂选择,可以将上述setfattr命令与none一起用作扩展属性的值。

示例:

# setfattr -n replica.split-brain-choice -v none file1

现在查看文件将再次出现Input/output error错误,如前所述。

# cat file
cat: file1: Input/output error

一旦确定了使用的文件,就应该设置brick以进行修复。使用以下命令完成此操作:

# setfattr -n replica.split-brain-heal-finalize -v <heal-choice> <path-to-file>

示例

# setfattr -n replica.split-brain-heal-finalize -v test-client-2 file1

上述命令可用于修复所有文件上的数据和元数据脑裂。

注意:

1) 如果禁用了fopen keep cachefuse挂载选项,则每次选择新副本之前都需要使inode无效。split-brain-choice检查文件。可以使用如下命令:

# sefattr -n inode-invalidate -v 0 <path-to-file>

2) 上面提到的从客户端修复脑裂的过程将无法在nfs客户端上运行,因为它不提供xattrs支持

2.3 自动修复脑裂

基于gluster命令行和客户端的修复方法需要手动修复,手动运行命令。cluster.favorite child policy卷选项,当设置为可用的策略之一时,它将自动修复脑裂,而无需用户干预;默认值为none,即禁用。

# gluster volume set help | grep -A3 cluster.favorite-child-policy
Option: cluster.favorite-child-policy
Default Value: none
Description: This option can be used to automatically resolve split-brains using various policies without user intervention. "size" picks the file with the biggest size as the source. "ctime" and "mtime" pick the file with the latest ctime and mtime respectively as the source. "majority" picks a file with identical mtime and size in more than half the number of bricks in the replica.

cluster.favorite child policy适用于该卷的所有文件。如果启用了此选项,则不必在每个文件脑裂时手动修复脑裂文件,而将会根据设置的策略自动修复脑裂。

2.4 最佳实践

1.获取脑裂文件的路径:

可以通过以下方法获得:

a)命令gluster volume heal info split-brain
b)标识从客户端对其执行的文件操作始终失败并出现Input/Output error的文件。

2.从客户端关闭打开此文件的应用程序。虚拟机需要关闭电源。

3.确定正确的副本:

通过使用getfattr命令获取和验证扩展属性的变更记录;然后通过扩展属性来确定哪些brick包含可信的文件

getfattr -d -m . -e hex <file-path-on-brick>

有可能会出现一个brick包含正确的数据,而另一个brick也包含正确的元数据

  1. 使用setfattr命令在包含文件数据/元数据的“不良副本”的brack上重置相关的扩展属性。

5.在客户端执行查找命令来触发文件的自我修复:

ls -l <file-path-on-gluster-mount>

步骤3至5的详细说明:

要了解如何解决脑裂,我们需要了解changelog扩展属性。

getfattr -d -m . -e hex <file-path-on-brick>

示例:

[root@store3 ~]# getfattr -d -e hex -m. brick-a/file.txt
\#file: brick-a/file.txt
security.selinux=0x726f6f743a6f626a6563745f723a66696c655f743a733000
trusted.afr.vol-client-2=0x000000000000000000000000
trusted.afr.vol-client-3=0x000000000200000000000000
trusted.gfid=0x307a5c9efddd4e7c96e94fd4bcdcbd1b

trusted.afr.<volname>-client-<subvolume-index> Afr使用扩展属性来维护文件的变更日志;这个值由glusterfs客户端(fuse或nfs-server)进程计算;当glusterfs客户端修改文件或目录时,客户端联系每个模块,并根据模块的响应更新changelog扩展属性。

示例:

[root@pranithk-laptop ~]# gluster volume info vol
 Volume Name: vol
 Type: Distributed-Replicate
 Volume ID: 4f2d7849-fbd6-40a2-b346-d13420978a01
 Status: Created
 Number of Bricks: 4 x 2 = 8
 Transport-type: tcp
 Bricks:
 brick-a: pranithk-laptop:/gfs/brick-a
 brick-b: pranithk-laptop:/gfs/brick-b
 brick-c: pranithk-laptop:/gfs/brick-c
 brick-d: pranithk-laptop:/gfs/brick-d
 brick-e: pranithk-laptop:/gfs/brick-e
 brick-f: pranithk-laptop:/gfs/brick-f
 brick-g: pranithk-laptop:/gfs/brick-g
 brick-h: pranithk-laptop:/gfs/brick-h

在上面的示例中:

Brick             |    Replica set        |    Brick subvolume index
----------------------------------------------------------------------------
-/gfs/brick-a     |       0               |       0
-/gfs/brick-b     |       0               |       1
-/gfs/brick-c     |       1               |       2
-/gfs/brick-d     |       1               |       3
-/gfs/brick-e     |       2               |       4
-/gfs/brick-f     |       2               |       5
-/gfs/brick-g     |       3               |       6
-/gfs/brick-h     |       3               |       7

brick中的每个文件都维护自己的变更日志,副本集中所有其他brick中存在的文件的变更日志,如该brick所示。

在上面给出的示例卷中,brick-a中的所有文件都有两个条目,一个用于自身,另一个用于副本卷中的文件,即brick-b:

trusted.afr.vol-client-0=0x000000000000000000000000–>自身的更改日志(brick-a)
brick-b的trusted.afr.vol-client-1=0x000000000000000000000000–>更改日志,如brick-a所示

同样,brick-b中的所有文件也将具有:
brick-a的trusted.afr.vol-client-0=0x000000000000000000000000–>更改日志,如brick-b所示
trusted.afr.vol-client-1=0x000000000000000000000000–>自身的更改日志(brick-b)

Changelog值解析

每个扩展属性都有一个24位十六进制数字的值,前8位代表数据的变更日志,后8位代表变更日志
元数据的,最后8位数字表示目录项的更改日志。

0x 000003d7 00000001 00000000
        |      |       |
        |      |        \_ changelog of directory entries
        |       \_ changelog of metadata
         \ _ changelog of data

首8位字段记录数据变更记录
中间8位字段记录元数据变更记录
末8位字段记录索引gfid变更记录

当发生脑裂时,文件的更改日志将如下所示:

示例:(两份数据,元数据在同一个文件上脑裂对比)

[root@pranithk-laptop vol]# getfattr -d -m . -e hex /gfs/brick-?/a
getfattr: Removing leading '/' from absolute path names
\#file: gfs/brick-a/a
trusted.afr.vol-client-0=0x000000000000000000000000
trusted.afr.vol-client-1=0x000003d70000000100000000
trusted.gfid=0x80acdbd886524f6fbefa21fc356fed57
\#file: gfs/brick-b/a
trusted.afr.vol-client-0=0x000003b00000000100000000
trusted.afr.vol-client-1=0x000000000000000000000000
trusted.gfid=0x80acdbd886524f6fbefa21fc356fed57

结果解析

文件/gfs/brick-a/a上的changelog扩展属性:

trusted.afr.vol-client-0的前8位都是零(0x00000000……………)
trusted.afr.vol-client-1的前8位并非全为零(0x000003d7……………)
所以/gfs/brick-a/a上的changelog表示数据操作成功完成,但在/gfs/brick-b/a上失败了。

trusted.afr.vol-client-0的后8位全为零(x………00000000…….)
trusted.afr.vol-client-1不是全为零(x………0000000 1……)
因此/gfs/brick-a/a上的changelog表示数据操作成功完成,但在/gfs/brick-b/a上失败了。

文件/gfs/brick-b/a上的changelog扩展属性:

trusted.afr.vol-client-0的前8位并非全为零(0x000003b0……………)
trusted.afr.vol-client-1的前8位都为零(0x00000000……………)
所以/gfs/brick-b/a上的changelog表示数据操作成功完成,但在/gfs/brick-a/a上失败了。

trusted.afr.vol-client-0的后8位不是全为零(x………0000000 1…….)
trusted.afr.vol-client-1的后8位全为零(x………00000000……)
所以/gfs/brick-b/a上的changelog表示数据操作成功完成,但在/gfs/brick-a/a上失败了。

由于两个副本都具有数据,元数据更改并未在两个副本同时生效,因此它既是数据脑裂又是元数据脑裂。

确定正确的副本

使用stat,getfatter命令的输出来决定要保留的元数据和要决定要保留哪些数据的文件内容。

继续上面的例子,假设我们想要保留/gfs/brick-a/a和/gfs/brick-b/a的元数据。

重置相关变更日志以解决脑裂:

解决数据脑裂:

更改文件的changelog扩展属性,某些数据在/gfs/brick-a/a上操作成功,但在/gfs/brick-b/a上操作失败,所以/gfs/brick-b/a不应包含任何更改日志,重置在/gfs/brick-b/a的trusted.afr.vol-client-0上更改日志的数据部分。

解决元数据脑裂:

更改文件的changelog扩展属性,某些数据在/gfs/brick-b/a上操作成功,但在/gfs/brick-a/a上失败,所以/gfs/brick-a/a不应包含任何更改日志,重置trusted.afr.vol-client-1更改日志的元数据部分。

完成上述操作后,更改日志将如下所示:

在 /gfs/brick-b/a查看:
trusted.afr.vol-client-0
0x000003b00000000100000000 to 0x000000000000000100000000

元数据部分仍然不是全部为零,执行setfattr-n trusted.afr.vol-client-0-v 0x00000000000000010000000/gfs/brick-b/a

在/gfs/brick-a/a查看:
trusted.afr.vol-client-1
0x000003d70000000100000000 to 0x000003d70000000000000000

数据部分仍然不是全部为零,执行setfattr-n trusted.afr.vol-client-1-v 0x000003d7000000000000000/gfs/brick-a/a

在完成上述操作之后,变更日志如下所示:

[root@pranithk-laptop vol]# getfattr -d -m . -e hex /gfs/brick-?/a
getfattr: Removing leading '/' from absolute path names
#file: gfs/brick-a/a
trusted.afr.vol-client-0=0x000000000000000000000000
trusted.afr.vol-client-1=0x000003d70000000000000000
trusted.gfid=0x80acdbd886524f6fbefa21fc356fed57

#file: gfs/brick-b/a
trusted.afr.vol-client-0=0x000000000000000100000000
trusted.afr.vol-client-1=0x000000000000000000000000
trusted.gfid=0x80acdbd886524f6fbefa21fc356fed57

执行ls -l <file-path-on-gluster-mount>触发自愈

修复目录脑裂

当目录上出现脑裂时,AFR可以保守地合并目录中的不同条目。如果在一个brick上的目录 storage 具有entry 12 而在另一个brick上具有entry 34 则AFR将合并目录中的所有 1, 2, 3, 4 条目;以在同一目录中具有条目。但是,如果由于目录中文件的删除而导致脑裂的情况,则可能导致重新显示已删除的文件。当至少有一个条目具有相同文件名但 gfid 在该目录中不同时,脑裂需要人工干预。例:

brick-a 目录上有2个条目, file1 带有 gfid_xfile2 。在 brick-b 目录中有2项 file1gfid_yfile3 。这里的 file1 brick的gfid 有所不同。这类目录脑裂需要人工干预才能解决此问题。必须删除 file1 on brick-afile1 on brick-b 才能解决裂脑问题。

此外, gfid-link 必须删除相应的文件。这些 gfid-link 文件位于brick的顶级目录中。如果文件的gfid为 0x307a5c9efddd4e7c96e94fd4bcdcbd1bgetfattr 先前从命令接收到的trust.gfid 扩展属性),则可以在找到gfid-link文件 /gfs/brick-a/.glusterfs/30/7a/307a5c9efddd4e7c96e94fd4bcdcbd1b

注意事项

删除gfid-link之前,必须确保在该Brick上没有指向该文件的硬链接,如果存在硬链接,则也必须删除它们。

本文转自GlusterFS官方文档

2 Likes