文章目录

  • 一、背景
  • 二、坑点
  • 三、难点
  • 四、解决
  • 4.1 离线安装redis-trib环境
  • 4.2 解决中断```redis-trib rebalance```命令后槽位的修复问题
  • 4.2.1 动态扩容的过程
  • 4.2.2 ```redis-trib```的执行原理
  • 4.2.3 实战记录
  • 五、后续


一、背景

  • 业务用户的增长,redis集群内存使用越来越大
  • 集群单节点的内存限额已经很大了(17GB),不能单纯的通过调整节点内存限额来扩容
  • 不能纵向扩容,那就横向扩容

二、坑点

  • 因为海外网络的原因,导致使用redis-trib reblance进行动态扩容时很慢
  • 本地机房10分钟迁完一个节点的槽位,海外跨机房10个小时才能迁完一个节点
  • 又不敢中断,怕中断后槽位分配出现问题,之后很难调整

从早上10点迁到晚上8点才迁完一个节点的,实在是慢的不行;还考虑到万一夜里进程挂掉了,那时候处理起来更麻烦了。

所以决定主动出击,把问题尽快解决,为业务减少点损失,也给自己找条生路…

三、难点

这个问题主要是有两个难点:

  • 怎么在海外机器上离线搭建redis-trib.rb环境(生产环境中的服务器不能连外网,不好直接下载东西)
  • 中断redis-trib rebalance命令后,槽位分配万一出现问题,要怎么修复

四、解决

4.1 离线安装redis-trib环境

离线安装环境的主要参考如下:



还有一个的难点就是传文件,我这边的办法是:

  • 先将需要的安装包下载到本地
  • 然后通过终端,直接将文件拖动上传到内网办公的服务器
  • 在服务器上使用nc命令将安装包发送到海外的服务器上

4.2 解决中断redis-trib rebalance命令后槽位的修复问题

要解决redis-trib rebalance中断后的问题,首先得知道动态扩容涉及到的过程,以及redis-trib的执行原理。

4.2.1 动态扩容的过程
  • 准备新节点
  • 提前准备好新节点并运行在集群模式下
  • 建议使用相同的配置文件,便于管理
  • 加入集群
  • 可用cluster meet命令
  • 也可用redis-trib.rb add-node命令
  • 线上环境建议使用redis-trib.rb add-node命令添加,避免将新节点加入到其他集群,造成集群‘融合’,导致数据丢失
  • 迁移槽和数据
  • 槽迁移计划
  • 迁移数据
  • 对目标节点发送cluster setslot{slot}importing{sourceNodeId}命令,让目标节点准备导入槽的数据
  • 对源节点发送cluster setslot{slot}migrating{targetNodeId}命令,让源节点准备迁出槽的数据
  • 源节点循环执行cluster getkeysinslot{slot}{count}命令,获取count个属于槽{slot}的键
  • 在源节点上执行migrate{targetIp}{targetPort}""0{timeout}keys{keys…}命令,把获取的键通过流水线(pipeline)机制批量迁移到目标节点,批量迁移版本的migrate命令在Redis3.0.6以上版本提供,之前的migrate命令只能单个键迁移。对于大量key的场景,批量键迁移将极大降低节点之间网络IO次数
  • 重复执行上述两个步骤,直到槽下所有的键值数据迁移到目标节点
  • 向集群内所有主节点发送cluster setslot{slot}node{targetNodeId}命令,通知槽分配给目标节点。为了保证槽节点映射变更及时传播,需要遍历发送给所有主节点更新被迁移的槽指向新节点
  • 添加从节点
  • 使用cluster replicate{masterNodeId}命令为主节点添加对应从节点
4.2.2 redis-trib的执行原理

主要参考如下:


4.2.3 实战记录

在了解了redis集群的动态扩容原理以及redis-trib的具体实现过程后,先在测试集群上做了实验,发现redis-trib.rb fix ip:port是能修复rebalance中断导致的槽位问题,所以就开始在线上开始操作。

  • 按下Ctrl+c中断redis-trib.rb rebalance进程
  • 使用redis-triib.rb check检查集群的状态(发现23号槽位还在处理开放的状态)
...
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
[WARNING] Node 10.172.18.26:34564 has slots in migrating state (23).
[WARNING] Node 10.172.18.24:37571 has slots in importing state (23).
[WARNING] The following slots are open: 23
>>> Check slots coverage...
[OK] All 16384 slots covered.
  • 使用redis-triib.rb fix修复集群的状态(把正在处于migrating和importing的那个槽位(23)接着处理完)
...
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
[WARNING] Node 10.172.18.26:34564 has slots in migrating state (23).
[WARNING] Node 10.172.18.24:37571 has slots in importing state (23).
[WARNING] The following slots are open: 23
>>> Fixing open slot 23
Set as migrating in: 10.172.18.26:34564
Set as importing in: 10.172.18.24:37571
Moving slot 23 from 10.172.18.26:34564 to 10.172.18.24:37571: ...........................................................
>>> Check slots coverage...
[OK] All 16384 slots covered.
  • 再使用redis-triib.rb check检查集群的状态(这时候集群状态就正常,没有异常槽位)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

注意:有时候执行一遍redis-trib fix之后,集群check之后发现有提示

Redis [ERR] Nodes don’t agree about configuration!

这应该是由于各个节点的槽位信息不一致导致的,需要调整各个节点槽位记录,让其保持一致。

最简单的方法是再执行一遍redis-trib fix,让其自动校验调整下集群的槽位信息。

  • 确认集群状态正常后,到海外的机器上再次执行redis-trib.rb rebalance命令,让其开始做槽位迁移

五、后续

之后在海外机器上做迁移果然快多了。。。

下次一定得注意r`edis-trib.rb命令的跨机房使用,不光慢不说,还可能中断后槽位信息不一致导致集群不可用,那就GGL了。

还好提前处理了,不然又得写故障报告了@_@