找回密码
 注册
查看: 1802|回复: 0

分布式存储Ceph rbd-mirror灾备同步数据

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2021-12-7 13:35:36 | 显示全部楼层 |阅读模式
个人主要关注的技术领域:高性能Nginx开发、分布式缓存、分布式存储。" {# k: `# P8 I8 A6 j& l
1.说明介绍 1.1 基本原理
& o9 `5 |& B0 G0 r2 K0 B& y# u, yRBD Mirror原理其实和MySQL的主从同步原理非常类似,前者基于journaling,后者基于binlog,简单地说就是利用日志进行回放(replay):通过在存储系统中增加Mirror组件,采用异步复制的方式,实现异地备份。(此处的journal是指Ceph RBD的journal,而不是OSD的journal)
  X* a% b+ J2 k该能力利用了 RBD image 的日志特性,以确保集群间的副本崩溃一致性。镜像功能需要在同伴集群( peer clusters )中的每一个对应的 pool 上进行配置,可设定自动备份某个存储池内的所有 images 或仅备份 images 的一个特定子集。 rbd-mirror 守护进程负责从远端集群拉取 image 的更新,并写入本地集群的对应 image 中。' F0 K, N/ E: C9 Y
当RBD Journal功能打开后,所有的数据更新请求会先写入RBD Journal,然后后台线程再把数据从Journal区域刷新到对应的image区域。RBD journal提供了比较完整的日志记录、读取、变更通知以及日志回收和空间释放等功能,可以认为是一个分布式的日志系统。5 ^  C$ T2 t% u; G
1.2 工作流程
# d2 h* ]! R3 l: N( I8 m* K
6 K7 \  Q" F  L% C1、当接收到一个写入请求后,I/O会先写入主集群的Image Journal6 B" E, G2 _! l( U) H0 M
2、Journal写入成功后,通知客户端
4 c3 o$ m% Q& P$ C* P; Y1 ?3、客户端得到响应后,开始写入image
& |+ u9 `0 _* }# n3、备份集群的mirror进程发现主集群的Journal有更新后,从主集群的Journal读取数据,写入备份集群(和上面序号一样,是因为这两个过程同时发生)- r7 \: V  e7 k- k
4、备份集群写入成功后,会更新主集群Journal中的元数据,表示该I/O的Journal已经同步完成
& }+ B, E* Y2 T5、主集群会定期检查,删除已经写入备份集群的Journal数据。
4 t- T: F; |& O; `1 |+ ^/ U以上就是一个rbd-mirror工作周期内的流程,在现有的Jewel版本中30s为一次工作周期,暂时不能改变这个周期时间。. w- V- A3 D+ c5 |' O* w
1.3 优点
: {6 m7 E# k. a: K1、当副本在异地的情况下,减少了单个集群不同节点间的数据写入延时;
* [% l7 e+ `9 `; @2、减少本地集群或异地集群由于意外断电导致的数据丢失。
# R% n  a2 D8 `7 A. i! C& b" A1.4 单向备份与双向备份1 A; L/ v9 P8 F! x2 E& \9 r" W
双向备份:两个集群之间互相同步,两个集群都要运行rbd-mirror进程。- r1 U9 w( @9 t# ]2 J
单向备份:分为主集群和从集群,只在从集群运行rbd-mirror进程,主集群的修改会自动同步到从集群。- e( B; ?0 M/ ]
1.5 安装须知- k6 q# d8 W% W% Q4 ]6 I; o6 ]% {
RBD 镜像功能需要 Ceph Jewel 或更新的发行版本。
- I1 [9 e3 x2 P  J+ g8 Y7 j目前Jewel版本只支持一对一,不支持一对多。
0 b8 v& x2 p' W- z; x  i, |两个集群 (local和remote) 需要能够互通。1 w7 j# p1 D3 O; m$ k
RBD需要开启journal特性, 启动后会记录image的事件。
  d$ b5 `: Z! Y4 d2. mirroring 模式% |1 T1 C8 Q- l, Q: U; m3 }6 \
mirroring是基于存储池进行的peer,ceph支持两种模式的镜像,根据镜像来划分有:
1 P& {% g2 S+ h存储池模式+ ?; m1 a- m4 L
一个存储池内的所有镜像都会进行备份% s8 B, ^" V  v! L* y
镜像模式+ W4 P% n4 Q) m1 n
只有指定的镜像才会进行备份
6 ~4 ]1 y  B& R- T2.1 存储池模式 2.1.1 创建存储池
' B) \' l. N  t  L创建一个用于测试的存储池:5 c4 Q+ _# O- }; d( `% H
#local集群
- ^5 R1 s# W5 Q2 J6 g2 Rceph osd pool create test_pool 100 100 replicated --cluster= localpool 'test_pool'created
( j! z5 w5 a6 U8 o2 |( Y" }% X; f#remote集群
! M9 ?9 t- C# d) cceph osd pool create test_pool 100 100 replicated --cluster=remotepool 'test_pool'created 2.1.2 启用存储池模式
5 h& P$ F( i  e: \4 e开启存储池rbdmirror的镜像功能:( E+ @4 M; t% ~% g9 A
#local集群
( {8 ~4 r0 t# M! I$ A& A% mrbd mirror pool enabletest_pool pool --cluster= local/ I( n0 c8 X. F! \" J" Q! n9 x
#remote集群& e8 O) K- W- f1 y" |. a2 G
rbd mirror pool enabletest_pool pool --cluster=remote 2.1.3 创建RBD
0 K& i+ {5 _6 G) ~5 \主集群创建一个测试用的RBD:& b1 Q+ u4 K6 s" q# ^# i
rbd create test_pool/test_image --size=1024 --cluster= local2.1.4 主集群开启jounaling特性
& k& H8 l" h4 L启动后会才会记录image的事件,才可以被rbd-mirror检测到并同步到从集群:
5 W6 E; A+ t* |rbd feature enabletest_pool/test_image exclusive-lockrbd feature enabletest_pool/test_image journaling 2.1.5. 增加同伴集群1 m+ a/ f0 J- ~! w3 ^- U+ x
把local和remote设为同伴,这个是为了让rbd-mirror进程找到它peer的集群的存储池:& l( S$ d* c! V- N2 k* J
rbd mirror pool peer add test_pool client.admin@remote --cluster= local
! w9 o4 J8 x2 U' N% w6 ~" {rbd mirror pool peer add test_pool client.admin@ local--cluster=remote* e; V* e& P1 e" |- W: ?
#如果需要删除peer 语法:" A& [- e  w9 _$ u  r7 A
rbd mirror pool peer remove <pool-name> <peer-uuid>4 I: y4 F* m. m; S: {4 N! l
查看peer的情况:
2 K- R  r; Y6 x* o2 yrbd 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 localclient.admin 2.1.6 开启rbd-mirror的同步进程
& t$ B3 B% W" F$ I/ ^4 l0 u- Ra. 先用调试模式启动进程看看情况,在remote的机器上执行
( E+ N& J# _0 Z, m! [/ z1 x#remote:8 x1 D: m+ ?$ h. n
rbd-mirror -d --setuser ceph --setgroup ceph --cluster remote -i admin, g! g7 S7 ?+ R) G, v& j
b. 如果确认没问题就用服务来控制启动
) _: S' Y3 E, C( Z. c7 k#remote
2 G1 y3 v  U* J# x( _0 Mvim [url=]/usr/lib/systemd/system/ceph-rbd-mirror@.service[/url]% `+ u+ a; p2 K& j7 [4 H
#修改
, `1 ]: k- Q0 O+ s/ vEnvironment= CLUSTER=remote6 Z: S* {1 Z, g; t
c. 在remote机器上启动) t! q5 J8 }" i) z7 }1 X6 D( B
systemctl start ceph-rbd-mirror @adminps -ef|grep rbdceph 43251117: 59? 00: 00: 00/usr/bin/rbd-mirror -f --cluster remote --id admin --setuser ceph --setgroup ceph 2.1.7 检查同步结果
/ c; P; ~+ l9 ?* ba. 查询local集群镜像的同步的状态- u8 i. P2 D7 x
#local. q) D# C1 ~1 L7 t  f9 [6 X# h  G
rbd mirror image status test_pool/test_image --cluster remotetest_image: global_id: dabdbbed-7c06-4e1d-b860-8dd104509565 state: up+replaying deion: 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:223 u0 U# \1 g4 I* S; E  U4 @3 o
b. 检查数据是否同步到remote集群
) J" d/ m( k% V) t% p& v! B#remote& z' p9 P( O/ D" Y( N8 E$ p
rbd info test_pool/test_image 2.2 镜像模式 2.2.1 主集群开启jounaling特性
( }( K( m! l  s6 C( U* p启动后会才会记录image的事件,才可以被rbd-mirror检测到并同步到从集群
# s/ Y' c% J# ?7 [# m6 L. X: B#local5 k- K7 X+ ?: o3 ~
rbd feature enabletest_pool/test_image exclusive-lockrbd feature enabletest_pool/test_image journaling 2.2.2 开启存储池的mirror的模式 #local:" ?8 s- f  R+ u- k3 z
rbd mirror pool enabletest_pool image" c* n% q' t6 \5 X' h! j' Z2 }" o3 H
#remote:
4 l; O( H8 c- O3 s6 A4 v; s" I5 G) Wceph osd pool create test_pool 100 100 replicated --cluster=remotepool 'rbdmirror'created rbd mirror pool enabletest_pool image 2.2.3 开启image的mirror #local  P7 B# \& G$ S; o: d9 K! {
rbd mirror image enabletest_pool/test_imageMirroring enabled rbd info test_pool/test_image --cluster= localrbd image 'test_image': size 10240 MB in2560 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: true2.2.4 增加同伴集群
/ O3 X# t- q( |+ J2 Q6 b% @$ L+ b把local和remote设为同伴,这个是为了让rbd-mirror进程找到它peer的集群的存储池:
) m+ y* k3 h4 V. N% I3 Srbd mirror pool peer add test_pool client.admin@remote --cluster= local3 k1 Q- s7 K8 R" T% t9 b
rbd mirror pool peer add test_pool client.admin@ local--cluster=remote
; n/ H& _, ?3 j* n$ \/ C: R4 N#如果需要删除peer 语法:! q9 h2 }; L' E; P* j$ b
rbd mirror pool peer remove <pool-name> <peer-uuid>
! I2 e, t2 k1 \$ O# Y查看peer的情况:
  c9 o, o: A$ J" m% F3 J. _7 @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 localclient.admin 2.2.5 开启rbd-mirror的同步进程
% L, p3 v. q2 ?7 L3 @a. 先用调试模式启动进程看看情况,在remote的机器上执行
- J9 h1 u3 R9 e. D& Q#remote:
& @' [: r" Q9 v. N6 zrbd-mirror -d --setuser ceph --setgroup ceph --cluster remote -i admin- ]8 y9 g8 @( R# T/ i" V
b. 如果确认没问题就用服务来控制启动& Y4 a3 ^! \; s5 Z+ z
#remote' ?1 \- E5 |  W& [; f
vim [url=]/usr/lib/systemd/system/ceph-rbd-mirror@.service[/url]) i# m: U: t: ]+ a, R5 s
#修改
3 v7 t) d& H- N4 f+ G% [Environment= CLUSTER=remote: l' y9 _! W1 x* z( K
c. 在remote机器上启动8 ^- c8 n+ h3 m4 W2 ~0 v
systemctl start ceph-rbd-mirror @adminps -ef|grep rbdceph 43251117: 59? 00: 00: 00/usr/bin/rbd-mirror -f --cluster remote --id admin --setuser ceph --setgroup ceph 2.2.6 检查同步结果
9 f3 i2 `$ ]/ ]$ O2 c6 f5 wa. 查询local集群镜像的同步的状态+ y* |+ ~; h8 o) \
#local
( G, A& T3 A6 g6 |rbd mirror image status test_pool/test_image --cluster remotetest_image: global_id: dabdbbed-7c06-4e1d-b860-8dd104509565 state: up+replaying deion: 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  g1 W' z4 R' O% D8 t
b. 检查数据是否同步到remote集群
% H) M- R. \1 |- }3 S#remote3 f& \; z6 p; y$ o- B! j
rbd info test_pool/test_image 3. 测试对比报告 3.1 单主集群性能 3.1.1 rbd性能测试3 A! Z4 k/ Z: }4 X0 u$ w' _
顺序读写 //block size是4M,30个线程并发 测试结果:30线程并发,带宽:935 MB/s 平均IOPS:228.33
3 y. |$ x. N. g$ @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
# Z% e7 v& [. D/ j& ?随机读写 //block size是4M,30个线程并发 测试结果:30线程并发,带宽:936 MB/s 平均IOPS: 228.574 `( D: P) c7 {. i; q, [: l! m
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 3.2 主备集群性能 3.2.1 rbd性能测试! P0 F  L" E0 [9 \5 \
顺序读写 //block size是4M,30个线程并发 测试结果:30线程并发,带宽:182 MB/s 平均IOPS:44.53' L5 ^2 x. e/ Y0 T* l
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
) P+ z# x* z, P& }随机读写 //block size是4M,30个线程并发 测试结果:30线程并发,带宽:149 MB/s 平均IOPS: 36.50
; Z5 O, q9 T; o% r" `7 Z: w6 ^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 3.3 测试结果5 I5 a0 V) t# J9 T; u
通过测试结果,可以看出启用rbd-mirror 会导致主集群性能下降5倍多。. S# P6 c: q7 y8 B) M% \  m
工具 集群模式 块大小 并发数 顺序读写 随机读写, P; b5 @  w: @; ~, j1 _
rbd bench-write 单主集群 4M 30 带宽:935 MB/s8 g+ I4 q; t/ G6 \8 N! m  |0 o
平均IOPS:228.33
) i7 t( U3 R! l' P3 e5 _) s: }带宽:936 MB/s
) Q. Q5 z, `( I5 a! z平均IOPS: 228.57+ v* _) p% f; p
rbd bench-write 主备集群 4M 30 带宽:182 MB/s7 h5 H- R6 n4 p
平均IOPS:44.536 {; ~0 _7 P4 K
带宽:149 MB/s
* a* o6 C  v1 C( {4 ~& \平均IOPS: 36.50
: `7 S0 t/ y9 ^. R0 a4. 分析原因 4.1 journal流程- ]5 d' U# V6 G: ]9 [; X
当RBD Journal功能打开后,所有的数据更新请求会先写入Image Journal
  E. s: l8 b, v写入成功后,通知客户端
6 Z* n1 N8 S2 Q# ]  W7 X$ U9 `客户端得到响应后,开始写image" ]- f* N: ?7 b+ K4 e. i: T! J
备份集群的mirror进程发现主集群的Journal有更新后,从主集群的Journal读取数据,写入备份集群# P) t- D/ i$ l5 }- n
备份集群写入成功后,会更新主集群Journal中的元数据,表示该I/O的Journal已经同步完成' y; P* m6 J9 s, _# F, i5 c4 K* f
4.2 优化0 C/ f/ A1 n0 m
Use a small SSD/NVMe-backed pool for journals) Z7 T7 j% a/ x, i
‘rbd journal pool = <fast pool name>’5 M, H# r/ j) B8 E' d
Batch multiple events into a single journal append3 Z; @9 t3 a8 a8 ?' S
‘rbd journal object flush age = <seconds>’
9 Q5 q' `% K% m9 |  D& j7 TIncrease journal data width to match queue depth
( d' O; l7 o7 _9 Y7 y, t3 {2 H0 `‘rbd journal splay width = <number of objects>’
5 m5 D- {& g# `+ h3 |, m% \Future work: potentially parallelize journal append + image write between write barriers
4 M- L) \% R& I* O; E7 h1. rbd journal pool 功能没实现sudo ceph daemon osd.0 config setrbd_journal_pool = test_pool3{ "error": "error setting 'rbd_journal_pool' to '= test_pool3': (38) Function not implemented"} 2. 调整参数从10-100,效果不明显rbd_journal_object_flush_age = 100rbd_journal_splay_width = 100 4.3 官方待改进 4.3.1 引入一致性组
; w2 i6 P- `3 {& f$ {8 kjournaling可以看做是另一个rbd的image(一些rados对象),一般情况下,先写日志,然后返回客户端,然后被写入底层的rbd的image,出于性能考虑,这个journal可以跟它的镜像不在一个存储池当中。# u9 X: C; s+ W( l
目前是一个image一个journal,最近应该会沿用这个策略,直到ceph引入一致性组。关于一致性组的概念就是一组卷,然后用的是一个RBD image。可以在所有的组中执行快照操作,有了一致性的保证,所有的卷就都在一致的状态。. y  s2 K- n- W3 y- x
3.当一致性组实现的时候,我们就可以用一个journal来管理所有的RBD的镜像,可以给一个已经存在image开启journal,ceph将会将你的镜像做一个快照,然后对快照做一个复制,然后开启journal,这都是后台执行的一个任务可以启用和关闭单个镜像或者存储池的mirror功能,
3 ~) ?1 D  l; |5 U5 U/ E7 V- {. B如果启用了journal功能,那么每个镜像将会被复制可以使用 rbd mirror pool enable启用它。% n  C5 e  p, u' r6 ?5 M
4.3.2 并行写2 D) G$ M1 c3 l' \3 B- E' T  U5 e
Future work: potentially parallelize journal append + image write between write barriers: D/ b1 t2 @! o+ _
参考官方文档如下:8 ^* |. _4 P* y( v( ]3 D
官方类似问题:https://www.spinics.net/lists/ceph-users/msg31676.html! Q0 a) a, Y! |2 m/ {
4.4 结论& x- d) ~$ \( @, R4 z( X
由于核心流程就是先写日志,然后写image需要写两份的逻辑,所以导致性能就会有损失。
0 E( c7 i+ ?  D  n( j根据官方的参数优化也没有明显的效果,建议等待官方更新features。4 K* N6 n  u& q4 I
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-12 00:07 , Processed in 0.034378 second(s), 25 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表