【星控】基于 Butterfly 框架 + raft 协议实现一个 Redis 集群的管控服务
+---------+ +---------+ +---------+ +-------------------+
|twemproxy| |twemproxy| |twemproxy| | |
+---------+ +---------+ +---------+ \ | +-------------+ |
| \ / \ / | \ | |cfg primary | |
| \ / \ / | \ | +-------------+ |
| X X | \ | |
| / \ / \ | \| +-------------+ |
| / \ / \ | | |cfg secondary| |
+------------------+ +------------------+ /| +-------------+ |
| +--------+ | | +--------+ | / | |
| | master | | | | master | | / | +-------------+ |
| +--------+ | | +--------+ | / | |cfg secondary| |
| +-----+ +-----+ | | +-----+ +-----+ | / | +-------------+ |
| |slave| |slave| | | |slave| |slave| | | |
| +-----+ +-----+ | | +-----+ +-----+ | | |
+------------------+ +------------------+ +-------------------+
仅管理单地域 Redis 集群,并保证高可靠性和高可用性。
- 路由管理
- 单机止损
- 集群扩缩容
- 配置管理
https://github.com/meetbill/cc
Controller 工作在地域级别,往往一个地域有多个逻辑机房或物理机房,一个地域可以部署多个 controller,但是同一地域内只有一个实际工作。
当实际工作的 controller 挂掉后,集群会进行重新选择新主。
功能
节点读写权限控制
节点主从切换
主故障自动选主
从故障自动封禁
数据迁移控制
数据 Rebalance
拓扑信息由 redis cluster 进行维护
感知层及决策层由 redis cluster 处理
cc 获取一致的拓扑信息,然后进行执行操作,即 cc 主要负责执行层
通过下发命令到 redis cluster 集群进行迁移 slot 进行扩缩容
管理集群相关的配置,比如是否进行从库自动封禁,是否自动切主
拓扑信息在 redis cluster 中,本身是无状态节点,通过主备方式实现(部署多个节点,然后在 zookeeper 上进行注册抢主)
https://github.com/mongodb/mongo
https://github.com/ksarch-saas/cfgServer
强一致模型
- 优点是社区实现很多,开发成本低,控制模块集群规模较小,性能可接受
- 缺点是跨地域支持较差
当 Redis 集群主实例故障时,cfgServer 需要执行切主操作,所以需要进行区分主从,通过外部依赖进行选主。租约 + 锁的形式实现简单高效
多个 CfgServer 均可正常进行读写,只是由 cfgServer 执行操作的模块需要抢主进行单一操作
Proxy 需要获取集群拓扑信息,业界有很多实现,可以分为两类。
- 第一类主动更新,Proxy 主动拉取信息
- 第二类被动更新,cfgServer 发现变化后通知 Proxy 更新
备注:启动 Proxy 时,需要拉取到 topo 信息
折衷考虑,选择被动更新方式,通过版本号区分是否需要更新
MetaDB 用于存放 topo 数据以及配置数据,可以使用如下方式实现
- 自研模块:基于 https://github.com/bakwc/PySyncObj 上实现 raft 模块
- MongoDB : 自带副本集,可保障强一致性和自身高可用
- Redis : 主从模式,无法保障自身高可用,如果是多地域管控需求时,可以使用此方式
MongoDB 副本集,可以保障自身高可用,可满足需求,故选择使用 MongoDB
两种方式
集群间数据相互同步,用户读写都走本地域,出现地域故障时,用户切流到其他地域
+---------+ +---------+ +---------+ +-------------------+
|twemproxy| |twemproxy| |twemproxy| | |
+---------+ +---------+ +---------+ \ | +-------------+ |
| \ / \ / | \ | |cfg primary | |
| \ / \ / | \ | +-------------+ |
| X X | \ | |
| / \ / \ | \| +-------------+ |
| / \ / \ | | |cfg secondary| | BJ 地域
+------------------+ +------------------+ /| +-------------+ |
| +--------+ | | +--------+ | / | |
| | master | | | | master | | / | +-------------+ |
| +--------+ | | +--------+ | / | |cfg secondary| |
| +-----+ +-----+ | | +-----+ +-----+ | / | +-------------+ |
| |slave| |slave| | | |slave| |slave| | | |
| +-----+ +-----+ | | +-----+ +-----+ | | |
+------------------+ +------------------+ +-------------------+
----------------------------------------------------------------------------------------------------
^ ^ ^
| | |
| | | 集群中数据相互同步
| | |
V V V
----------------------------------------------------------------------------------------------------
+---------+ +---------+ +---------+ +-------------------+
|twemproxy| |twemproxy| |twemproxy| | |
+---------+ +---------+ +---------+ \ | +-------------+ |
| \ / \ / | \ | |cfg primary | |
| \ / \ / | \ | +-------------+ |
| X X | \ | |
| / \ / \ | \| +-------------+ |
| / \ / \ | | |cfg secondary| | NJ 地域
+------------------+ +------------------+ /| +-------------+ |
| +--------+ | | +--------+ | / | |
| | master | | | | master | | / | +-------------+ |
| +--------+ | | +--------+ | / | |cfg secondary| |
| +-----+ +-----+ | | +-----+ +-----+ | / | +-------------+ |
| |slave| |slave| | | |slave| |slave| | | |
| +-----+ +-----+ | | +-----+ +-----+ | | |
+------------------+ +------------------+ +-------------------+
集群间数据同步的方案有很多,比如:
- 业务侧多写
- 业务方需要自行实现数据分发功能,写入到 MQ,对业务有较大侵入
- Netflix 开源实现的 dynomite,通过代理层接受数据后写入各个需要同步的节点
- 可以在 twemproxy 上实现多写,写跨地域时写入到队列中,然后 worker 进程读队列中内容写跨地域
- 模拟从库拉取各地域主库数据,然后写到跨地域集群
- 数据同步如何实现防环
- 通过读取主库的 AOF,然后同步数据到跨地域集群
- AOF 切割
- 数据同步如何实现防环
- 等等,方案很多
+---------+ +---------+ +---------+ +-------------------+
|twemproxy| |twemproxy| |twemproxy| | |
+---------+ +---------+ +---------+ \ | +-------------+ |
| \ / \ / | \ | |cfg primary | |
| \ / \ / | \ | +-------------+ |
| X X | \ | |
| / \ / \ | \| +-------------+ |
| / \ / \ | | |cfg secondary| | BJ 地域
+------------------+ +------------------+ /| +-------------+ |
| +--------+ | | +--------+ | / | |
| | master | | | | master | | / | +-------------+ |
| +--------+ | | +--------+ | / | |cfg secondary| |
| +-----+ +-----+ | | +-----+ +-----+ | / | +-------------+ |
| |slave| |slave| | | |slave| |slave| | | |
| +-----+ +-----+ | | +-----+ +-----+ | | |
| | | | +-------------------+
| | | |
| +-----+ +-----+ | | +-----+ +-----+ | +-------------------+
| |slave| |slave| | | |slave| |slave| | | |
| +-----+ +-----+ | | +-----+ +-----+ | | cfg primary | NJ 地域
| | | | | cfg secondary |
| | | | | cfg secondary |
+------------------+ +------------------+ +-------------------+
twemproxy 中写都写到主地域 master,读本地域 slave
cfgServer + metaDB 方式,将计算与数据分离