集群架构

集群就是使用网络将若干台计算机连通起来,并提供统一的管理方式,使其对外呈现单机的服务效果。

作用:

  • 分散单台服务器的访问压力,实现负载均衡
  • 分散单台服务器的存储压力,实现可扩展性
  • 降低单台服务器宕机带来的业务灾难

集群架构的数据存储设计:
先将 key 通过CRC16(key)%16384进行计算,得到的数用来确定这个key在集群中哪台计算机的存储空间位置。

redis会将所有的存储空间计划切割成16384份(每份代表的是一个存储空间,不是一个key的保存空间,一个存储空间内可以放若干个key),每台主机保存若干个存储空间。

将key按照计算出的结果放到对应的存储空间。

这个存储空间称为“槽”(slot)。

扩展新的机器:将原来每台服务器上的槽拿出来一部分,放到扩新增加的服务器上。增加了可扩展性。

如果移除一台服务器,则将该服务器上的槽返还现有的服务器中。

集群架构的内部通讯设计:

各个服务器之间会进行互联,每台服务器都会记录其他所有服务器上的槽编号,便于后续查找。

客户端如果向A服务器发出一个key,经过CRC16(key)%16384运算后得出其所在的槽。如果该key对应的槽就在A服务器上,则直接返回。如果未命中,则通过A服务器上记录的其他服务器槽编号,可以得知该key所在的服务器、这样可以保证最多两次即可命中。

集群开启示例

编辑配置文件:

  1. port 6379
  2. daemonize no
  3. dir /home/redis/data
  4. dbfilename dump-6379.rdb
  5. rdbcompression yes
  6. rdbchecksum yes
  7. save 10 2
  8. appendonly yes
  9. appendfsync always
  10. appendfilename appendonly-6379.aof
  11. bind 127.0.0.1
  12. databases 16
  13. # 不需要再在配置文件中指定对应的master
  14. # 增加关于集群的配置
  15. # 使能集群
  16. cluster-enabled yes
  17. # 集群自动生成的节点配置文件
  18. cluster-config-file nodes-6379.conf
  19. # 节点超时下线时长
  20. cluster-node-timeout 10000

旧版本Redis启动集群使用的 src/redis-trib.rb,这是一个 ruby 脚本,需要先安装ruby:

  1. # --replicas 后面的第一个数字表示:一个master对应几个slave。
  2. # 再往后列出所有的服务器的ip、端口号。redis会自动将前面的几个设置为master,后面的设置为slave。
  3. # 后面列出的ip、端口号的数量,要和--replilcas后的slave/master比例 对应起来。
  4. ./redis-trib.rb create --replicas 1 127.0.0.1:6379

redis 5.0之后需要使用redis-cli命令进行替换:

  1. redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1

启动之后,便会根据配置文件配置的路径、node文件名在对应文件夹下生成对应的node节点文件。此时的node节点文件内只保存本Redis服务器的信息:

  1. [redis@mycentos7 data]$ cat nodes-6379.conf
  2. ddd8d8c57f7919aac742845b0a2ee8aa46f8daf0 :0@0 myself,master - 0 0 0 connected
  3. vars currentEpoch 0 lastVoteEpoch 0

Redis自动分析出几台服务器扮演的主/从角色后,会提示:Can I set the above configuration? (type 'yes' to accept):

输入yes之后,会将这些主从角色信息、所有的节点信息都保存进node节点文件中。例如:

  1. [redis@mycentos7 data]$ cat nodes-6379.conf
  2. cafbf4c76fecdc705569eb4d1a841ddaa5a247e3 127.0.0.1:6381@16381 master - 0 1611830119789 3 connected 10923-16383
  3. ddd8d8c57f7919aac742845b0a2ee8aa46f8daf0 127.0.0.1:6379@16379 myself,master - 0 1611830117000 1 connected 0-5460
  4. c5e86db426ff6597eb6a6e37176ca5a760d34443 127.0.0.1:6380@16380 master - 0 1611830118771 2 connected 5461-10922
  5. d48006559e8fdbfaafcbb2b7670e5527f50866ab 127.0.0.1:6383@16383 slave c5e86db426ff6597eb6a6e37176ca5a760d34443 0 1611830116000 2 connected
  6. fa4f94fea01550d3c5368632d1a937a0d497f8e3 127.0.0.1:6382@16382 slave ddd8d8c57f7919aac742845b0a2ee8aa46f8daf0 0 1611830119000 1 connected
  7. cad69dd5aa16eb6420b51b67f68dd4d04154cef5 127.0.0.1:6384@16384 slave cafbf4c76fecdc705569eb4d1a841ddaa5a247e3 0 1611830118000 3 connected
  8. vars currentEpoch 6 lastVoteEpoch 0

相关配置项

  • 设置加入cluster,成为其中的节点
    1. cluster-enabled yes|no
  • cluster配置文件名,该文件属于自动生成,仅用于快速查找文件并查询文件内容
    1. cluster-config-file <filename>
  • 节点服务响应超时时间,用于判定该节点是否下线或切换为从节点
    1. cluster-node-timeout <milliseconds>
  • master连接的slave最小数量
    1. cluster-migration-barrier <count>

设置和获取数据

如果直接使用 redis-cli开启客户端,使用set name zhangsan设置数据时,可能会因为该key对应的槽不在当前客户端连接的master上而报错:

  1. [redis@mycentos7 ~]$ redis-cli
  2. 127.0.0.1:6379> set name zhangsan
  3. # 错误,请移至位于6380端口的5798号槽进行操作
  4. (error) MOVED 5798 127.0.0.1:6380

为避免这种情况,可以使用专门的参数 -c 开启集群客户端:

  1. redis-cli -c

这样,集群便会自动将该Key重定向到对应的服务器上的槽中:

  1. [redis@mycentos7 ~]$ redis-cli -c
  2. 127.0.0.1:6379> set name zhangsan
  3. -> Redirected to slot [5798] located at 127.0.0.1:6380
  4. OK

可以使用redis的cluster nodes指令查看节点信息:

  1. 127.0.0.1:6380> cluster nodes
  2. c5e86db426ff6597eb6a6e37176ca5a760d34443 127.0.0.1:6380@16380 myself,master - 0 1611883770000 2 connected 5461-10922
  3. ddd8d8c57f7919aac742845b0a2ee8aa46f8daf0 127.0.0.1:6379@16379 master - 0 1611883769000 1 connected 0-5460
  4. cafbf4c76fecdc705569eb4d1a841ddaa5a247e3 127.0.0.1:6381@16381 master - 0 1611883770213 3 connected 10923-16383
  5. fa4f94fea01550d3c5368632d1a937a0d497f8e3 127.0.0.1:6382@16382 slave ddd8d8c57f7919aac742845b0a2ee8aa46f8daf0 0 1611883770000 1 connected
  6. d48006559e8fdbfaafcbb2b7670e5527f50866ab 127.0.0.1:6383@16383 slave c5e86db426ff6597eb6a6e37176ca5a760d34443 0 1611883769191 2 connected
  7. cad69dd5aa16eb6420b51b67f68dd4d04154cef5 127.0.0.1:6384@16384 slave cafbf4c76fecdc705569eb4d1a841ddaa5a247e3 0 1611883771234 3 connected

客户端Cluster节点相关命令

  • 查看集群节点信息
    1. cluster nodes
  • 进入一个从节点redis,切换其主节点
    1. cluster replicate <master-id>
  • 发现一个新节点,新增主节点
    1. cluster meet ip:port
  • 忽略一个没有slot的节点
    1. cluster forget <id>
  • 手动故障转移
    1. cluster failover

主从下线和主从切换

当一台slave服务器下线后,其对应的master会将其标记为下线状态,并通知集群内其他所有服务器。等该slave服务再次上线后,其对应的master会重新进行数据同步,将其标记为上线状态,并通知集群内其他服务器删除该slave的下线状态。

当一台master服务器下线后,其对应的slave会连续的发起请求,经过cluster-node-timeout时长之后,slave会将自己设置成master。当原来的master再次上线后,会被设置成slave。