redis-trib.rb工具介绍
redis-trib.rb是redis集群管理工具,可以检查集群、创建删除节点、挪key、批量下发实例命令等等。
不是没有redis-trib.rb就没有集群管理了,没有redis-trib.rb照样可以管理集群。redis本身就有集群相关管理命令,redis-trib.rb只是封装了这些命令,它极大的简化了集群管理工作。
redis-trib.rb以前是开源工具,现在已经合并到redis软件中了,跟redis-cli在一个bin目录下,所以这个命令一般都能直接用。如果没有的话检查下环境变量,或者去官网下一个
redis-trib.rb本身支持交互窗口,但是生产都得提前准备好方案,设置提前写好运行脚本,交互模式不太实用,所以本篇的介绍都是针对非交互式的。
常用命令
redis-trib.rb查看help
redis-trib.rb可做如下操作
command | 行为 |
---|---|
create | 创建集群,需要提前建好实例 |
check | 检查集群,其实也是输出集群信息,check比info更实用一点 |
info | 输出集群信息 |
fix | 修复集群,自检并自动修复集群异常,某些场景无法自动修复 |
reshard | 挪slot命令,加减节点的核心命令 |
rebalance | 因为slot不均匀导致数据倾斜,rebalance可以自动转移slot平衡集群 |
add-node | 添加节点 |
del-node | 删除节点 |
set-timeout | 设置集群心跳连接超时参数 |
call | 在所有节点上执行命令 |
import | 从外部redis导入集群 |
help | 打印此帮助 |
查看集群状态
redis-trib.rb check --password mypass 127.30.30.10:6486
>>> Performing Cluster Check (using node 127.30.30.10:6486)
M: 62e4f253ce48af6699713c11dcc8baae062a736d 127.30.30.10:6486
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: e2f650538610505be567cf4bf87c599e1afd354d 127.30.30.47:6486
slots: (0 slots) slave
replicates 62e4f253ce48af6699713c11dcc8baae062a736d
S: 081dad4fadf8cf29a018ef12b703eb9a3363a86a 127.30.30.51:6485
slots: (0 slots) slave
replicates 387a5764c93f4d52c9f46996df4af0d74abacf0f
M: 2e0335e3fc413568c3f2900a66c837d34db6565a 127.30.30.51:6484
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 78c01003a13979221d9ef42660f4715c5ccd48aa 127.30.30.45:6484
slots: (0 slots) slave
replicates 2e0335e3fc413568c3f2900a66c837d34db6565a
M: 387a5764c93f4d52c9f46996df4af0d74abacf0f 127.30.30.47:6485
slots:5461-10922 (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
至少确认两个信息
- check输出[ok],无异常输出,集群状态正常
- 节点ID,在reshard和加减节点时会用到
这个经典的3主3从redis集群架构如下
reshard参数说明
host:port:这个是必传参数,用来从一个节点获取整个集群信息,相当于获取集群信息的入口。
–from :需要从哪些源节点上迁移slot,可从多个源节点完成迁移,以逗号隔开,传递的是节点的node id,还可以直接传递–from all,这样源节点就是集群的所有节点,不传递该参数的话,则会在迁移过程中提示用户输入。
–to :slot需要迁移的目的节点的node id,目的节点只能填写一个,不传递该参数的话,则会在迁移过程中提示用户输入。
–slots :需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。
–yes:设置该参数,可以在打印执行reshard计划的时候,提示用户输入yes确认后再执行reshard。
–timeout :设置migrate命令的超时时间。
–pipeline :定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10。
非交互的执行命令,如下
redis-trib.rb reshard --password mypass --from f2ce18189001d64fd55d3500f48338aa6d92bf7e --to da0b390d8fd35b303f857dd15a3a4ac0ca317c7b --slots 100 --pipeline 1000 --timeout 100000000 --yes 127.10.0.79:6416
表示非交互模式从节点da0b390d8fd35b303f857dd15a3a4ac0ca317c7b转移100个slot到f2ce18189001d64fd55d3500f48338aa6d92bf7e节点
连接节点为127.10.0.79:6416(redis-trib.rb连接到集群的登陆节点),注意这个节点最好是缩容节点后仍保留的节点
总是报命令错误?
redis-trib.rb的help(直接敲redis-trib.rb就出来help了)有点问题。help看上去把–password放在了命令最后,如果按照help来敲命令,那么你可能总是会得到命令错误的提示:
[ERR] Wrong number of arguments for specified sub command
应该把 --password 放到“中间”,command动作后面,像这样
redis-trib.rb call --password mypass 127.30.30.130:7367 config get maxmemory
操作注意事项
使用redis自带工具redis-trib.rb reshard做slot和key的迁移,步骤很简单。但是仍有一些注意点,有些可能导致reshard中断,需手工修复。
为了减少不必要的麻烦并提高变更的成功率,我们需要注意这些点
- 只要把缩容后的slot计算均匀,手动分配slot到保留的节点,slot是均匀的,最后不太需要做rebalance操作
- 确保缩容后,每个机器的节点数不超过总节点数的一半
- 对于节点较多的集群,可以把命令做成脚本。但是需要注意,在每个reshard命令中间插入sleep 5。reshard命令太“紧凑”也可能导致reshard失败
- timeout参数尽量设置的够大,设置过小会导致reshard命令中断
- 对于内存较大、或者有大key的节点,转移这些keys的时间会更长,更应该调大timeout参数
- 内存得是足够的。比如减少节点后,每个实例的内存是否足够,如果不够需要增加maxmemory或者不要减少那么多节点
变更风险点
reshard是否在线操作?
reshard操作会把slot设置为迁移状态,迁移key时业务还是会有短暂的感知。
加减节点是否需要重启redis实例?
不需要!整个加减节点的所有操作是不需要重启redis实例的
加减节点是否需要重启应用?
不确定!取决于中间件是否缓存了路由
实际案例中增删节点时遇到过有些应用一点感觉没有,有些必须要重启才正常的情况
slot计算
迁移前把迁移后的slot的分配算好,就可以不重复迁移slot,并减少rebalance这一步。再者,如果节点过多或者物理内存(或cg)有限,本身迁移过程中需要把slot分散地reshard到其他各个节点上。所以需要提前计算好slot的分配以及reshard过程中迁移多少slot。
以一个56节点的redis cluster为例,减少16个节点到40个节点
缩容前,每个节点的slots为:16384/56=292.5(292或293)
缩容后,每个节点的slots为:16384/40=409.6(409或410)
那么,reshard时转移的slot为:410-293=117
因为要把删除的节点上的slot全部转移完
所以每个节点上还剩一点slots需要转移完 292.5-117-117=58.5(58或59)
具体数值看节点到底有多少slot,目的是slot均匀且删除节点的slot全部转移,差1、2个slot问题不大
实施方案案例
从多个集群节点中减少一部分节点,并完成回退方案(回退就是增加节点)
删除集群的一部分节点
- 选择要踢出的节点,并计算分配到其他节点的slot个数
(一般来说,会选择整个机器上部署的所有节点)
RLZLCLUSTER RLZLCLUSTER_40 主库 hostlzl111 76a301a4f1bd18d19df29aff6dc9c42e141f7225 127.10.11.50:6475
RLZLCLUSTER RLZLCLUSTER_41 从库 hostlzl111 1df5c7a055f3e776d856a43f83f0b8414ddb33a5 127.10.11.50:6476
- reshard迁移slot(会转移key)
把需要剔除的节点上的slot迁移走,迁到不会剔除的节点上
#redis-trib.rb check 127.10.11.35:6612 |grep -A 2 -B 2 3aca6bf3cc102d65d5dbed9e461773c32d3864c2
#76a301a4f1bd18d19df29aff6dc9c42e141f7225 节点上所有slot迁移,迁移到其他2个节点上
redis-trib.rb reshard --password mypass --from 76a301a4f1bd18d19df29aff6dc9c42e141f7225 --to 726823529b76f2048711f07aea11615fa4ea5720 --slots 30 --pipeline 1000 --timeout 100000000 --yes 127.10.11.79:6416
redis-trib.rb reshard --password mypass --from 76a301a4f1bd18d19df29aff6dc9c42e141f7225 --to da6ced81cbaa2ca65514a5819469ae6f72e99737 --slots 117 --pipeline 1000 --timeout 100000000 --yes 127.10.11.79:6416
- 检查删除的节点没有slot
redis-trib.rb check --password mypass 127.10.11.79:6416|grep -E -A 1 "127.10.11.50"
- 剔除节点 (ip:port为登陆节点,不是删除节点)
#删除从节点:
redis-trib.rb del-node --password mypass 127.10.11.79:6416 1df5c7a055f3e776d856a43f83f0b8414ddb33a5
#删除主节点:
redis-trib.rb del-node --password mypass 127.10.11.79:6416 76a301a4f1bd18d19df29aff6dc9c42e141f7225
回退方案(将节点加回集群)
- 将新的单实例加入为主节点
/paic/redis/3.2.12/bin/redis-trib.rb add-node --password mypass 172.30.32.9:6476 $ip:port
- 将新的单实例加入为从节点
#指定给某个集群的主节点添加从节点
redis-trib.rb add-node --slave --master-id <one_master_id>
/paic/redis/3.2.12/bin/redis-trib.rb check --password mypass 127.10.11.50:6495
3.进行rebalance(整个集群只需要执行一次),或者手动reshard
/paic/redis/3.2.12/bin/redis-trib.rb rebalance --password mypass --threshold <arg> 127.10.11.50:6495
(附)迁移中断问题处理
迁移命令中断,集群check报错
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
[WARNING] Node 127.10.11.2:6410 has slots in importing state (1312).
[WARNING] Node 127.10.11.50:6475 has slots in migrating state (1312).
[WARNING] The following slots are open: 1312
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** Please fix your cluster problems before resharding
解决方案一:用fix自动修复
redis-trib.rb fix --password mypass 127.10.11.50:6495
解决方案二: 如果fix失败,手动stable,检查key的位置
r -c
CLUSTER SETSLOT 1312 stable
cluster GETKEYSINSLOT 1312 1000