• 节点迁移使用翻倍迁移

    slot

    Redis Cluster - 图2

  • 节点直接互相通信的。【gossip协议】

Redis Cluster - 图3
redis cluster有16384个slot
为什么redis集群的最大槽数是16384个? - 简书
Redis Cluster - 图4

客户端本地有 slot->node的缓存
slot更变就进行重定向。

Redis Cluster会丢数据么?

Redis Cluster 不保证强一致性
Redis Cluster 会丢数据吗? - 知乎

创建集群

配置cluster

放行访问IP限制

bind 0.0.0.0

端口

port 6371

后台启动

daemonize yes

日志存储目录及日志文件名

logfile “/usr/local/redis/cluster/log/redis-6371.log”

rdb数据文件名

dbfilename dump-6371.rdb

aof模式开启和aof数据文件名

appendonly yes appendfilename “appendonly-6371.aof”

rdb数据文件和aof数据文件的存储目录

dir /usr/local/redis/cluster/data

设置密码

requirepass 123456

从节点访问主节点密码(必须与 requirepass 一致)

masterauth 123456 # 是否开启集群模式,默认 no cluster-enabled yes # 集群节点信息文件,会保存在 dir 配置对应目录下【系统自动创建,维护】默认nodes.conf cluster-config-file nodes-6371.conf

集群节点连接超时时间

cluster-node-timeout 15000

集群节点 IP

cluster-announce-ip 192.168.10.101

集群节点映射端口

cluster-announce-port 6371

集群节点总线端口

cluster-announce-bus-port 16371

批量修改
image.png

  • cluster-require-full-coverage:集群完整性(有一个down机集群就不可用),建议设置为no
  • cluster-config-file nodes-6379.conf:虽然此配置的名字叫”集群配置文件”,但是此配置文件不能人工编辑,它是集群节点自动维护的文件,主要用于记录集群中有哪些节点、他们的状态以及一些持久化参数等,方便在重启时恢复这些状态。通常是在收到请求之后这个文件就会被更新。【可cat conf文件查看节点信息,和cluster node命令信息一样】

快速生成其他节点配置文件:
image.png
运行:redis-server redis-xxxx.conf
显示集群模式
image.png

创建集群【5.0之后】—cluster create

Redis Cluster 在5.0之后取消了ruby脚本 redis-trib.rb的支持(手动命令行添加集群的方式不变),集合到redis-cli里,避免了再安装ruby的相关环境。直接使用redis-cli的参数—cluster 来取代。

redis-cli —cluster create \ 192.168.137.111:6379 192.168.137.111:6380 \ 192.168.137.112:6379 192.168.137.112:6380 \ 192.168.137.113:6379 192.168.137.113:6380 \ —cluster-replicas 1

  • 最后的1:比例,表示一主对应一从

分配结果:
image.png

操作命令

  1. redis-cli --cluster help
  2. Cluster Manager Commands:
  3. create host1:port1 ... hostN:portN #创建集群
  4. --cluster-replicas <arg> #从节点个数
  5. check host:port #检查集群
  6. --cluster-search-multiple-owners #检查是否有槽同时被分配给了多个节点
  7. info host:port #查看集群状态
  8. fix host:port #修复集群
  9. --cluster-search-multiple-owners #修复槽的重复分配问题
  10. reshard host:port #指定集群的任意一节点进行迁移slot,重新分slots
  11. --cluster-from <arg> #需要从哪些源节点上迁移slot,可从多个源节点完成迁移,以逗号隔开,传递的是节点的node id,还可以直接传递--from all,这样源节点就是集群的所有节点,不传递该参数的话,则会在迁移过程中提示用户输入
  12. --cluster-to <arg> #slot需要迁移的目的节点的node id,目的节点只能填写一个,不传递该参数的话,则会在迁移过程中提示用户输入
  13. --cluster-slots <arg> #需要迁移的slot数量,不传递该参数的话,则会在迁移过程中提示用户输入。
  14. --cluster-yes #指定迁移时的确认输入
  15. --cluster-timeout <arg> #设置migrate命令的超时时间
  16. --cluster-pipeline <arg> #定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10
  17. --cluster-replace #是否直接replace到目标节点
  18. rebalance host:port #指定集群的任意一节点进行平衡集群节点slot数量
  19. --cluster-weight <node1=w1...nodeN=wN> #指定集群节点的权重
  20. --cluster-use-empty-masters #设置可以让没有分配slot的主节点参与,默认不允许
  21. --cluster-timeout <arg> #设置migrate命令的超时时间
  22. --cluster-simulate #模拟rebalance操作,不会真正执行迁移操作
  23. --cluster-pipeline <arg> #定义cluster getkeysinslot命令一次取出的key数量,默认值为10
  24. --cluster-threshold <arg> #迁移的slot阈值超过threshold,执行rebalance操作
  25. --cluster-replace #是否直接replace到目标节点
  26. add-node new_host:new_port existing_host:existing_port #添加节点,把新节点加入到指定的集群,默认添加主节点
  27. --cluster-slave #新节点作为从节点,默认随机一个主节点
  28. --cluster-master-id <arg> #给新节点指定主节点
  29. del-node host:port node_id #删除给定的一个节点,成功后关闭该节点服务
  30. call host:port command arg arg .. arg #在集群的所有节点执行相关命令
  31. set-timeout host:port milliseconds #设置cluster-node-timeout
  32. import host:port #将外部redis数据导入集群
  33. --cluster-from <arg> #将指定实例的数据导入到集群
  34. --cluster-copy #migrate时指定copy
  35. --cluster-replace #migrate时指定replace
  36. help
  37. For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.

查看信息

  • check 查看
    • redis-cli —cluster check 192.168.137.111:6379
  • cluster info:cluster信息
  • cluster nodes:节点信息

image.png

添加节点 add-node

添加主节点 —cluster-master-id

redis-cli —cluster add-node new_host:new_port existing_host:existing_port

例子

redis-cli -a 123456 —cluster add-node 192.168.10.103:6377 192.168.10.103:6375

existing_host是任意一个节点

添加从节点 —cluster-slave

redis-cli —cluster add-node newhost:new_port existing_host:existing_port —cluster-slave —cluster-master-id node_id
# 例子_ redis-cli -56 —cluster add-node 192.168.10.103:6378 192.168.10.103:6377 —cluster-slave —cluster-master-id 66f3cbc063a84ff3c209fa2db7104e4666d82e9c

这里existing_host是要给哪个master做slave。

重新分片 reshard

一次性分配

redis-cli —cluster reshard host:port —cluster-from node_id —cluster-to node_id —cluster-slots —cluster-yes

例子

redis-cli -a 123456 —cluster reshard 192.168.10.103:6377 —cluster-from a1cd39d24bd2c9456026d592f0fac8728cea0e29 —cluster-to 66f3cbc063a84ff3c209fa2db7104e4666d82e9c —cluster-slots 2000

  • —cluster-yes:免除手动确认

    手动分配

    /usr/local/redis/bin/redis-cli -a 123456 —cluster reshard 192.168.10.103:6377

image.png

  • done:结束

    删除

    删除从节点

    redis-cli —cluster del-node host:port node_id

    # 例子 redis-cli -a 123456 —cluster del-node 192.168.10.103:6378 5800786da604cedb56eb1b50d83e9f82bb09b421

删除主节点

  • 移动slot到其他master
  • 移除节点

Jedis Cluster客户端(smart客户端)

image.png

image.png

image.png

  • 异常会刷新本地slot缓存。

获取redis cluster的所有node:
image.png

客户端重定向:moved异常 和 ask异常

moved异常

image.png
image.png

  • redis-cli -c 集群模式会自动redirect
  • redis-cli 普通模式 会抛异常

重分片对 Redis 集群的性能影响分析 — blog.huangz.me

ask异常

image.png
image.png

moved ask区别

Redis Cluster - 图19
moved永久转移,更新客户端 slot-node缓存
ask该slot正在转移。一部分数据在A一部分在B
Redis Cluster - 图20

故障转移【redis cluster自身高可用】

  • ping、pong,不需要sentinel
  • 主观下线 客观下线

    故障发现

    主客观下线【ping pong】

    image.png
    客观下线:

  • 半数以上持有槽的主节点都标记某节点主观下线。

  • 维护自身故障列表

image.png
image.png

故障恢复

  1. 检查资格
    1. 从节点与故障主节点的断线时间
    2. 越接近主节点的offset,越优先选举为主节点。
  2. 选举投票
    1. 从节点让主节点给他投票
  • master宕机后,slave修改master_replid,变为master节点。
  • master恢复后,变为slave节点

image.png

集群迁移

Redis-shake

redis-full-check检查集群是否一致。

redis cluster配置

  • cluster-require-full-coverage:允许部分节点发生故障。否则,如果一个节点宕机没有从节点,集群将不可用。【默认yes,建议设置no】
  • cluster-node-timeout:某个节点持续timeout的时间
    • cluster-slave-validity-factor

      Hash Tag【确保一组key映射到同一个slot中】

      提升mget效率。

user:{user1}:ids和user:{user1}:tweets 对他们取hash结果是一样的=hash(user1)
当一个key包含 {} 的时候,就不对整个key做hash,而仅对 {} 包括的字符串做hash。

热点key

key后面加随机1、2、3、4。请求的时候也随机加。?