【Redis】Redis Cluster 简单介绍

Redis Cluster 是 Redis 3.0 提供的一种分布式解决方案, 允许数据在多个节点之间分散存储, 从而实现高可用性和可扩展性。

特点:

  1. 分片: Redis Cluster 将数据分散到多个节点, 通过哈希槽 (hash slots) 机制将键映射到不同的节点上。总共有 16384 个哈希槽, 每个节点负责一部分槽。
  2. 高可用性: Redis Cluster 支持主从复制, 每个主节点可以有多个从节点, 从节点可以在主节点故障时自动提升为主节点。
  3. 自动故障转移: 当主节点宕机时, Cluster 会自动检测并选择从节点提升为新的主节点, 保持服务的可用性。
  4. 无中心化: Redis Cluster 是去中心化的, 没有单点故障。所有节点都可以处理请求, 提升了系统的健壮性。

解决的问题:

  1. 数据存储限制: 单个 Redis 实例的内存限制使其在处理大规模数据时受到约束, Redis Cluster 通过分片技术克服了这一限制, 支持更大规模的数据存储。
  2. 高可用性需求: 在传统的 Redis 配置中, 主节点故障会导致服务不可用。Redis Cluster 通过主从复制和自动故障转移确保服务的连续性, 满足高可用性的需求。
  3. 负载均衡: 随着数据量和访问量的增加, Redis Cluster 可以通过增加节点和分配哈希槽实现负载均衡, 避免某一节点过载。

1 Redis Cluster 的搭建

Redis Cluster 可以看成是由多个 Redis 实例组成的数据集合。
客户端不需要关注数据的子集到底存储在哪个节点, 只需要关注这个集合整体。

那么如何搭建一个这样的集群呢?
注: 这里用一台集群搭建集群, Ip 地址为 192.169.10.10, 7000/7001/7002 为主节点的端口, 8000/8001/8002 为对应的从节点的端口。

1.1 修改配置

修改 redis.conf 配置文件中的 3 个参数

  1. cluster-enabled yes
  2. cluster-config-file “node-7000.conf”
  3. cluster-node-timeout 5000

其他的参数和单个 Redis 实例的一样。

cluster-enabled yes: Redis 实例可以分为单机模式 (standalone) 和集群模式 (cluster)。 yes 开启为集群模式。

cluster-config-file: 该参数指定了集群配置文件的位置。每个节点在运行过程中, 会维护一份集群配置文件; 每当集群信息发生变化时 (如增减节点), 集群内所有节点会将最新信息更新到自己维护的配置文件。
当节点重启后, 会重新读取该配置文件, 获取集群信息, 可以方便的重新加入到集群中。
也就是说当 Redis 节点以集群模式启动时, 会首先寻找是否有集群配置文件, 如果有则使用文件中的配置启动, 如果没有, 则初始化配置并将配置保存到文件中。 集群配置文件由 Redis 节点维护, 不需要人工修改。

cluster-node-timeout: 节点之间心跳超时时间

cluster-require-full-coverage: 默认值为 yes, 将其修改为 no, 表示 Redis 节点的槽没有完全分配时,集群仍可以上线。

1.2 启动节点

通过 redis-server redis.conf 配置文件启动 Redis。
可以通过 cluster nodes 查看当前的节点集群信息。

1.3 节点握手

执行 redis-cli --cluster create 命令

节点启动以后是相互独立的,并不知道其他节点存在, 需要进行节点握手。
将独立的节点组成一个网络。注下面的操作, 不能使用 localhost 和 127.0.0.1, 需要使用局域网 Ip 或 公网 Ip

redis-cli --cluster create 192.169.10.10:7000 192.169.10.10:7001 192.169.10.10:7002 192.169.10.10:8000 192.169.10.10:8001 192.169.10.10:8002 --cluster-replicas 1

–cluster-replicas 1 表示每个主节点有 1 个从节点, 后面的多个 {ip:port} 表示节点地址。(默认: 所有节点平均分成 2 组, 前面一组为主节点, 后面一组为从节点)

执行创建命令后, Redis 会给出一个预计的方案, 对 6 个节点分配 3 主 3 从, 如果认为没有问题,输入 yes 确认

>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.169.10.10:8000 to 192.169.10.10:7000
Adding replica 192.169.10.10:8001 to 192.169.10.10:7001
Adding replica 192.169.10.10:8002 to 192.169.10.10:7002
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: dfdc9c0589219f727e4fd0ad8dafaf7e0cfb4f1c 192.169.10.10:7000
   slots:[0-5460] (5461 slots) master
M: 8c878b45905bba3d7366c89ec51bd0cd7ce959f8 192.169.10.10:7001
   slots:[5461-10922] (5462 slots) master
M: aeeb7d7076d9b25a7805ac6f508497b43887e599 192.169.10.10:7002
   slots:[10923-16383] (5461 slots) master
S: ebc479e609ff8f6ca9283947530919c559a08f80 192.169.10.10:8000
   replicates aeeb7d7076d9b25a7805ac6f508497b43887e599
S: 49385ed6e58469ef900ec48e5912e5f7b7505f6e 192.169.10.10:8001
   replicates dfdc9c0589219f727e4fd0ad8dafaf7e0cfb4f1c
S: 8d6227aefc4830065624ff6c1dd795d2d5ad094a 192.169.10.10:8002
   replicates 8c878b45905bba3d7366c89ec51bd0cd7ce959f8
Can I set the above configuration? (type 'yes' to accept): 

输入 yes 后

>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 192.169.10.10:7000)
M: dfdc9c0589219f727e4fd0ad8dafaf7e0cfb4f1c 192.169.10.10:7000
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 8c878b45905bba3d7366c89ec51bd0cd7ce959f8 192.169.10.10:7001
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: ebc479e609ff8f6ca9283947530919c559a08f80 192.169.10.10:8002
   slots: (0 slots) slave
   replicates aeeb7d7076d9b25a7805ac6f508497b43887e599
S: 49385ed6e58469ef900ec48e5912e5f7b7505f6e 192.169.10.10:8000
   slots: (0 slots) slave
   replicates dfdc9c0589219f727e4fd0ad8dafaf7e0cfb4f1c
M: aeeb7d7076d9b25a7805ac6f508497b43887e599 192.169.10.10:7002
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 8d6227aefc4830065624ff6c1dd795d2d5ad094a 192.169.10.10:8001
   slots: (0 slots) slave
   replicates 8c878b45905bba3d7366c89ec51bd0cd7ce959f8
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

1.4 Redis Cluster 相关的命令

集群命令

命令效果
cluster info打印集群的信息
cluster nodes列出集群当前已知的所有节点 (node), 以及这些节点的相关信息
cluster meet 将 ip 和 port 所指定的节点添加到集群当中, 让它成为集群的一份子, 这时候没有主从关系
cluster forget <node_id>从集群中移除 node_id 指定的节点 (保证空槽道)
cluster replicate <node_id>将当前节点设置为 node_id 指定的节点的从节点
cluster saveconfig将节点的配置文件保存到硬盘里面

槽slot命令

命令效果
cluster addslots [slot …]将一个或多个槽 (slot) 指派 (assign) 给当前节点
cluster delslots [slot …]移除一个或多个槽对当前节点的指派
cluster flushslots移除指派给当前节点的所有槽, 让当前节点变成一个没有指派任何槽的节点
cluster setslot node <node_id>将槽 slot 指派给 node_id 指定的节点, 如果槽已经指派给另一个节点, 那么先让另一个节点删除该槽, 然后再进行指派
cluster setslot migrating <node_id>将本节点的槽 slot 迁移到 node_id 指定的节点中
cluster setslot importing <node_id>从 node_id 指定的节点中导入槽 slot 到本节点
cluster setslot stable取消对槽 slot 的导入 (imort) 或者迁移 (migrate)

键命令

命令效果
cluster keyslot 计算键 key 应该被放置在哪个槽上
cluster countkeysinslot 返回槽 slot 目前包含的键值对数量
cluster getkeysinslot 返回 count 个 slot 槽中的键

2 故障转移

集群的实现与哨兵思路类似: 通过定时任务发送 PING 消息检测其他节点状态。节点下线分为主观下线和客观下线, 客观下线后选取从节点进行故障转移。

与哨兵一样, 集群只实现了主节点的故障转移, 从节点故障时只会被下线, 不会进行故障转移。因此, 使用集群时, 应谨慎使用读写分离技术, 因为从节点故障会导致读服务不可用, 可用性变差。

大体是:

  1. slave 发现自己的 maste 变为 Fail 状态, 偏尝试进行 Failover, 以期成为新的 master
  2. slave 将自己记录的集群 currentEpoch + 1, 然后广播 FAILOVER_AUTH_REQUEST 信息
  3. 其他节点收到改消息后, 只有 master 节点会进行响应, 判断请求这的合法性, 并发送 FAILOVER_AUTH_ACK, 对每一个 epoch 只发送一次 ack
  4. 尝试 Failover 的 slave 收集 FAILOVER_AUTH_ACK
  5. 超过半数后变成新的 master
  6. 广播 Pong 通知其他集群节点

节点数量: 在故障转移阶段, 需要由主节点投票选出哪个从节点成为新的主节点, 从节点选举胜出需要的票数为 N/2+1, 其中 N 为主节点数量 (包括故障主节点), 但故障主节点实际上不能投票。
因此为了能够在故障发生时顺利选出从节点, 集群中至少需要3个主节点 (且部署在不同的物理机上)。

故障转移时间: 从主节点故障发生到完成转移, 所需要的时间主要消耗在主观下线识别、主观下线传播、选举延迟等几个环节。具体时间与参数 cluster-node-timeout 有关, 一般来说:
故障转移时间(毫秒) ≤ 1.5 * cluster-node-timeout + 1000
cluster-node-timeout 的默认值为 15000ms (15s), 因此故障转移时间会在 20s 量级

3 Hash Tag

有些 multi key 操作是不能跨阶段的, 如果要让某些数据统一分配到同一个节点上, 可以借助 Hast Tag 功能。

Hash Tag 原理是: 当一个 key 包含 {} 的时候, 不对整个 key 做 hash, 而仅对 {} 包括的字符串做 hash。
Hash Tag 可以让不同的 key 拥有相同的 hash 值, 从而分配在同一个槽里, 这样针对不同 key 的批量操作 (mget/mset等), 以及事务、Lua 脚本等都可以支持。

Hash Tag 可能会带来数据分配不均的问题, 这时可以

  1. 调整不同节点中槽的数量,使数据分布尽量均匀
  2. 避免对热点数据使用 Hash Tag, 导致请求分布不均

4 Redis Cluster 的不足

  1. Client 实现复杂, 驱动要求实现 Smart Client, 缓存 slots mapping 信息并及时更新, 提高了开发难度, 客户端的不成熟影响业务的稳定性
  2. 节点会因为某些原因发生阻塞 (阻塞时间大于 cluster-node-timeout), 被判断下线, 这种 failover 是没必要的
  3. 数据通过异步复制, 不保证数据的强一致性
  4. 多个业务使用同一套集群时, 无法根据统计区分冷热数据, 资源隔离性较差, 容易出现相互影响的情况

5 参考

深入学习Redis(5):集群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值