本期推荐的是一个由携程框架部门研发的Redis多数据中心复制管理系统——X-Pipe。
Redis 在携程内部得到了广泛的使用,根据客户端数据统计,整个携程全部 Redis 的读写请求在每秒 2000W,其中写请求约 100W,很多业务甚至会将 Redis 当成持久化的内存数据库使用。这样,就对 Redis 多数据中心提出了很大的需求,一是为了提升可用性,解决数据中心 DR(Disaster Recovery) 问题,二是提升访问性能,每个数据中心可以读取当前数据中心的数据,无需跨机房读数据,在这样的需求下,XPipe 应运而生 。
为了方便描述,后面用 DC 代表数据中心 (Data Center)。
整体架构
- Console 用来管理多机房的元信息数据,同时提供用户界面,供用户进行配置和 DR 切换等操作。
- Keeper 负责缓存 Redis 操作日志,并对跨机房传输进行压缩、加密等处理。
- Meta Server 管理单机房内的所有 keeper 状态,并对异常状态进行纠正。
Redis 数据复制问题
多数据中心首先要解决的是数据复制问题,即数据如何从一个 DC 传输到另外一个 DC。我们决定采用伪 slave 的方案,即实现 Redis 协议,伪装成为 Redis slave,让 Redis master 推送数据至伪 slave。这个伪 slave,我们把它称为 keeper,如下图所示:
使用 keeper 带来的优势:
- 减少 master 全量同步
如果异地机房 slave 直接连向 master,多个 slave 会导致 master 多次全量同步,而 keeper 可以缓存 rdb 和 replication log,异地机房的 slave 直接从 keeper 获取数据,增强 master 的稳定性。
- 减少多数据中心网络流量
在两个数据中心之间,数据只需要通过 keeper 传输一次,且 keeper 之间传输协议可以自定义,方便支持压缩 (目前暂未支持)。
- 网络异常时减少全量同步
keeper 将 Redis 日志数据缓存到磁盘,这样,可以缓存大量的日志数据 (Redis 将数据缓存到内存 ring buffer,容量有限),当数据中心之间的网络出现较长时间异常时仍然可以续传日志数据。
- 安全性提升
多个机房之间的数据传输往往需要通过公网进行,这样数据的安全性变得极为重要,keeper 之间的数据传输也可以加密 (暂未实现),提升安全性。
机房切换流程
- 检查是否可以进行 DR 切换
类似于 2PC 协议,首先进行 prepare,保证流程能顺利进行。
- 原主机房 master 禁止写入
此步骤,保证在迁移的过程中,只有一个 master,解决在迁移过程中可能存在的数据丢失情况。
- 提升新主机房 master
- 其它机房向新主机房同步
同时提供回滚和重试功能。回滚功能可以回滚到初始的状态,重试功能可以在 DBA 人工介入的前提下,修复异常条件,继续进行切换。
高可用
XPipe 系统高可用
如果 keeper 挂掉,多数据中心之间的数据传输可能会中断,为了解决这个问题,keeper 有主备两个节点,备节点实时从主节点复制数据,当主节点挂掉后,备节点会被提升为主节点,代替主节点进行服务。
提升的操作需要通过第三方节点进行,我们把它称之为 MetaServer,主要负责 keeper 状态的转化以及机房内部元信息的存储。同时 MetaServer 也要做到高可用:每个 MetaServer 负责特定的 Redis 集群,当有 MetaServer 节点挂掉时,其负责的 Redis 集群将由其它节点接替;如果整个集群中有新的节点接入,则会自动进行一次负载均衡,将部分集群移交到此新节点。
Redis 自身高可用
Redis 也可能会挂,Redis 本身提供哨兵 (Sentinel) 机制保证集群的高可用。但是在 Redis4.0 版本之前,提升新的 master 后,其它节点连到此节点后都会进行全量同步,全量同步时,slave 会处于不可用状态;master 将会导出 rdb,降低 master 的可用性;同时由于集群中有大量数据 (RDB) 传输,将会导致整体系统的不稳定。
截止当前文章书写之时,4.0 仍然没有发布 release 版本,而且携程内部使用的 Redis 版本为 2.8.19,如果升到 4.0,版本跨度太大,基于此,我们在 Redis3.0.7 的版本基础上进行优化,实现了 psync2.0 协议,实现了增量同步。
测试数据
测试方案
测试方式如下图所示。从 client 发送数据至 master,并且 slave 通过 keyspace notification 的方式通知到 client,整个测试延时时间为 t1+t2+t3。
测试数据
首先我们测试 Redis master 直接复制到 slave 的延时,为 0.2ms。然后在 master 和 slave 之间增加一层 keeper,整体延时增加 0.1ms,到 0.3ms。
在携程生产环境进行了测试,生产环境两个机房之间的 ping RTT 约为 0.61ms,经过跨数据中心的两层 keeper 后,测试得到的平均延时约为 0.8ms,延时 99.9 线为 2ms。
docker快速启动
1 启动准备
- 需要提前启动docker进程,且支持docker-compose
- 新建一个路径,在该路径下启动(建议)
2 启动docker
- 方式一:启动dockerhub上的镜像
/bin/bash -c "$(curl -sSL https://raw.githubusercontent.com/ctripcorp/x-pipe/master/redis/dockerPackage/start-xpipe-container.sh)"
启动后的容器分布
执行命令:docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1e77491414a9 ctripcorpxpipe/xpipe-console:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:8079->8080/tcp, :::8079->8080/tcp consolejq
6694f9eff0ad ctripcorpxpipe/xpipe-console:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:8081->8080/tcp, :::8081->8080/tcp consoleoy
aa0d109c7aae ctripcorpxpipe/xpipe-meta:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:9747->8080/tcp, :::9747->8080/tcp metajq
0c6cb6dfe51f ctripcorpxpipe/xpipe-meta:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:9748->8080/tcp, :::9748->8080/tcp metaoy
0e0f78ae096d ctripcorpxpipe/xpipe-keeper:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:7080->8080/tcp, :::7080->8080/tcp keeperjq1
16c5fdd14a5e ctripcorpxpipe/xpipe-keeper:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:7081->8080/tcp, :::7081->8080/tcp keeperjq2
1915292f3a7f ctripcorpxpipe/xpipe-keeper:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:7180->8080/tcp, :::7180->8080/tcp keeperoy1
0c885945d8f3 ctripcorpxpipe/xpipe-keeper:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:7181->8080/tcp, :::7181->8080/tcp keeperoy2
15062ab45feb ctripcorpxpipe/xpipe-proxy:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:19079->80/tcp, :::19079->80/tcp, 0.0.0.0:19442->443/tcp, :::19442->443/tcp, 0.0.0.0:8092->8080/tcp, :::8092->8080/tcp proxyjq
ed38daf8e71e ctripcorpxpipe/xpipe-proxy:1.0 "docker-entrypoint.sh" 3 days ago Up 3 days 0.0.0.0:19081->80/tcp, :::19081->80/tcp, 0.0.0.0:19444->443/tcp, :::19444->443/tcp, 0.0.0.0:8091->8080/tcp, :::8091->8080/tcp proxyoy
d0e811ea5d3d zookeeper "/docker-entrypoint.…" 3 days ago Up 3 days 2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp, :::2181->2181/tcp, 8080/tcp zoo1
41381b5bd3a9 zookeeper "/docker-entrypoint.…" 3 days ago Up 3 days 2888/tcp, 3888/tcp, 8080/tcp, 0.0.0.0:2182->2181/tcp, :::2182->2181/tcp zoo2
d5f85ee0360e ctripcorpxpipe/xpipe-mysql:2.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
ba2b64f10700 redis:4.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:6379->6379/tcp, :::6379->6379/tcp redis-6379
4687df7ac486 redis:4.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:6479->6379/tcp, :::6479->6379/tcp redis-6479
58cfdf41284a redis:4.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:6579->6379/tcp, :::6579->6379/tcp redis-6579
d180471bb010 redis:4.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:6679->6379/tcp, :::6679->6379/tcp redis-6679
4539be899dd3 redis:4.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:7379->6379/tcp, :::7379->6379/tcp redis-7379
dcf1b8079c1e redis:4.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:7479->6379/tcp, :::7479->6379/tcp redis-7479
180a2255d038 redis:4.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:7579->6379/tcp, :::7579->6379/tcp redis-7579
a877a83287b4 redis:4.0 "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:7679->6379/tcp, :::7679->6379/tcp redis-7679
- 方式二:根据最新代码编译本地镜像再启动
3 验证
- 数据复制
测试master中数据是否能同步到备机房redis:
1、如果本地未安装reids, 则随机进入一台redis容器
docker exec -ti redis-6379 bash
2、连接主机房master redis 并添加数据后退出
`redis-cli -h 172.19.0.10
set test1 12345`
3、连接备机房slave redis 获取数据成功后退出
`redis-cli -h 172.19.0.13
get test1`
4、例子
song@ubuntu:~/yusong/code/test$ docker exec -ti redis-6379 bash
root@c568933bae57:/data# redis-cli -h 172.19.0.10
172.19.0.10:6379> set test1 12345
OK
172.19.0.10:6379> exit
root@c568933bae57:/data# redis-cli -h 172.19.0.13
172.19.0.13:6379> get test1
"12345"
172.19.0.13:6379> exit
- 延迟监测
启动浏览器,进入localhost:8079/#
/cluster_dc_shards/cluster1 查看各个redis的状态指示均为绿色
- 迁移功能
1、在cluster_list页面找到该cluster,点击迁移
2、选择待迁移cluster和目标机房
3、执行迁移
4、查看迁移是否成功
4 停止
docker-compose down
—END—
开源协议:Apache 2.0