简介
DRBD(Distributed Replicated Block Device,分布式复制块设备)是一个用软件实现的、无共享的、服务器之间镜像块设备内容的存储复制解决方案。DRBD是镜像块设备,是按数据位镜像成一样的数据块。
安装
ubuntu环境
准备两个ubuntu系统,一个作为源端ubu1,一个作为目的端ubu2。1
2
3
4
5
6
7
8bob@ubu1:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.5 LTS
Release: 20.04
Codename: focal
bob@ubu1:~$ uname -a
Linux ubu1 5.4.0-139-generic #156-Ubuntu SMP Sat Jan 21 13:46:46 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux
1 | bob@ubu2:~$ lsb_release -a |
brbd.ko
为linux内核自带,不需要另行安装
1 | bob@ubu1:~$ lsmod | grep drbd |
至于使用drbd的工具还是要安装的
1 | bob@ubu1:~$ sudo apt-cache show drbd-utils |
两个节点ubu1和ubu2都需要安装这个drbd-utils
包
常规用法
配置
配置/etc/drbd.d/global_common.conf
1 | global { |
DRBD系统向虚拟块的镜像中写入数据时,支持三种协议
protocol A
数据一旦写入磁盘并发送到网络中就认为完成了写入操作protocol B
收到接收确认就认为完成了写入操作protocol C
收到写入确认就认为完成了写入操作
基于安全考虑我们一般选择protocol C
配置DRBD资源/etc/drbd.d/r0.res
1 | resource r0 { |
device
指drbd映射出来的快设备名称,disk
指用于存放数据的硬盘。
启动
分别在ubu1
和ubu2
上创建DRBD资源元数据
1 | bob@ubu1:~$ sudo drbdadm create-md r0 |
1 | bob@ubu2:~$ sudo drbdadm create-md r0 |
然后再启动ubu1
和ubu2
上的DRBD服务
1 | bob@ubu1:~$ sudo systemctl start drbd |
1 | bob@ubu2:~$ sudo systemctl start drbd |
启动r0
资源,并设置ubu1
为主设备
1 | bob@ubu1:~$ sudo drbdadm up r0 |
可以使用drbdadm status r0
查看状态,也可以用cat /proc/drbd
查看同步进度。
当peer-disk
状态为UpToDate
表示数据已经同步到最新状态。
eg:1
2
3
4
5bob@ubu1:~$ sudo drbdadm status r0
r0 role:Primary
disk:UpToDate
peer role:Secondary
replication:Established peer-disk:UpToDate
如需查询服务状态详细信息可以通过命令drbdsetup status r0 --verbose --statistics
查询
文件系统常规使用
首先通过lsblk
查看drbd1
快设备是否存在,然后格式化成xfs文件系统,并挂载到/mnt
目录上1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22bob@ubu1:~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop1 7:1 0 49.1M 1 loop /snap/core18/2681
loop2 7:2 0 59.1M 1 loop /snap/core20/1826
loop3 7:3 0 60.7M 1 loop /snap/lxd/21843
loop4 7:4 0 43.2M 1 loop /snap/snapd/17954
loop5 7:5 0 91.9M 1 loop /snap/lxd/24065
loop6 7:6 0 57.5M 1 loop /snap/core20/1332
loop7 7:7 0 43.2M 1 loop /snap/snapd/18363
loop8 7:8 0 49.1M 1 loop /snap/core18/2701
sda 8:0 0 20G 0 disk
└─drbd1 147:1 0 20G 1 disk
sr0 11:0 1 1.1G 0 rom
vda 252:0 0 100G 0 disk
├─vda1 252:1 0 512M 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 98.5G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 49.3G 0 lvm /
bob@ubu1:~$ mkfs.xfs /dev/drbd1
...
bob@ubu1:~$ mount /dev/drbd1 /mnt
bob@ubu1:~$ touch /mnt/hello
切换
切换操作,可以认为是切换primary节点操作。需要先将ubu1(primary节点)设置成secondary
,再将ubu2(secondary节点)设置成primary
,然后ubu2节点就可以挂载drbd1
快设备了。
1 | bob@ubu1:~$ sudo drbdadm secondary r0 |
1 | bob@ubu2:~$ sudo drbdadm primary r0 |
在将ubu1节点从primary状态设置成secondary状态时可能会遇到如下错误
1 | bob@ubu1:~$ sudo drbdadm secondary r0 |
这说明当前块设备brbd1
正在被挂载或者被其他应用使用,可以使用lsof
命令查看改设备的使用情况,并终止使用后再设置节点状态为secondary
。
硬盘容量大小不一致情况
当源和备硬盘容量大小不一致时,取最小容量做为drbd块设备对外提供的存储空间大小。
ubu1:
1 | bob@ubu1:~$ lsblk |
ubu2:
1 | bob@ubu2:~$ lsblk |
硬盘扩容情况
在ubu1上使用lvm构建底层硬盘存储数据,方便后续进行扩容操作。先创建一个20G的lv,然后创建drbd块设备,待同步完数据后对lv进行扩容10G操作,最后再对drbd进行扩容操作。(此间省略lvm相关操作)
ubu2上使用一个30G的scsi设备,不配置lvm,与ubu1上的lvm块设备构成一个异构环境。
ubu1:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54bob@ubu1:~/drbd_res$ cat /etc/drbd.d/r1.res
resource r1 {
on ubu1 {
device /dev/drbd2;
disk /dev/drbd-vg/drbdlv1;
address 192.168.64.2:7792;
meta-disk internal;
}
on ubu2 {
device /dev/drbd2;
disk /dev/sdb;
address 192.168.64.4:7792;
meta-disk internal;
}
}
bob@ubu1:~/drbd_res$ sudo drbdadm create-md r1
initializing activity log
initializing bitmap (640 KB) to all zero
Writing meta data...
New drbd meta data block successfully created.
success
bob@ubu1:~/drbd_res$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 49.1M 1 loop /snap/core18/2681
loop1 7:1 0 49.1M 1 loop /snap/core18/2701
loop2 7:2 0 43.2M 1 loop /snap/snapd/17954
loop3 7:3 0 57.5M 1 loop /snap/core20/1332
loop4 7:4 0 43.2M 1 loop /snap/snapd/18363
loop5 7:5 0 60.7M 1 loop /snap/lxd/21843
loop6 7:6 0 91.9M 1 loop /snap/lxd/24065
loop7 7:7 0 59.1M 1 loop /snap/core20/1826
sda 8:0 0 20G 0 disk
└─drbd1 147:1 0 20G 1 disk
sdb 8:16 0 21G 0 disk
└─drbd--vg-drbdlv1 253:1 0 20G 0 lvm
sdc 8:32 0 31G 0 disk
sr0 11:0 1 1.1G 0 rom
vda 252:0 0 100G 0 disk
├─vda1 252:1 0 512M 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 98.5G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 49.3G 0 lvm /
bob@ubu1:~/drbd_res$ sudo drbdadm up r1
bob@ubu1:~/drbd_res$ sudo drbdadm primary --force r1
bob@ubu1:~/drbd_res$ cat /proc/drbd
version: 8.4.11 (api:1/proto:86-101)
srcversion: B438804C5AE8C84C95D0411
1: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
2: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:14496 nr:0 dw:0 dr:16616 al:8 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:20956348
[>....................] sync'ed: 0.1% (20464/20476)M
finish: 2:21:35 speed: 2,416 (2,416) K/sec
ubu2:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21bob@ubu2:~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 49.1M 1 loop /snap/core18/2681
loop1 7:1 0 49.1M 1 loop /snap/core18/2701
loop2 7:2 0 60.7M 1 loop /snap/lxd/21843
loop3 7:3 0 91.9M 1 loop /snap/lxd/24065
loop4 7:4 0 57.5M 1 loop /snap/core20/1332
loop5 7:5 0 59.1M 1 loop /snap/core20/1826
loop6 7:6 0 43.2M 1 loop /snap/snapd/17954
loop7 7:7 0 43.2M 1 loop /snap/snapd/18363
sda 8:0 0 20G 0 disk
└─drbd1 147:1 0 20G 1 disk
sdb 8:16 0 32G 0 disk
└─drbd2 147:2 0 20G 1 disk
sdc 8:32 0 22G 0 disk
sr0 11:0 1 1.1G 0 rom
vda 252:0 0 100G 0 disk
├─vda1 252:1 0 512M 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 98.5G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 49.3G 0 lvm /
目前drbd2对外提供的是一个20G的硬盘,接下来在不停drbd复制链接的情况下对其扩容10G(同样,省略lvm相关操作)
ubu1:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54bob@ubu1:~/drbd_res$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 49.1M 1 loop /snap/core18/2681
loop1 7:1 0 49.1M 1 loop /snap/core18/2701
loop2 7:2 0 43.2M 1 loop /snap/snapd/17954
loop3 7:3 0 57.5M 1 loop /snap/core20/1332
loop4 7:4 0 43.2M 1 loop /snap/snapd/18363
loop5 7:5 0 60.7M 1 loop /snap/lxd/21843
loop6 7:6 0 91.9M 1 loop /snap/lxd/24065
loop7 7:7 0 59.1M 1 loop /snap/core20/1826
sda 8:0 0 20G 0 disk
└─drbd1 147:1 0 20G 1 disk
sdb 8:16 0 21G 0 disk
└─drbd--vg-drbdlv1 253:1 0 30G 0 lvm
└─drbd2 147:2 0 20G 0 disk
sdc 8:32 0 31G 0 disk
└─drbd--vg-drbdlv1 253:1 0 30G 0 lvm
└─drbd2 147:2 0 20G 0 disk
sr0 11:0 1 1.1G 0 rom
vda 252:0 0 100G 0 disk
├─vda1 252:1 0 512M 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 98.5G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 49.3G 0 lvm /
bob@ubu1:~/drbd_res$ sudo drbdadm status r1
r1 role:Primary
disk:UpToDate
peer role:Secondary
replication:SyncSource peer-disk:Inconsistent done:88.51
bob@ubu1:~/drbd_res$ sudo drbdadm resize r1
bob@ubu1:~/drbd_res$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 49.1M 1 loop /snap/core18/2681
loop1 7:1 0 49.1M 1 loop /snap/core18/2701
loop2 7:2 0 43.2M 1 loop /snap/snapd/17954
loop3 7:3 0 57.5M 1 loop /snap/core20/1332
loop4 7:4 0 43.2M 1 loop /snap/snapd/18363
loop5 7:5 0 60.7M 1 loop /snap/lxd/21843
loop6 7:6 0 91.9M 1 loop /snap/lxd/24065
loop7 7:7 0 59.1M 1 loop /snap/core20/1826
sda 8:0 0 20G 0 disk
└─drbd1 147:1 0 20G 1 disk
sdb 8:16 0 21G 0 disk
└─drbd--vg-drbdlv1 253:1 0 30G 0 lvm
└─drbd2 147:2 0 30G 0 disk
sdc 8:32 0 31G 0 disk
└─drbd--vg-drbdlv1 253:1 0 30G 0 lvm
└─drbd2 147:2 0 30G 0 disk
sr0 11:0 1 1.1G 0 rom
vda 252:0 0 100G 0 disk
├─vda1 252:1 0 512M 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 98.5G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 49.3G 0 lvm /
ubu2:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21bob@ubu2:~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 49.1M 1 loop /snap/core18/2681
loop1 7:1 0 49.1M 1 loop /snap/core18/2701
loop2 7:2 0 60.7M 1 loop /snap/lxd/21843
loop3 7:3 0 91.9M 1 loop /snap/lxd/24065
loop4 7:4 0 57.5M 1 loop /snap/core20/1332
loop5 7:5 0 59.1M 1 loop /snap/core20/1826
loop6 7:6 0 43.2M 1 loop /snap/snapd/17954
loop7 7:7 0 43.2M 1 loop /snap/snapd/18363
sda 8:0 0 20G 0 disk
└─drbd1 147:1 0 20G 1 disk
sdb 8:16 0 32G 0 disk
└─drbd2 147:2 0 30G 1 disk
sdc 8:32 0 22G 0 disk
sr0 11:0 1 1.1G 0 rom
vda 252:0 0 100G 0 disk
├─vda1 252:1 0 512M 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 98.5G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 49.3G 0 lvm /
使用drbdadm resize r1
完成对r1
资源的扩容操作。
硬盘存在有效数据情况
ubu1和ubu2上分别创建了两个硬盘,一个20G存drbd的meta-data,一个30G用于存drbd的数据。
1 | bob@ubu1:~/drbd_res$ cat r2.res |
先对ubu1上的数据盘sdc
创建文件系统,并写入数据。然后再做drbd pair。
ubu1:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47bob@ubu1:~/drbd_res$ sudo mkfs.ext4 /dev/sdc
mke2fs 1.45.5 (07-Jan-2020)
Discarding device blocks: done
Creating filesystem with 8126464 4k blocks and 2031616 inodes
Filesystem UUID: 656f1b08-77a2-4488-acb1-f25ff616b257
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
bob@ubu1:~/drbd_res$ sudo mount /dev/sdc /mnt/
bob@ubu1:~/drbd_res$ echo "Hi, bob" > /mnt/bob.txt
bob@ubu1:~/drbd_res$ sudo umount /mnt
bob@ubu1:~/drbd_res$ sudo drbdadm create-md r2
md_offset 0
al_offset 4096
bm_offset 36864
Found some data
==> This might destroy existing data! <==
Do you want to proceed?
[need to type 'yes' to confirm] yes
initializing activity log
initializing bitmap (672 KB) to all zero
Writing meta data...
New drbd meta data block successfully created.
success
bob@ubu1:~/drbd_res$ sudo drbdadm up r2
bob@ubu1:~/drbd_res$ sudo drbdadm primary --force r2
bob@ubu1:~/drbd_res$ cat /proc/drbd
version: 8.4.11 (api:1/proto:86-101)
srcversion: B438804C5AE8C84C95D0411
1: cs:Connected ro:Secondary/Secondary ds:UpToDate/UpToDate C r-----
ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
3: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r-----
ns:130656 nr:0 dw:0 dr:131328 al:8 bm:0 lo:0 pe:4 ua:0 ap:0 ep:1 wo:f oos:32376640
[>....................] sync'ed: 0.5% (31616/31744)M
finish: 1:14:56 speed: 7,176 (7,176) K/sec
ubu2:1
2
3
4
5
6bob@ubu2:~$ sudo drbdadm create-md r2
initializing activity log
initializing bitmap (704 KB) to all zero
Writing meta data...
New drbd meta data block successfully created.
success
此时drbd pair已经创建好了,drbd3
也已经创建完成,直接挂载drbd3
查看数据是否依然还在
ubu1:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27bob@ubu1:~/drbd_res$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 49.1M 1 loop /snap/core18/2681
loop1 7:1 0 49.1M 1 loop /snap/core18/2701
loop2 7:2 0 43.2M 1 loop /snap/snapd/17954
loop3 7:3 0 57.5M 1 loop /snap/core20/1332
loop4 7:4 0 43.2M 1 loop /snap/snapd/18363
loop5 7:5 0 60.7M 1 loop /snap/lxd/21843
loop6 7:6 0 91.9M 1 loop /snap/lxd/24065
loop7 7:7 0 59.1M 1 loop /snap/core20/1826
sda 8:0 0 20G 0 disk
└─drbd1 147:1 0 20G 1 disk
sdb 8:16 0 21G 0 disk
└─drbd3 147:3 0 31G 0 disk
sdc 8:32 0 31G 0 disk
└─drbd3 147:3 0 31G 0 disk
sr0 11:0 1 1.1G 0 rom
vda 252:0 0 100G 0 disk
├─vda1 252:1 0 512M 0 part /boot/efi
├─vda2 252:2 0 1G 0 part /boot
└─vda3 252:3 0 98.5G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 49.3G 0 lvm /
bob@ubu1:~/drbd_res$ sudo mount /dev/drbd3 /mnt/
bob@ubu1:~/drbd_res$ ls /mnt/
bob.txt lost+found
bob@ubu1:~/drbd_res$ cat /mnt/bob.txt
Hi, Bob
原理
DRBD(Distributed Replicated Block Device)是一个基于内核模块的高可用性(HA)软件,它在两个或多个节点之间复制块设备数据,使得在其中一个节点发生故障时,其他节点可以接管工作并保持服务可用性。
DRBD的工作原理:
- DRBD将每个块设备划分为数据和元数据两个区域。元数据包含块设备的状态信息和同步状态,而数据包含实际的用户数据。
- DRBD使用一个专用的网络通信通道(通常是TCP / IP)来在节点之间传输数据。当发生写操作时,数据被写入本地节点的数据区域,并通过网络传输到远程节点,然后在远程节点上写入远程节点的数据区域。
- DRBD还使用一种名为“生成标识符”(Generation Identifiers)的机制来检测节点间的数据同步状态。每个生成标识符对应一个生成版本,节点在进行数据同步时,使用生成标识符来判断版本是否相同。
- DRBD提供了多种数据同步策略,例如全同步,增量同步和快速同步,以便在不同的应用场景下获得最佳的性能和数据完整性。
- DRBD支持不同的工作模式,如协议A和协议C,用于适应不同的应用需求。协议A用于异步复制,适用于数据传输速度较慢的场景,而协议C则用于同步复制,适用于对数据完整性有较高要求的场景。
DRBD Metadata
DRBD元数据包括:
- DRBD容量
- GI(Generation Identifiers)
- Activity Log
- Quick-sync Bitmap
Internal meta data
资源配置成internal
方式存储元数据,这意味着元数据将与底层实际存储的数据放在一起。它通过在设备末尾设置一个区域来专门存储元数据。
优点
由于元数据与实际数据密不可分,因此在硬盘发生故障时,管理员不需要采取任何特殊措施。元数据将随着实际数据丢失,并与实际数据一起恢复。缺点
如果底层设备是单个物理硬盘(而不是 RAID 集),则内部元数据可能会对写入吞吐量产生负面影响。应用程序发起的写请求的性能可能会触发 DRBD 中元数据的更新。如果元数据存储在同一磁盘上,则写操作可能会导致硬盘的写入/读取头产生两次额外的移动。
如果您计划将内部元数据与已经有需要保留的数据的现有底层设备一起使用,您必须考虑 DRBD 元数据所需的空间。另外,在创建 DRBD 资源时,新创建的元数据可能会覆盖底层设备末尾的数据,从而可能破坏现有的文件。
为了避免这种情况发生,有三种解决方法:
- 扩容底层硬盘,保证其有足够的容量存储元数据。
- 缩小已存在于底层硬盘的数据的大小,这需要文件系统的支持。
- 使用external meta data 替代。
External meta data
External meta data 只是简单地存储在一个与包含生产数据的设备不同的、专用的块设备中。
优势
对于某些写操作,使用外部元数据可以产生略微改善的延迟行为。缺点
元数据与实际生产数据并不密不可分。这意味着,在硬件故障仅破坏生产数据(但不破坏 DRBD 元数据)的情况下,需要手动干预,以实现从存活的节点对新替换磁盘的全面数据同步。
如果满足以下所有条件,使用外部元数据也是唯一可行的选择,您正在使用 DRBD 复制一个已经包含您希望保留的数据的现有设备,且该现有设备不支持扩大容量,且该设备上的现有文件系统不支持缩小容量。
Generation Identifiers
DRBD 使用Generation Identifiers(GIs)来标识“复制数据代”。数据同步是基于GI实现的。GI是一个递增的整数,每个DRBD设备都有自己的GI计数器,用于记录本地和远程节点上最新的GI。当DRBD设备从远程节点读取数据时,它会比较本地和远程节点上的GI值。如果本地GI值低于远程节点上的GI值,那么DRBD设备会自动启动数据同步,将远程节点上的数据复制到本地节点上。
该GI在DRBD的内部机制如下:
- 确定这两个节点是否实际上是同一集群的成员(而不是意外连接的两个节点)
- 确定后台重新同步的方向(如果有必要)
- 确定是否需要进行完全重新同步或是否仅需要进行部分重新同步
- 标识脑裂
分裂大脑是指当DRBD设备与另一个节点失去联系时发生的问题。在这种情况下,每个节点都可能认为自己是唯一的“活动”节点,并开始独立地写入数据。当两个节点再次连接时,它们可能会发现它们的数据不同步。GI用于解决这个问题。当两个节点重新连接时,它们比较彼此的GI值。如果GI值相同,则两个节点处于相同的“代”,可以继续同步数据。如果GI值不同,则两个节点处于不同的“代”,需要手动解决分裂大脑问题,通常需要将其中一个节点上的数据进行回滚。
数据代(Data generations)
以下情况下标记新的数据生成开始:
- 初始设备全量同步时
- 断开的资源切换到主要角色时
- 资源在主要角色下线时
因此,我们可以总结出,每当资源处于已连接的连接状态,并且两个节点的磁盘状态都为UpToDate时,两个节点上的当前数据生成相同。
反之亦然。请注意,当前实现使用最低位来编码节点的角色(主/辅)。因此,即使被认为具有相同的数据生成,不同节点上的最低位也可能不同。
每个新的数据生成由8字节的通用唯一标识符(UUID)标识。
GI元组(The generation identifier tuple)
BD在本地资源元数据中保存了有关当前和历史数据生成的四个信息:
- 当前UUID (Current UUID)
这是从本地节点的视角看到的当前数据生成的生成标识符。当资源已连接并且同步完成时,当前UUID在节点之间是相同的。 - 位图UUID (Bitmap UUID)
这是用于跟踪在断开连接模式下磁盘同步位图中的更改的生成的UUID。与磁盘同步位图本身一样,该标识符仅在断开连接模式下才相关。如果资源已连接,则此UUID始终为空(零)。 - 两个历史UUID (Historical UUIDs)
它们是当前数据生成之前的两个数据生成的标识符。
GI如何变化
Start of a new data generation
当一个节点(无论是由于网络故障还是手动干预)失去与其对等节点的连接时,DRBD 以下方式修改其本地生成GI:
- 为新的数据生成创建一个新的 UUID。这成为主节点的新的 current UUID。
- 用之前的current UUID替换现在的Bitmap UUID,因此它成为主节点的新的Bitmap UUID。
- 在次要节点上,GI元组保持不变
Start of re-synchronization
在重新同步初始化时,DRBD在本地GI执行这些修改:
- 同步源上的Current UUID保持不变。
- 同步源上的Bitmap UUID轮换到第一个历史UUID。
- 在同步源上生成一个新的Bitmap UUID。
- 此UUID成为同步目标上的新Current UUID。
- 同步目标上的Bitmap UUID和历史UUID保持不变。
Completion of re-synchronization
当重新同步完成,需要执行如下步骤:
- 同步源上的Current UUID保持不变
- 同步源上的Bitmap UUID轮转到第一个历史UUID,第一历史UUID替换第二历史UUID(任何已存在的第二历史UUID将被丢弃)
- 同步源上的Bitmap UUID将被清空(清零)
- 同步目标采用来自同步源的整个GI元组
DRBD如何使用GI
当两个节点之间建立连接时,它们会交换当前可用的生成标识符,并相应地进行操作。可能有许多可能的结果:
- 两个节点的Current UUID都为空
本地节点检测到它自己和对等节点的当前UUID都为空。这是刚刚配置好的资源的正常情况,尚未启动初始完全同步。不会进行同步,必须手动启动。 - 一个节点的Current UUID为空
本地节点检测到对等节点的Current UUID为空,而自己的不为空。这是刚刚配置好的资源的正常情况,初始全同步刚刚启动,本地节点被选为初始同步源。DRBD现在设置磁盘上同步位图中的所有位(意味着它认为整个设备不同步),并作为同步源开始同步。在相反的情况下(本地Current UUID为空,对等节点不为空),DRBD执行相同的步骤,只是本地节点变成同步目标。 - Current UUID相等
本地节点检测到其Current UUID和对等节点的Current UUID都不为空且相等。这是在资源处于从属角色时进入断开连接模式的资源的正常情况,且在断开连接期间没有在任一节点上进行晋升。不会进行同步,因为不需要同步。 - Bitmap UUID与对等节点的Current UUID匹配
本地节点检测到它的Bitmap UUID与对等节点的Current UUID匹配,而对等节点的Bitmap UUID为空。这是从属节点故障后的正常预期情况,本地节点处于主角色。这意味着对等节点在此期间从未变为主节点,并一直使用相同的数据生成基础。现在,DRBD会启动正常的后台重新同步,本地节点成为同步源。反之,如果本地节点检测到它的Bitmap UUID为空,并且对等节点的位图与本地节点的Current UUID匹配,那么这是本地节点故障后的正常预期情况。同样,DRBD现在启动正常的后台重新同步,本地节点成为同步目标。 - Current UUID与对等节点的历史UUID匹配
本地节点检测到它的Current UUID与对等节点的历史UUID之一匹配。这意味着尽管两个数据集共享一个共同的祖先,并且对等节点具有最新的数据,但在对等节点的位图中保留的信息已经过时且无法使用。因此,正常同步是不足够的。DRBD现在将整个设备标记为不同步,并启动完全后台重新同步,本地节点成为同步目标。在相反的情况(本地节点的历史 UUID 与对等节点的Current UUID匹配),DRBD 执行相同的步骤,只是本地节点成为同步源。 - Bitmap UUID匹配,但Current UUID不匹配
本地节点检测到其Current UUID与对等节点的Current UUID不同,但Bitmap UUID匹配。这是脑裂的情况,但数据生成具有相同的父级。这意味着如果已配置,DRBD 将调用脑裂自动恢复策略。否则,DRBD将断开连接并等待手动脑裂解决。 - Current UUID 和Bitmap UUID 都不匹配
本地节点检测到其Current UUID与对等节点的Current UUID不同,且Bitmap UUID也不匹配。这是不相关祖先代的脑裂,因此即使配置了自动恢复策略,也是无用的。DRBD断开连接并等待手动脑裂解决。 - 没有 UUID 匹配
如果DRBD未能在两个节点的GI元组中检测到任何匹配的元素,它会记录关于不相关数据的警告并断开连接。这是DRBD防止意外连接两个之前从未听说过对方的集群节点的安全保障。
Activity Log
在一个写操作期间,DRBD将写操作转发到本地后备块设备,但也通过网络发送数据块。这两个操作实际上都是同时进行的。随机的时序行为可能会导致这样一种情况:写操作已经完成,但网络传输尚未完成。如果此时活动节点失败并启动故障转移,则这个数据块在节点之间是不同步的——在崩溃之前已在失败的节点上写入,但复制尚未完成。因此,当节点最终恢复时,这个块必须在随后的同步期间从数据集中删除。否则,崩溃的节点将“领先于”存活的节点,这将违反复制存储的“全部或无”的原则。这不仅是DRBD所特有的问题,在实际上所有的复制存储配置中都存在这个问题。许多其他存储解决方案(就像DRBD本身在0.7版本之前)要求在活动节点失败后,该节点必须在恢复后进行完全同步。
DRBD自0.7版本之后。在元数据区域存储活动日志(Activity Log)跟踪了“最近”已经写入的那些块。俗称,这些区域被称为热区段。如果一个临时失败的处于活动模式的节点进行同步,只有在AL中突出显示的那些热区段需要进行同步,而不需要同步整个设备。这大大减少了在活动节点崩溃后进行同步所需的时间。
Activity extents
Activity Log由多个Activity extents组成。可通过资源配置文件中的activity-log-size
参数进行配置,该参数表示Active extents数量,必须是2的幂,且范围通常在16到4096之间。每个Activity extents大小为4MiB。
保持大的活动日志可以提高写入吞吐量。每次激活新的扩展时,一个旧的扩展将被重置为非活动状态。这种转换需要向元数据区域写入一个操作。如果活动扩展数很高,旧的活动扩展很少被交换出,从而减少了元数据写操作,从而提高了性能。
保持小的活动日志可以缩短在主节点失败和随后的恢复后的同步时间。
选择一个合适Activity Log Size
R
是同步速度(单位:MB/s)tsync
是同步时间(单位:s)E
是Active extents数量
DRBD是可以控制同步带宽的,使用net
配置选项来控制DRBD在网络上使用的带宽。这个选项可以在DRBD配置文件中的全局段中设置,也可以在资源段中设置。
eg:1
2
3
4
5
6global {
...
net {
max-rate 1G;
}
}
max-rate
选项将同步带宽限制为1Gbit/s。您可以将该选项设置为所需的速率,以控制DRBD在网络上使用的带宽。
Quick-sync Bitmap
Quick-sync Bitmap是 DRBD 在每个资源上使用的内部数据结构,用于跟踪块是否同步(在两个节点上相同)或不同步。它仅在资源处于断开模式时才相关。在Quick-sync Bitmap中,一个比特表示一个 4KiB 的磁盘数据块。如果该位被清除,则意味着相应的块仍与对等节点同步。这意味着该块自断开连接以来尚未被写入。相反,如果该位被设置,则意味着该块已被修改,并且在连接再次可用时需要重新同步。
当 DRBD 检测到断开的设备上的写 I/O 时,因此开始在Quick-sync Bitmap中设置位,它在 RAM 中执行此操作,从而避免了昂贵的同步元数据 I/O 操作。只有当相应的块变得“冷”(从活动日志中过期)时,DRBD 才会在Quick-sync Bitmap的磁盘表示中进行适当的修改。同样,如果在断开连接的同时手动关闭了剩余节点上的资源,则 DRBD 将完整的Quick-sync Bitmap刷新到持久存储中。当对等节点恢复或重新建立连接时,DRBD 将结合两个节点的位图信息,确定必须重新同步的总数据集。同时,DRBD 检查生成标识符以确定同步方向。
充当同步源的节点然后将协商好的块传输到对等节点,在同步目标确认修改时清除同步位。如果重新同步现在被中断(例如,由于另一个网络故障),然后继续恢复,它将在离开时继续进行 - 当然,同时修改的任何其他块都将添加到重新同步数据集中。