|
|
个人主要关注的技术领域:高性能Nginx开发、分布式缓存、分布式存储。
( W, k7 d$ m! L' U% z( [6 F1.说明介绍 1.1 基本原理
. c6 `# b7 `& [2 f% Y. u$ SRBD Mirror原理其实和MySQL的主从同步原理非常类似,前者基于journaling,后者基于binlog,简单地说就是利用日志进行回放(replay):通过在存储系统中增加Mirror组件,采用异步复制的方式,实现异地备份。(此处的journal是指Ceph RBD的journal,而不是OSD的journal)
6 I& l+ H1 c4 b该能力利用了 RBD image 的日志特性,以确保集群间的副本崩溃一致性。镜像功能需要在同伴集群( peer clusters )中的每一个对应的 pool 上进行配置,可设定自动备份某个存储池内的所有 images 或仅备份 images 的一个特定子集。 rbd-mirror 守护进程负责从远端集群拉取 image 的更新,并写入本地集群的对应 image 中。, J& f* u$ Q! E8 Y
当RBD Journal功能打开后,所有的数据更新请求会先写入RBD Journal,然后后台线程再把数据从Journal区域刷新到对应的image区域。RBD journal提供了比较完整的日志记录、读取、变更通知以及日志回收和空间释放等功能,可以认为是一个分布式的日志系统。
1 K( k+ C8 V' U" L( h$ C, ?! |1.2 工作流程- ^: [+ }3 a c, s) A A* Z5 I
( o9 J9 @0 V# p# z( \- Q- J/ a* K1、当接收到一个写入请求后,I/O会先写入主集群的Image Journal
/ u* P! C; S. y4 f% q% f; J9 b8 L2、Journal写入成功后,通知客户端
0 C1 j* H6 `' I2 r0 i0 ?2 r8 h. R3、客户端得到响应后,开始写入image# u7 D* @7 R$ |
3、备份集群的mirror进程发现主集群的Journal有更新后,从主集群的Journal读取数据,写入备份集群(和上面序号一样,是因为这两个过程同时发生)
9 m- S. A7 Z, ]7 J5 K, d7 t a0 C4、备份集群写入成功后,会更新主集群Journal中的元数据,表示该I/O的Journal已经同步完成# @/ G( J8 K( K9 _8 H: u; H# d6 Z
5、主集群会定期检查,删除已经写入备份集群的Journal数据。. H' a3 v$ N* B. m& D+ W a
以上就是一个rbd-mirror工作周期内的流程,在现有的Jewel版本中30s为一次工作周期,暂时不能改变这个周期时间。! X: @9 X& D8 o9 g0 l
1.3 优点
$ {& N/ T& n3 D c* h1、当副本在异地的情况下,减少了单个集群不同节点间的数据写入延时;
2 F$ ~. Z$ ?* u" [" N2 Z$ p2、减少本地集群或异地集群由于意外断电导致的数据丢失。
8 _1 j1 A( V- _5 P9 P$ s1.4 单向备份与双向备份
, b' d1 E2 ?# T$ t3 ?1 M) n3 Y双向备份:两个集群之间互相同步,两个集群都要运行rbd-mirror进程。; d3 E$ u b5 k& r/ ]
单向备份:分为主集群和从集群,只在从集群运行rbd-mirror进程,主集群的修改会自动同步到从集群。1 S6 ]: j7 Y$ M3 l F
1.5 安装须知
7 w ]0 w! T& q2 d2 QRBD 镜像功能需要 Ceph Jewel 或更新的发行版本。
7 p/ |$ n- O0 k1 J. N! u; ~目前Jewel版本只支持一对一,不支持一对多。
$ r6 m( G4 i+ Z( O9 @1 A7 o f两个集群 (local和remote) 需要能够互通。
# |. g* j+ M" PRBD需要开启journal特性, 启动后会记录image的事件。
6 t- R- x) l2 K# F8 Z$ R8 m2. mirroring 模式' {* c' o. Z& G" x( {( N' @
mirroring是基于存储池进行的peer,ceph支持两种模式的镜像,根据镜像来划分有:1 ?# R4 `7 E7 R7 r- g3 l% W+ e
存储池模式. I$ ~# A4 ]/ ^3 o' d2 ~+ z
一个存储池内的所有镜像都会进行备份
" _, A( R, U, V5 ?镜像模式
. M3 W' ?6 `! i+ |$ K只有指定的镜像才会进行备份/ [' r/ v8 B" z3 {* M! d( Z! g, C
2.1 存储池模式 2.1.1 创建存储池
+ R! m0 |# i6 ^6 [; c3 h: c创建一个用于测试的存储池:
: v3 I& L8 w/ n2 Q& l, ~#local集群! w X4 b$ g4 E3 a
ceph osd pool create test_pool 100 100 replicated --cluster= localpool 'test_pool'created
; u2 P& X$ A' d; a- S3 k3 y/ p1 @1 O#remote集群 Z9 D/ x7 v5 T" E, ~3 K8 { x
ceph osd pool create test_pool 100 100 replicated --cluster=remotepool 'test_pool'created 2.1.2 启用存储池模式& @( p( d5 |6 o1 D( `
开启存储池rbdmirror的镜像功能:3 P( r8 z' r* U! U* f" s3 T
#local集群
4 y8 C- ]" I" q1 [5 drbd mirror pool enabletest_pool pool --cluster= local
& O7 e8 t2 S- S1 @, C+ y! {$ ^#remote集群
$ I9 T/ N1 F6 L: I+ K3 G2 Q$ Hrbd mirror pool enabletest_pool pool --cluster=remote 2.1.3 创建RBD
1 E8 y8 N, U) L) Q9 V$ r0 O8 s+ ]主集群创建一个测试用的RBD:
9 Q# f* ]7 x, prbd create test_pool/test_image --size=1024 --cluster= local2.1.4 主集群开启jounaling特性
/ h* h, f4 M$ H" T; ]* v9 n启动后会才会记录image的事件,才可以被rbd-mirror检测到并同步到从集群:
' n7 o$ v9 C: {+ X. prbd feature enabletest_pool/test_image exclusive-lockrbd feature enabletest_pool/test_image journaling 2.1.5. 增加同伴集群/ B1 |' p5 k& u8 w
把local和remote设为同伴,这个是为了让rbd-mirror进程找到它peer的集群的存储池:" U. G2 L2 ]" @; K0 \
rbd mirror pool peer add test_pool client.admin@remote --cluster= local
3 F5 r5 U7 C* P. h; x0 wrbd mirror pool peer add test_pool client.admin@ local--cluster=remote! s: g. v$ y C. S1 P
#如果需要删除peer 语法:
% A; Z9 J5 ?9 V* |4 s8 z& yrbd mirror pool peer remove <pool-name> <peer-uuid>
& j- B9 J# t9 a' I6 a$ q! x查看peer的情况:( q/ Q% M1 q* D8 Z/ o9 M
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.1.6 开启rbd-mirror的同步进程
: M: z" U+ F. c5 ?% i+ I/ va. 先用调试模式启动进程看看情况,在remote的机器上执行
' H7 Z( c, V' b/ q5 y, ] l#remote:
# P3 W1 t; h: T! d3 }3 O. F. C7 zrbd-mirror -d --setuser ceph --setgroup ceph --cluster remote -i admin
2 X$ A* X/ A' S. K5 ?# S& ob. 如果确认没问题就用服务来控制启动' K. P: B8 _( h3 s7 m @- N& ?+ w
#remote) @( {7 h2 p! d' e/ X
vim [url=]/usr/lib/systemd/system/ceph-rbd-mirror@.service[/url]' A. C5 l& _2 p) i
#修改& V( D3 z; d" `
Environment= CLUSTER=remote4 l( U4 \/ h" p) d& | K
c. 在remote机器上启动/ X! H, }3 |- N" Y" y' |6 k5 q- U4 E
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 检查同步结果& _9 d9 X# F9 K G
a. 查询local集群镜像的同步的状态
: N; }: h( A, ?$ X( M9 j#local
, g6 ], g# p0 h6 t- Mrbd 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 T3 I) I. X. Y7 J2 r( i8 y
b. 检查数据是否同步到remote集群
/ C3 G8 q4 l" G4 o( j t; H#remote
% X& m4 C" q+ T7 ~: _3 Xrbd info test_pool/test_image 2.2 镜像模式 2.2.1 主集群开启jounaling特性8 c H( }' c4 D- P" B
启动后会才会记录image的事件,才可以被rbd-mirror检测到并同步到从集群4 \2 P; _" K3 E" `7 _# n
#local
4 T& g- N8 s2 c Vrbd feature enabletest_pool/test_image exclusive-lockrbd feature enabletest_pool/test_image journaling 2.2.2 开启存储池的mirror的模式 #local:
/ X7 ?( S. W% T8 o4 o: P! Orbd mirror pool enabletest_pool image d0 [8 b. w# X! C! V% v
#remote:+ }; K7 h! j! F" A
ceph osd pool create test_pool 100 100 replicated --cluster=remotepool 'rbdmirror'created rbd mirror pool enabletest_pool image 2.2.3 开启image的mirror #local
5 u6 R+ G) f; I# `; crbd 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 增加同伴集群2 }% L. {5 r% ?
把local和remote设为同伴,这个是为了让rbd-mirror进程找到它peer的集群的存储池:
# v" f2 T+ e$ ?0 _! ^4 mrbd mirror pool peer add test_pool client.admin@remote --cluster= local% S; K. |, X2 G1 m
rbd mirror pool peer add test_pool client.admin@ local--cluster=remote$ t7 {/ H6 |# A; i
#如果需要删除peer 语法:
* H Q4 b5 l* i$ t# G7 wrbd mirror pool peer remove <pool-name> <peer-uuid>, b0 P) C1 A+ d6 m% I, r
查看peer的情况:
+ J& q$ @- ]8 p. n7 F+ |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的同步进程
# ?% D; ^) d' }( Ua. 先用调试模式启动进程看看情况,在remote的机器上执行6 w9 }7 o F4 m+ }7 K
#remote:
3 K1 u% a/ r5 U1 s# R: zrbd-mirror -d --setuser ceph --setgroup ceph --cluster remote -i admin1 l/ @8 S1 B6 N+ c: D0 Z4 p
b. 如果确认没问题就用服务来控制启动
9 i6 F# j; ?" u- f: `#remote
# f. q; l- A& S; n" D1 jvim [url=]/usr/lib/systemd/system/ceph-rbd-mirror@.service[/url]
+ B0 Z* ?+ q# Y& a' A1 K! T) l#修改" g2 k2 R( Y# Z
Environment= CLUSTER=remote
# z1 i" Y8 @! q$ e# [# yc. 在remote机器上启动
$ b% t+ C$ j1 n5 i/ R% Usystemctl 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 z0 x5 N" i& ]4 E6 `* Ya. 查询local集群镜像的同步的状态$ b' d. i4 S1 S! I
#local& B+ l* s# K7 t9 L
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& U. g7 C x+ x5 E2 W. B+ V u
b. 检查数据是否同步到remote集群 T$ z* |& F9 O4 [, r) S9 J. g( @
#remote; e/ T# H+ P& V$ ]4 i
rbd info test_pool/test_image 3. 测试对比报告 3.1 单主集群性能 3.1.1 rbd性能测试
9 F L( @3 E% U! A- ^- F( y顺序读写 //block size是4M,30个线程并发 测试结果:30线程并发,带宽:935 MB/s 平均IOPS:228.33
# h2 M2 d* [: B" V8 _# frbd 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
, K, r# m6 Y1 I; H( @4 ?随机读写 //block size是4M,30个线程并发 测试结果:30线程并发,带宽:936 MB/s 平均IOPS: 228.57
% I* N4 @3 y6 t2 s; ]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性能测试
# J! g: N2 m$ g* h' g顺序读写 //block size是4M,30个线程并发 测试结果:30线程并发,带宽:182 MB/s 平均IOPS:44.53
) Q3 w9 D: q- S1 F& g9 ?0 Y% srbd 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. `9 D2 L* ?- M# h: x' p$ {! u) }
随机读写 //block size是4M,30个线程并发 测试结果:30线程并发,带宽:149 MB/s 平均IOPS: 36.501 x+ |; v* y8 c# s! c5 t( b
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 测试结果& ^! c- I- n+ v) p8 g2 K4 l
通过测试结果,可以看出启用rbd-mirror 会导致主集群性能下降5倍多。7 S. v2 s* n5 M! l+ ~- x" j
工具 集群模式 块大小 并发数 顺序读写 随机读写5 E; |8 {: d6 W9 V3 K7 [
rbd bench-write 单主集群 4M 30 带宽:935 MB/s
2 d, Y% S9 W7 A9 V/ W% q平均IOPS:228.339 J/ g6 F( `* v/ G- G- ?
带宽:936 MB/s7 K6 I& |7 c& G+ z
平均IOPS: 228.57& N% i. b8 C; R
rbd bench-write 主备集群 4M 30 带宽:182 MB/s8 e, R$ b- E6 e1 A* f9 X# x
平均IOPS:44.53
0 {6 e, A: B& b! n+ N! @! z) M1 c带宽:149 MB/s
9 ?9 a c( y, @8 s平均IOPS: 36.50
4 A3 E! J- _+ W5 a( O5 }4. 分析原因 4.1 journal流程" E3 `3 @ L# L6 @7 x' M
当RBD Journal功能打开后,所有的数据更新请求会先写入Image Journal' F( q, \& P, n- k5 t# n% P
写入成功后,通知客户端 \- V( k% W j: w; N
客户端得到响应后,开始写image1 R' g1 I, F5 U, E% d1 e7 k
备份集群的mirror进程发现主集群的Journal有更新后,从主集群的Journal读取数据,写入备份集群
! n8 I' y2 C! ?0 T- Y# J1 B) k备份集群写入成功后,会更新主集群Journal中的元数据,表示该I/O的Journal已经同步完成5 D0 v8 A+ |9 \" I
4.2 优化; X/ W: C9 z3 @% \0 e3 Y8 X
Use a small SSD/NVMe-backed pool for journals
. `& V. o- u! |, B+ c5 O. R- e" y‘rbd journal pool = <fast pool name>’, \5 x. O8 Z" q/ z/ x# I
Batch multiple events into a single journal append& n+ {2 g: K+ W! \+ \7 L! j# q/ r
‘rbd journal object flush age = <seconds>’3 ]" B+ q' o% l
Increase journal data width to match queue depth/ d* ~) q( [4 c f( O9 T3 c
‘rbd journal splay width = <number of objects>’) e4 ~3 T; _: w8 W ]% c# o7 [' d
Future work: potentially parallelize journal append + image write between write barriers
( N& D: ~! `$ g! m: B1. 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 引入一致性组( P$ K0 y/ r+ N! U, i& R7 P
journaling可以看做是另一个rbd的image(一些rados对象),一般情况下,先写日志,然后返回客户端,然后被写入底层的rbd的image,出于性能考虑,这个journal可以跟它的镜像不在一个存储池当中。
: d2 }1 r, B/ i3 s5 W2 o目前是一个image一个journal,最近应该会沿用这个策略,直到ceph引入一致性组。关于一致性组的概念就是一组卷,然后用的是一个RBD image。可以在所有的组中执行快照操作,有了一致性的保证,所有的卷就都在一致的状态。
- z! q. _2 `. y2 w* |3.当一致性组实现的时候,我们就可以用一个journal来管理所有的RBD的镜像,可以给一个已经存在image开启journal,ceph将会将你的镜像做一个快照,然后对快照做一个复制,然后开启journal,这都是后台执行的一个任务可以启用和关闭单个镜像或者存储池的mirror功能,
, x9 x9 `* s ^. W4 B$ d9 S如果启用了journal功能,那么每个镜像将会被复制可以使用 rbd mirror pool enable启用它。
5 D6 J! S" Y: e2 j# f3 J5 s" j4.3.2 并行写
' H+ y; ~8 l: _7 Y& M+ U. S6 JFuture work: potentially parallelize journal append + image write between write barriers6 T7 |; n2 z: p
参考官方文档如下:6 @) ~# Z N8 k8 Y9 g6 G
官方类似问题:https://www.spinics.net/lists/ceph-users/msg31676.html
3 k) m5 R. {7 y( y! W Q, F4.4 结论$ b7 y Q( {% G! Z4 U: M2 G: b# m
由于核心流程就是先写日志,然后写image需要写两份的逻辑,所以导致性能就会有损失。 u! l! R/ T, Y5 l
根据官方的参数优化也没有明显的效果,建议等待官方更新features。, Y, X7 R, ~" \
|
|