一简介
事先说明一下, 本篇文章不涉及对 redis-trib.rb 源代码的分析, 只是从使用的角度来阐述一下, 对第一次使用的人来说很重要 redis-trib.rb 是 redis 官方推出的管理 redis 集群的工具, 集成在 redis 的源码 src 目录下, 是基于 redis 提供的集群命令封装成简单便捷实用的操作工具这个文件可以在 src 这个目录下使用, 也可以像 redis-cli 等命令一样, 可以拷贝到单独目录, 方便使用 redis-trib.rb 是 redis 作者用 ruby 写成的, 为了看懂 redis-trib.rb 的源码, 我还要花一些时间来学学 rubyruby 这门语言我是在老赵的教程里面最早听说的, 认为这个语言和我关系不大, 当初也就没有在意, 自然也就没学了现在看来不行了, 所以我就特意花了一个月的时间学习了一下 ruby 这门语言, 同时也被 ruby 语言的简洁明了所吸引阅读本文需要对 redis 集群功能有一定的了解关于 redis 集群功能的介绍, 可以参考本人的另两篇文章, 第一篇是 Redis 进阶实践之十一 Redis 的 Cluster 集群搭建, 第二篇是 Redis 进阶实践之十二 Redis 的 Cluster 集群动态扩容
二 Redis-trib.rb 详细介绍
Redis-Trib.rb 这个脚本文件的功能很强大, 使用起来也很方便, 我们就由浅入深来探讨这个脚本文件的使用吧我们先来看看他的帮助信息吧, 这个最简单, 学习一门新技术的时候, 也应该先看看帮助的东西
- 1#ruby redis-trib.rb help (Redis-Trib.rb 的帮助信息)
- [root@linux redis]# ruby redis-trib.rb help
- Usage: redis-trib <command> <options> <arguments ...>
- create host1:port1 ... hostN:portN
- --replicas <arg>
- check host:port
- info host:port
- fix host:port
- --timeout <arg>
- reshard host:port
- --from <arg>
- --to <arg>
- --slots <arg>
- --yes
- --timeout <arg>
- --pipeline <arg>
- rebalance host:port
- --weight <arg>
- --auto-weights
- --use-empty-masters
- --timeout <arg>
- --simulate
- --pipeline <arg>
- --threshold <arg>
- add-node new_host:new_port existing_host:existing_port
- --slave
- --master-id <arg>
- del-node host:port node_id
- set-timeout host:port milliseconds
- call host:port command arg arg .. arg
- import host:port
- --from <arg>
- --copy
- --replace
- help (show this help)
- For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
(对于 check,fix,reshard,del-node,settimeout, 你可以指定集群中任何工作节点的主机和端口)
可以看到 redis-trib.rb 具有以下功能:
1create: 创建集群
2check: 检查集群
3info: 查看集群信息
4fix: 修复集群
5reshard: 在线迁移 slot
6rebalance: 平衡集群节点 slot 数量
7add-node: 将新节点加入集群
8del-node: 从集群中删除节点
9set-timeout: 设置集群节点间心跳连接的超时时间
10call: 在集群全部节点上执行命令
11import: 将外部 redis 数据导入集群
2Create 创建集群
命令格式: ruby redis-trib.rb create [--replicas <arg>] host1:port1 ... hostN:portN 地址列表必须大于等于 3
create 命令的可选 replicas 参数表示需要有几个 slave 从节点, 如果该参数存在, 必须在 < arguments ...>之前
Master 主节点没有 Slave 从节点, 最简单命令使用如下:
[root@linux redis]# ruby redis-trib.rb create 192.168.127.128:6379 192.168.127.129:6379 192.168.127.130:6379
每个 Master 主节点都有一个 slave 从节点的创建命令如下:
[root@linux redis]# ruby redis-trib.rb create --replicas 1 192.168.127.130:7000 192.168.127.130:7001 192.168.127.130:7002 192.168.127.130:7003 192.168.127.130:7004 192.168.127.130:7005
创建流程如下:
1 首先为每个节点创建 ClusterNode 对象, 包括连接每个节点检查每个节点是否为独立且 db 为空的节点执行 load_info 方法导入节点信息
2 检查传入的 master 节点数量是否大于等于 3 个只有大于 3 个节点才能组成集群
3 计算每个 master 需要分配的 slot 数量, 以及给 master 分配 slave
4 打印出分配信息, 并提示用户输入 yes 确认是否按照打印出来的分配方式创建集群
5 输入 yes 后, 会执行 flush_nodes_config 操作, 该操作执行前面的分配结果, 给 master 分配 slot, 让 slave 复制 master, 对于还没有握手 (cluster meet) 的节点, slave 复制操作无法完成, 不过没关系, flush_nodes_config 操作出现异常会很快返回, 后续握手后会再次执行 flush_nodes_config
6 给每个节点分配 epoch, 遍历节点, 每个节点分配的 epoch 比之前节点大 1
7 节点间开始相互握手, 握手的方式为节点列表的其他节点跟第一个节点握手
8 然后每隔 1 秒检查一次各个节点是否已经消息同步完成, 使用 ClusterNode 的 get_config_signature 方法, 检查的算法为获取每个节点 cluster nodes 信息, 排序每个节点, 组装成 node_id1:slots|node_id2:slot2|... 的字符串如果每个节点获得字符串都相同, 即认为握手成功
9 此后会再执行一次 flush_nodes_config, 这次主要是为了完成 slave 复制操作
10 最后再执行 check_cluster, 全面检查一次集群状态包括和前面握手时检查一样的方式再检查一遍确认没有迁移的节点确认所有的 slot 都被分配出去了
11 至此完成了整个创建流程, 返回[OK] All 16384 slots covered.
3Check 检查集群主从状态信息
命令格式: ruby redis-trib.rb check host:port 此地址可以是集群中任何一个节点的地址, 相当于获取集群信息的入口
检查集群状态的命令, 没有其他参数, 只需要选择一个集群中的一个节点即可执行命令以及结果如下:
- [root@linux redis]# ruby redis-trib.rb check 192.168.127.130:7000
- >>> Performing Cluster Check (using node 192.168.127.130:7000)
- M: a44081c39e7978c731a5c64476f4dc64e8d10c20 192.168.127.130:7000
- slots:66-5460 (5395 slots) master
- 1 additional replica(s)
- S: be14cfa7cc064e75977ec8517c1eccf96e92aebf 192.168.127.130:7005
- slots: (0 slots) slave
- replicates 3b025b3ecfa65f462de639c7a412be443cf1dd1c
- M: bafe517c084aadaacb0b0249dac1e706f24bc21f 192.168.127.130:7001
- slots:5528-10922 (5395 slots) master
- 1 additional replica(s)
- S: b04d39427329b256fcb9b851e02d4b814314b280 192.168.127.130:7004
- slots: (0 slots) slave
- replicates bafe517c084aadaacb0b0249dac1e706f24bc21f
- M: 3b025b3ecfa65f462de639c7a412be443cf1dd1c 192.168.127.130:7002
- slots:0-65,5461-5527,10923-16383 (5594 slots) master
- 1 additional replica(s)
- S: b96aac031170a2aa42c619fbc08450bb51af372c 192.168.127.130:7003
- slots: (0 slots) slave
- replicates a44081c39e7978c731a5c64476f4dc64e8d10c20
- [OK] All nodes agree about slots configuration.
- >>> Check for open slots...
- >>> Check slots coverage...
- [OK] All 16384 slots covered.
检查前会先执行 load_cluster_info_from_node 方法, 把所有节点数据 load 进来 load 的方式为通过自己的 cluster nodes 发现其他节点, 然后连接每个节点, 并加入 nodes 数组接着生成节点间的复制关系 load 完数据后, 开始检查数据, 检查的方式也是调用创建时候使用的 check_cluster
4Info 查看集群主节点信息
命令格式: ruby redis-trib.rb info host:port 此地址可以是集群中任何一个节点的地址, 相当于获取集群信息的入口
info 命令用来查看集群中 Master 主节点的信息 info 命令也是先执行 load_cluster_info_from_node 获取完整的集群信息
示例如下:
- [root@linux redis]# ruby redis-trib.rb info 192.168.127.130:7000
- 192.168.127.130:7000 (a44081c3...) -> 3 keys | 5395 slots | 1 slaves.
- 192.168.127.130:7001 (bafe517c...) -> 1 keys | 5395 slots | 1 slaves.
- 192.168.127.130:7002 (3b025b3e...) -> 1 keys | 5594 slots | 1 slaves.
- [OK] 5 keys in 3 masters.
- 0.00 keys per slot on average.
5Fix 修复集群
命令格式: ruby redis-trib.rb fix --timeout <arg> host:port 此地址可以是集群中任何一个节点的地址, 相当于获取集群信息的入口
执行效果如下:
- [root@linux redis]# ruby redis-trib.rb fix 192.168.127.130:7002
- >>> Performing Cluster Check (using node 192.168.127.130:7002)
- M: 3b025b3ecfa65f462de639c7a412be443cf1dd1c 192.168.127.130:7002
- slots:0-65,5461-5527,10923-16383 (5594 slots) master
- 1 additional replica(s)
- M: bafe517c084aadaacb0b0249dac1e706f24bc21f 192.168.127.130:7001
- slots:5528-10922 (5395 slots) master
- 1 additional replica(s)
- S: b96aac031170a2aa42c619fbc08450bb51af372c 192.168.127.130:7003
- slots: (0 slots) slave
- replicates a44081c39e7978c731a5c64476f4dc64e8d10c20
- S: b04d39427329b256fcb9b851e02d4b814314b280 192.168.127.130:7004
- slots: (0 slots) slave
- replicates bafe517c084aadaacb0b0249dac1e706f24bc21f
- M: a44081c39e7978c731a5c64476f4dc64e8d10c20 192.168.127.130:7000
- slots:66-5460 (5395 slots) master
- 1 additional replica(s)
- S: be14cfa7cc064e75977ec8517c1eccf96e92aebf 192.168.127.130:7005
- slots: (0 slots) slave
- replicates 3b025b3ecfa65f462de639c7a412be443cf1dd1c
- [OK] All nodes agree about slots configuration.
- >>> Check for open slots...
- >>> Check slots coverage...
- [OK] All 16384 slots covered.
- [root@linux redis]# ruby redis-trib.rb fix 192.168.127.130:7005
- >>> Performing Cluster Check (using node 192.168.127.130:7005)
- S: be14cfa7cc064e75977ec8517c1eccf96e92aebf 192.168.127.130:7005
- slots: (0 slots) slave
- replicates 3b025b3ecfa65f462de639c7a412be443cf1dd1c
- S: b96aac031170a2aa42c619fbc08450bb51af372c 192.168.127.130:7003
- slots: (0 slots) slave
- replicates a44081c39e7978c731a5c64476f4dc64e8d10c20
- M: 3b025b3ecfa65f462de639c7a412be443cf1dd1c 192.168.127.130:7002
- slots:0-65,5461-5527,10923-16383 (5594 slots) master
- 1 additional replica(s)
- M: a44081c39e7978c731a5c64476f4dc64e8d10c20 192.168.127.130:7000
- slots:66-5460 (5395 slots) master
- 1 additional replica(s)
- S: b04d39427329b256fcb9b851e02d4b814314b280 192.168.127.130:7004
- slots: (0 slots) slave
- replicates bafe517c084aadaacb0b0249dac1e706f24bc21f
- M: bafe517c084aadaacb0b0249dac1e706f24bc21f 192.168.127.130:7001
- slots:5528-10922 (5395 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.
1fix 命令的流程跟 check 的流程很像, 显示加载集群信息, 然后在 check_cluster 方法内传入 fix 为
true 的变量, 会在集群检查出现异常的时候执行修复流程目前 fix 命令能修复两种异常, 一种是集群有处于迁移中的 slot 的节点, 一种是 slot 未完全分配的异常
2fix_open_slot 方法是修复集群中在迁移 slots 数据槽的过程中节点的异常
2.1 先检查该 slot 是谁负责的, 迁移的源节点如果没完成迁移, owner 还是该节点没有 owner 的 slot 无法完成修复功能
2.2 遍历每个节点, 获取哪些节点的 slot 被标记为 migrating 迁移状态, 哪些节点的 slot 被标记为 importing 输入状态对于 owner 所有者不是该节点, 但是通过 cluster countkeysinslot 获取到该节点有数据的情况, 也认为该节点为 importing 输入状态
2.3 如果 migrating 迁移和 importing 输入状态的节点均只有 1 个, 这可能是迁移过程中 redis-trib.rb 被中断所致, 直接执行 move_slot 继续完成迁移任务即可传递 dots 和 fix 为 true
2.4 如果 migrating 迁移为空, importing 输入状态的节点大于 0, 那么这种情况执行回滚流程, 将 importing 输入状态的节点数据通过 move_slot 方法导给 slot 的 owner 所有者节点, 传递 dotsfix 和 cold 为 true 接着对 importing 的节点执行 cluster stable 命令恢复稳定
2.5 如果 importing 输入状态的节点为空, 有一个 migrating 迁移状态的节点, 而且该节点在当前 slot 没有数据, 那么可以直接把这个 slot 设为 stable
2.6 如果 migrating 迁移和 importing 输入状态不是上述情况, 目前 redis-trib.rb 工具无法修复, 上述的三种情况也已经覆盖了通过 redis-trib.rb 工具迁移出现异常的各个方面, 人为的异常情形太多, 很难考虑完全
3fix_slots_coverage 方法能修复 slot 未完全分配的异常未分配的 slot 有三种状态
3.1 所有节点的该 slot 都没有数据该状态 redis-trib.rb 工具直接采用随机分配的方式, 并没有考虑节点的均衡本人尝试对没有分配 slot 的集群通过 fix 修复集群, 结果 slot 还是能比较平均的分配, 但是没有了连续性, 打印的 slot 信息非常离散
3.2 有一个节点的该 slot 有数据该状态下, 直接把 slot 分配给该 slot 有数据的节点
3.3 有多个节点的该 slot 有数据此种情况目前还处于 TODO 状态, 不过 redis 作者列出了修复的步骤, 对这些节点, 除第一个节点, 执行 cluster migrating 命令, 然后把这些节点的数据迁移到第一个节点上清除 migrating 状态, 然后把 slot 分配给第一个节点
6Reshard 在线迁移 slot
命令格式: ruby redis-trib.rb reshard --from <arg> host:port 此地址可以是集群中任何一个主节点的地址, 相当于获取集群信息的入口
- --to <arg>
- --slots <arg>
- --yes
- --timeout <arg>
- --pipeline <arg>
reshard 命令可以在线把集群的一些 slot 从集群原来 slot 负责节点迁移到新的节点, 利用 reshard 可以完成集群的在线横向扩容和缩容
reshard 的参数很多, 下面来一一解释一番:
- reshard host:port
- --from <arg>
host:port: 这个是必传参数, 用来从一个节点获取整个集群信息, 相当于获取集群信息的入口
--from <arg>: 需要从哪些源节点上迁移 slot, 可从多个源节点完成迁移, 以逗号隔开, 传递的是节点的 node id, 还可以直接传递 --from all, 这样源节点就是集群的所有节点, 不传递该参数的话, 则会在迁移过程中提示用户输入
--to <arg>:slot 需要迁移的目的节点的 node id, 目的节点只能填写一个, 不传递该参数的话, 则会在迁移过程中提示用户输入
--slots <arg>: 需要迁移的 slot 数量, 不传递该参数的话, 则会在迁移过程中提示用户输入
--yes: 设置该参数, 可以在打印执行 reshard 计划的时候, 提示用户输入 yes 确认后再执行 reshard
--timeout <arg>: 设置 migrate 命令的超时时间
--pipeline <arg>: 定义 cluster getkeysinslot 命令一次取出的 key 数量, 不传的话使用默认值为 10
迁移的流程如下:
1 通过 load_cluster_info_from_node 方法装载集群信息
2 执行 check_cluster 方法检查集群是否健康只有健康的集群才能进行迁移
3 获取需要迁移的 slot 数量, 用户没传递 --slots 参数, 则提示用户手动输入
4 获取迁移的目的节点, 用户没传递 --to 参数, 则提示用户手动输入此处会检查目的节点必须为 master 节点
5 获取迁移的源节点, 用户没传递 --from 参数, 则提示用户手动输入此处会检查源节点必须为 master 节点 --from all 的话, 源节点就是除了目的节点外的全部 master 节点这里为了保证集群 slot 分配的平均, 建议传递 --from all
6 执行 compute_reshard_table 方法, 计算需要迁移的 slot 数量如何分配到源节点列表, 采用的算法是按照节点负责 slot 数量由多到少排序, 计算每个节点需要迁移的 slot 的方法为: 迁移 slot 数量 * (该源节点负责的 slot 数量 / 源节点列表负责的 slot 总数)这样算出的数量可能不为整数, 这里代码用了下面的方式处理:
- n = (numslots/source_tot_slots*s.slots.length)
- if i == 0
- n = n.ceil
- else
- n = n.floor
这样的处理方式会带来最终分配的 slot 与请求迁移的 slot 数量不一致, 这个 BUG 已经在 github 上提给作者, https://github.com/antirez/redis/issues/2990
7 打印出 reshard 计划, 如果用户没传 --yes, 就提示用户确认计划
8 根据 reshard 计划, 一个个 slot 的迁移到新节点上, 迁移使用 move_slot 方法, 该方法被很多命令使用, 具体可以参见下面的迁移流程 move_slot 方法传递 dots 为 true 和 pipeline 数量
9 至此, 就完成了全部的迁移任务
move_slot 方法可以在线将一个 slot 的全部数据从源节点迁移到目的节点, fixreshardrebalance 都需要调用该方法迁移 slot
move_slot 接受下面几个参数,
1pipeline: 设置一次从 slot 上获取多少个 key
2quiet: 迁移会打印相关信息, 设置 quiet 参数, 可以不用打印这些信息
3cold: 设置 cold, 会忽略执行 importing 和 migrating
4dots: 设置 dots, 则会在迁移过程打印迁移 key 数量的进度
5update: 设置 update, 则会更新内存信息, 方便以后的操作
move_slot 流程如下:
1 如果没有设置 cold, 则对源节点执行 cluster importing 命令, 对目的节点执行 migrating 命令 fix 的时候有可能 importing 和 migrating 已经执行过来, 所以此种场景会设置 cold
2 通过 cluster getkeysinslot 命令, 一次性获取远节点迁移 slot 的 pipeline 个 key 的数量.
3 对这些 key 执行 migrate 命令, 将数据从源节点迁移到目的节点
4 如果 migrate 出现异常, 在 fix 模式下, BUSYKEY 的异常, 会使用 migrate 的 replace 模式再执行一次, BUSYKEY 表示目的节点已经有该 key 了, replace 模式可以强制替换目的节点的 key 不是 fix 模式就直接返回错误了
5 循环执行 cluster getkeysinslot 命令, 直到返回的 key 数量为 0, 就退出循环
6 如果没有设置 cold, 对每个节点执行 cluster setslot 命令, 把 slot 赋给目的节点
7 如果设置 update, 则修改源节点和目的节点的 slot 信息
8 至此完成了迁移 slot 的流程
7Rebalance 平衡集群节点 slot 数量
命令格式: ruby redis-trib.rb rebalance --weight <arg> host:port 此地址可以是集群中任何一个节点的地址, 相当于获取集群信息的入口
- --auto-weights
- --threshold <arg>
- --use-empty-masters
- --timeout <arg>
- --simulate
- --pipeline <arg>
rebalance 命令可以根据用户传入的参数平衡集群节点的 slot 数量, rebalance 功能非常强大, 可以传入的参数很多
以下是 rebalance 的参数列表和命令示例
# ruby redis-trib.rb rebalance --threshold 1 --weight b31e3a2e=5 --weight 60b8e3a1=5 --use-empty-masters --simulate 10.180.157.199:6379
下面也先一一解释下每个参数的用法:
host:port: 这个是必传参数, 用来从一个节点获取整个集群信息, 相当于获取集群信息的入口
--weight <arg>: 节点的权重, 格式为 node_id=weight, 如果需要为多个节点分配权重的话, 需要添加多个 --weight <arg > 参数, 即 --weight b31e3a2e=5 --weight 60b8e3a1=5,node_id 可为节点名称的前缀, 只要保证前缀位数能唯一区分该节点即可没有传递 weight 的节点的权重默认为 1
--auto-weights: 这个参数在 rebalance 流程中并未用到
--threshold <arg>: 只有节点需要迁移的 slot 阈值超过 threshold, 才会执行 rebalance 操作具体计算方法可以参考下面的 rebalance 命令流程的第四步
--use-empty-masters:rebalance 是否考虑没有节点的 master, 默认没有分配 slot 节点的 master 是不参与 rebalance 的, 设置 --use-empty-masters 可以让没有分配 slot 的节点参与 rebalance
--timeout <arg>: 设置 migrate 命令的超时时间
--simulate: 设置该参数, 可以模拟 rebalance 操作, 提示用户会迁移哪些 slots, 而不会真正执行迁移操作
--pipeline <arg>: 与 reshar 的 pipeline 参数一样, 定义 cluster getkeysinslot 命令一次取出的 key 数量, 不传的话使用默认值为 10
rebalance 命令流程如下:
1load_cluster_info_from_node 方法先加载集群信息
2 计算每个 master 的权重, 根据参数 --weight <arg>, 为每个设置的节点分配权重, 没有设置的节点, 则权重默认为 1
3 根据每个 master 的权重, 以及总的权重, 计算自己期望被分配多少个 slot 计算的方式为: 总 slot 数量 * (自己的权重 / 总权重)
4 计算每个 master 期望分配的 slot 是否超过设置的阈值, 即 --threshold <arg > 设置的阈值或者默认的阈值计算的方式为: 先计算期望移动节点的阈值, 算法为:(100-(100.0*expected/n.slots.length)).abs, 如果计算出的阈值没有超出设置阈值, 则不需要为该节点移动 slot 只要有一个 master 的移动节点超过阈值, 就会触发 rebalance 操作
5 如果触发了 rebalance 操作那么就开始执行 rebalance 操作, 先将每个节点当前分配的 slots 数量减去期望分配的 slot 数量获得 balance 值将每个节点的 balance 从小到大进行排序获得 sn 数组
6 用 dst_idx 和 src_idx 游标分别从 sn 数组的头部和尾部开始遍历目的是为了把尾部节点的 slot 分配给头部节点
sn 数组保存的 balance 列表排序后, 负数在前面, 正数在后面负数表示需要有 slot 迁入, 所以使用 dst_idx 游标, 正数表示需要有 slot 迁出, 所以使用 src_idx 游标理论上 sn 数组各节点的 balance 值加起来应该为 0, 不过由于在计算期望分配的 slot 的时候只是使用直接取整的方式, 所以可能出现 balance 值之和不为 0 的情况, balance 值之和不为 0 即为节点不平衡的 slot 数量, 由于 slot 总数有 16384 个, 不平衡数量相对于总数, 基数很小, 所以对 rebalance 流程影响不大
7 获取 sn[dst_idx]和 sn[src_idx]的 balance 值较小的那个值, 该值即为需要从 sn[src_idx]节点迁移到 sn[dst_idx]节点的 slot 数量
8 接着通过 compute_reshard_table 方法计算源节点的 slot 如何分配到源节点列表这个方法在 reshard 流程中也有调用, 具体步骤可以参考 reshard 流程的第六步
9 如果是 simulate 模式, 则只是打印出迁移列表
10 如果没有设置 simulate, 则执行 move_slot 操作, 迁移 slot, 传入的参数为: quiet=>true,:dots=>false,:update=>true
11 迁移完成后更新 sn[dst_idx]和 sn[src_idx]的 balance 值如果 balance 值为 0 后, 游标向前进 1
12 直到 dst_idx 到达 src_idx 游标, 完成整个 rebalance 操作
8add-node 将新节点加入集群
命令格式: ruby redis-trib.rb add-node --slave new_host:new_port existing_host:existing_port 此地址可以是集群中任何一个节点的地址, 相当于获取集群信息的入口
--master-id <arg>
add-node 命令可以将新节点加入集群, 节点可以为 master, 也可以为某个 master 节点的 slave
add-node 有两个可选参数:
--slave: 设置该参数, 则新节点以 slave 的角色加入集群
--master-id: 这个参数需要设置了 --slave 才能生效,--master-id 用来指定新节点的 master 节点如果不设置该参数, 则会随机为节点选择 master 节点
可以看下 add-node 命令的执行示例:
[root@linux redis]# ruby redis-trib.rb add-node --slave --master-id dcb792b3e85726f012e83061bf237072dfc45f99 192.168.127.130:7007 192.168.127.130:7006
add-node 流程如下:
1 通过 load_cluster_info_from_node 方法转载集群信息, check_cluster 方法检查集群是否健康
2 如果设置了 --slave, 则需要为该节点寻找 master 节点设置了 --master-id, 则以该节点作为新节点的 master, 如果没有设置 --master-id, 则调用 get_master_with_least_replicas 方法, 寻找 slave 数量最少的 master 节点如果 slave 数量一致, 则选取 load_cluster_info_from_node 顺序发现的第一个节点 load_cluster_info_from_node 顺序的第一个节点是 add-node 设置的 existing_host:existing_port 节点, 后面的顺序根据在该节点执行 cluster nodes 返回的结果返回的节点顺序
3 连接新的节点并与集群第一个节点握手
4 如果没设置 slave 就直接返回 ok, 设置了 slave, 则需要等待确认新节点加入集群, 然后执行 cluster replicate 命令复制 master 节点
5 至此, 完成了全部的增加节点的流程
9del-node 从集群中删除节点
命令格式: ruby redis-trib.rb del-node host:port node-idnode id 是要删除的节点 ID 标识
del-node 可以把某个节点从集群中删除 del-node 只能删除没有分配 slot 的节点删除命令传递两个参数:
host:port: 从该节点获取集群信息
node_id: 需要删除的节点 id
del-node 执行结果示例如下:
- [root@linux redis]# ruby redis-trib.rb del-node 192.168.127.130:7006 71ecd970838e9b400a2a6a15cd30a94ab96203bf
- >>> Removing node 71ecd970838e9b400a2a6a15cd30a94ab96203bf from cluster 192.168.127.130:7000
- >>> Sending CLUSTER FORGET messages to the cluster...
- >>> SHUTDOWN the node.
del-node 流程如下:
1 通过 load_cluster_info_from_node 方法转载集群信息
2 根据传入的 node id 获取节点, 如果节点没找到, 则直接提示错误并退出
3 如果节点分配的 slot 不为空, 则直接提示错误并退出
4 遍历集群内的其他节点, 执行 cluster forget 命令, 从每个节点中去除该节点如果删除的节点是 master, 而且它有 slave 的话, 这些 slave 会去复制其他 master, 调用的方法是 get_master_with_least_replicas, 与 add-node 没设置 --master-id 寻找 master 的方法一样
5 然后关闭该节点
10set-timeout 设置集群节点间心跳连接的超时时间
命令格式: ruby redis-trib.rb set-timeout host:port node-idnode id 是要删除的节点 ID 标识
set-timeout 用来设置集群节点间心跳连接的超时时间, 单位是毫秒, 不得小于 100 毫秒, 因为 100 毫秒对于心跳时间来说太短了该命令修改是节点配置参数 cluster-node-timeout, 默认是 15000 毫秒通过该命令, 可以给每个节点设置超时时间, 设置的方式使用 config set 命令动态设置, 然后执行 config rewrite 命令将配置持久化保存到硬盘以下是示例:
- [root#linux redis]# ruby redis-trib.rb set-timeout 192.168.127.130:7000 30000
- >>> Reconfiguring node timeout in every cluster node...
- *** New timeout set for 192.168.127.130:7000
- *** New timeout set for 192.168.127.130:7000
- *** New timeout set for 192.168.127.130:7000
- *** New timeout set for 192.168.127.130:7000
- *** New timeout set for 192.168.127.130:7000
- >>> New node timeout set. 5 OK, 0 ERR.
11call 在集群全部节点上执行命令
命令格式: ruby redis-trib.rb call host:port [command redis 的命令]
call 命令可以用来在集群的全部节点执行相同的命令 call 命令也是需要通过集群的一个节点地址, 连上整个集群, 然后在集群的每个节点执行该命令
- [root@linux redis]# ruby redis-trib.rb call 192.168.127.130:7000 get key
- >>> Calling GET key
- 192.168.127.130:6379: MOVED 12539 192.168.127.130:7000
- 192.168.127.130:6379: MOVED 12539 192.168.127.130:7000
- 192.168.127.130:6379:
- 192.168.127.130:6379: MOVED 12539 192.168.127.130:7000
- 192.168.127.130:6379: MOVED 12539 192.168.127.130:7000
12import 将外部 redis 数据导入集群
命令格式: ruby redis-trib.rb import --from host:port host:port
执行示例如下:
[root@linux redis]# ruby redis-trib.rb import --from 192.168.127.130:7006 192.168.127.129:7000
上面的命令是把 192.168.127.130:7006(redis 4.8)上的数据导入到 192.168.127.129:7000 这个节点所在的集群
import 命令可以把外部的 redis 节点数据导入集群导入的流程如下:
1 通过 load_cluster_info_from_node 方法转载集群信息, check_cluster 方法检查集群是否健康
2 连接外部 redis 节点, 如果外部节点开启了 cluster_enabled, 则提示错误
3 通过 scan 命令遍历外部节点, 一次获取 1000 条数据
4 遍历这些 key, 计算出 key 对应的 slot
5 执行 migrate 命令, 源节点是外部节点, 目的节点是集群 slot 对应的节点, 如果设置了 --copy 参数, 则传递 copy 参数, 如果设置了 --replace, 则传递 replace 参数
6 不停执行 scan 命令, 直到遍历完全部的 key
7 至此完成整个迁移流程
这中间如果出现异常, 程序就会停止没使用 --copy 模式, 则可以重新执行 import 命令, 使用 --copy 的话, 最好清空新的集群再导入一次
import 命令更适合离线的把外部 redis 数据导入, 在线导入的话最好使用更专业的导入工具, 以 slave 的方式连接 redis 节点去同步节点数据应该是更好的方式
三总结
好了, 今天就写到这里, 有关 redis-trib.rb 脚步文件的内容还很多, 以后再补充进来吧这个脚本文件对我们很重要, 集群的操作很多功能都可以通过这个脚本文件来完成
来源: https://www.cnblogs.com/PatrickLiu/p/8484784.html