继上次分享的《分布式存储系统 Ceph 架构及使用场景解析》 和 《分布式存储Ceph之PG状态详解》 ,这次分享《分布式存储Ceph 块存储灾备方案》。
RBD Mirror原理其实和MySQL的主从同步原理非常类似,前者基于journaling,后者基于binlog,简单地说就是利用日志进行回放(replay):通过在存储系统中增加Mirror组件,采用异步复制的方式,实现异地备份。(此处的journal是指Ceph RBD的journal,而不是OSD的journal)
该能力利用了 RBD image 的日志特性,以确保集群间的副本崩溃一致性。镜像功能需要在同伴集群( peer clusters )中的每一个对应的 pool 上进行配置,可设定自动备份某个存储池内的所有 images 或仅备份 images 的一个特定子集。 rbd-mirror 守护进程负责从远端集群拉取 image 的更新,并写入本地集群的对应 image 中。
当RBD Journal功能打开后,所有的数据更新请求会先写入RBD Journal,然后后台线程再把数据从Journal区域刷新到对应的image区域。RBD journal提供了比较完整的日志记录、读取、变更通知以及日志回收和空间释放等功能,可以认为是一个分布式的日志系统。
1、当接收到一个写入请求后,I/O会先写入主集群的Image Journal
2、Journal写入成功后,通知客户端
3、客户端得到响应后,开始写入image
3、备份集群的mirror进程发现主集群的Journal有更新后,从主集群的Journal读取数据,写入备份集群(和上面序号一样,是因为这两个过程同时发生)
4、备份集群写入成功后,会更新主集群Journal中的元数据,表示该I/O的Journal已经同步完成
5、主集群会定期检查,删除已经写入备份集群的Journal数据。
以上就是一个rbd-mirror工作周期内的流程,在现有的Jewel版本中30s为一次工作周期,暂时不能改变这个周期时间。
1、当副本在异地的情况下,减少了单个集群不同节点间的数据写入延时;
2、减少本地集群或异地集群由于意外断电导致的数据丢失。
双向备份:两个集群之间互相同步,两个集群都要运行rbd-mirror进程。
单向备份:分为主集群和从集群,只在从集群运行rbd-mirror进程,主集群的修改会自动同步到从集群。
mirroring是基于存储池进行的peer,ceph支持两种模式的镜像,根据镜像来划分有:
存储池模式
镜像模式
创建一个用于测试的存储池:
#local集群ceph osd pool create test_pool 100 100 replicated --cluster=localpool 'test_pool' created #remote集群ceph osd pool create test_pool 100 100 replicated --cluster=remotepool 'test_pool' created
开启存储池rbdmirror的镜像功能:
#local集群rbd mirror pool enable test_pool pool --cluster=local #remote集群rbd mirror pool enable test_pool pool --cluster=remote
主集群创建一个测试用的RBD:
rbd create test_pool/test_image --size=1024 --cluster=local
启动后会才会记录image的事件,才可以被rbd-mirror检测到并同步到从集群:
rbd feature enable test_pool/test_image exclusive-lockrbd feature enable test_pool/test_image journaling
把local和remote设为同伴,这个是为了让rbd-mirror进程找到它peer的集群的存储池:
rbd mirror pool peer add test_pool client.admin@remote --cluster=local rbd mirror pool peer add test_pool client.admin@local --cluster=remote #如果需要删除peer 语法:rbd mirror pool peer remove \u0026lt;pool-name\u0026gt; \u0026lt;peer-uuid\u0026gt;
查看peer的情况:
rbd mirror pool info --pool=test_pool --cluster=localMode: poolPeers:UUID NAME CLIENTf0929e85-259d-450b-917e-9eb231b7e43b remote client.admin rbd mirror pool info --pool=test_pool --cluster=remoteMode: poolPeers:UUID NAME CLIENT5851ba6a-e383-4ef0-9b9d-5ae34c9518a6 local client.admin
a. 先用调试模式启动进程看看情况,在remote的机器上执行
#remote:rbd-mirror -d --setuser ceph --setgroup ceph --cluster remote -i admin
b. 如果确认没问题就用服务来控制启动
#remotevim /usr/lib/systemd/system/[email protected] #修改Environment=CLUSTER=remote
c. 在remote机器上启动
systemctl start ceph-rbd-mirror@adminps -ef|grep rbdceph 4325 1 1 17:59 ? 00:00:00 /usr/bin/rbd-mirror -f --cluster remote --id admin --setuser ceph --setgroup ceph
a. 查询local集群镜像的同步的状态
#localrbd mirror image status test_pool/test_image --cluster remotetest_image: global_id: dabdbbed-7c06-4e1d-b860-8dd104509565 state: up+replaying description: replaying, master_position=[object_number=2, tag_tid=2, entry_tid=3974], mirror_position=[object_number=3, tag_tid=2, entry_tid=2583], entries_behind_master=1391 last_update: 2017-01-22 17:54:22
b. 检查数据是否同步到remote集群
#remoterbd info test_pool/test_image
启动后会才会记录image的事件,才可以被rbd-mirror检测到并同步到从集群
#localrbd feature enable test_pool/test_image exclusive-lockrbd feature enable test_pool/test_image journaling
#local:rbd mirror pool enable test_pool image #remote:ceph osd pool create test_pool 100 100 replicated --cluster=remotepool 'rbdmirror' created rbd mirror pool enable test_pool image
#localrbd mirror image enable test_pool/test_imageMirroring enabled rbd info test_pool/test_image --cluster=localrbd image 'test_image': size 10240 MB in 2560 objects order 22 (4096 kB objects) block_name_prefix: rbd_data.105774b0dc51 format: 2 features: layering, exclusive-lock, journaling flags: create_timestamp: Wed Dec 13 16:46:08 2017 journal: 105774b0dc51 mirroring state: enabled mirroring global id: 013f9e35-9d08-40fc-bf24-1e11a07a0910 mirroring primary: true
把local和remote设为同伴,这个是为了让rbd-mirror进程找到它peer的集群的存储池:
rbd mirror pool peer add test_pool client.admin@remote --cluster=local rbd mirror pool peer add test_pool client.admin@local --cluster=remote #如果需要删除peer 语法:rbd mirror pool peer remove \u0026lt;pool-name\u0026gt; \u0026lt;peer-uuid\u0026gt;
查看peer的情况:
rbd mirror pool info --pool=test_pool --cluster=localMode: poolPeers:UUID NAME CLIENTf0929e85-259d-450b-917e-9eb231b7e43b remote client.admin rbd mirror pool info --pool=test_pool --cluster=remoteMode: poolPeers:UUID NAME CLIENT5851ba6a-e383-4ef0-9b9d-5ae34c9518a6 local client.admin
a. 先用调试模式启动进程看看情况,在remote的机器上执行
#remote:rbd-mirror -d --setuser ceph --setgroup ceph --cluster remote -i admin
b. 如果确认没问题就用服务来控制启动
#remotevim /usr/lib/systemd/system/[email protected] #修改Environment=CLUSTER=remote
c. 在remote机器上启动
systemctl start ceph-rbd-mirror@adminps -ef|grep rbdceph 4325 1 1 17:59 ? 00:00:00 /usr/bin/rbd-mirror -f --cluster remote --id admin --setuser ceph --setgroup ceph
a. 查询local集群镜像的同步的状态
#localrbd mirror image status test_pool/test_image --cluster remotetest_image: global_id: dabdbbed-7c06-4e1d-b860-8dd104509565 state: up+replaying description: replaying, master_position=[object_number=2, tag_tid=2, entry_tid=3974], mirror_position=[object_number=3, tag_tid=2, entry_tid=2583], entries_behind_master=1391 last_update: 2017-01-22 17:54:22
b. 检查数据是否同步到remote集群
#remoterbd info test_pool/test_image
rbd bench-write test_image --io-threads 30 --pool=test_pool --io-pattern seq --io-total 17199730000 --io-size 4096000elapsed: 18 ops: 4200 ops/sec: 228.33 bytes/sec: 935243763.72
rbd bench-write test_image --io-threads 30 --pool=test_pool --io-pattern rand --io-total 17199730000 --io-size 4096000elapsed: 18 ops: 4200 ops/sec: 228.57 bytes/sec: 936229596.77
rbd bench-write test_image --io-threads 30 --pool=test_pool --io-pattern seq --io-total 17199730000 --io-size 4096000elapsed: 94 ops: 4200 ops/sec: 44.53 bytes/sec: 182382108.66
rbd bench-write test_image --io-threads 30 --pool=test_pool --io-pattern rand --io-total 17199730000 --io-size 4096000elapsed: 115 ops: 4200 ops/sec: 36.50 bytes/sec: 149499469.69
通过测试结果可以看出启用rbd-mirror 会导致主集群性能下降5倍多。
工具 | 集群模式 | 块大小 | 并发数 | 顺序读写 | 随机读写 | |
---|---|---|---|---|---|---|
rbd bench-write | 单主集群 | 4M | 30 | 带宽:935 MB/s 平均IOPS:228.33 |
带宽:936 MB/s 平均IOPS: 228.57 |
|
rbd bench-write | 主备集群 | 4M | 30 | 带宽:182 MB/s 平均IOPS:44.53 |
带宽:149 MB/s 平均IOPS: 36.50 |
1. rbd journal pool 功能没实现sudo ceph daemon osd.0 config set rbd_journal_pool = test_pool3{ \u0026quot;error\u0026quot;: \u0026quot;error setting 'rbd_journal_pool' to '= test_pool3': (38) Function not implemented\u0026quot;} 2. 调整参数从10-100,效果不明显rbd_journal_object_flush_age = 100rbd_journal_splay_width = 100
3.当一致性组实现的时候,我们就可以用一个journal来管理所有的RBD的镜像,可以给一个已经存在image开启journal,ceph将会将你的镜像做一个快照,然后对快照做一个复制,然后开启journal,这都是后台执行的一个任务可以启用和关闭单个镜像或者存储池的mirror功能,
如果启用了journal功能,那么每个镜像将会被复制可以使用 rbd mirror pool enable启用它。
由于核心流程就是先写日志,然后写image需要写两份的逻辑,所以导致性能就会有损失。
根据官方的参数优化也没有明显的效果,建议等待官方更新features。
作者介绍:李航, 多年的底层开发经验,在高性能 nginx 开发和分布式缓存 redis cluster 有着丰富的经验,目前从事分布式存储 Ceph 工作。先后在 58 同城、汽车之家、优酷土豆集团工作。
目前供职于滴滴基础平台运维部 - 技术专家岗位,主要负责分布式 Ceph 系统。个人主要关注的技术领域:高性能 Nginx 开发、分布式缓存、分布式存储。