redis集群系列四

输出是多么快乐的一件事情,hurray~

1 集群的完整性

  • 如果参数cluster-require-full-coverage设置为yes(默认值),则所有槽都需要并指派到节点上,保护集群的完整性。
  • 如果参数cluster-require-full-coverage设置为no,在某些分片故障切换的时候,其他节点还是可用的
# cluster-require-full-coverage yes

2 大集群的带宽消耗

2.1 大集群的带宽消耗主要有三方面

  • 消息频率:节点发现与其他节点最后通讯时间超过cluster-node-timeout/2时会直接发送ping消息
  • 消息数据量:slots槽数组(2KB)+ 整个集群1/10的状态数据(1个节点的状态数据104bytes)
  • 物理机器上的节点规模

2.2 大集群的带宽消耗预估量

  • 以200个节点为例子,20台物理机器,每台物理机器10个节点。

  • 实际通信的过程中, AB两个节点进行ping/pong,A会通过一个随机的端口向节点B的集群通讯端口发送ping消息,节点B通过集群通信端口向A发送pong消息。所以A节点的入口带宽,不仅包含本身的集群端口,也包含随机端口,而随机端口正是其他节点的集群通讯端口的出口带宽。

  • 那么可以计算出来,1台机器的入口带宽:

每个消息是2kb+20*104bytes=4kb
1台机器集群端口的入口带宽:4kb*190*2*10/15=1203kb
实际的1台机器的入口带宽=所有机器集群端口的出口带宽+本台机器的集群端口的入口带宽=1203kb*20=24mb左右

有人做了一个抓包统计gossip消息实验及分析,很细致,感兴趣或者自己想抓包分析的可参考:https://github.com/moooofly/MarkSomethingDown/blob/master/Redis/Redis%20%E4%BD%BF%E7%94%A8%E9%97%AE%E9%A2%98%E6%B1%87%E6%80%BB%EF%BC%88%E7%BD%91%E6%96%87%EF%BC%89.md

集群的带宽消耗,主要由读写命令和gossip消息消耗;所以搭建redis集群要注意根据业务规模和消息通信成本做好规划。

官方建议集群的最大规模在1000以内。建议合理选择哦

3 pub/sub 广播问题

  • 对集群所有的主节点执行subscribe订阅test频道
  • 连接集群发布test频道的消息
  • 集群内所有节点订阅test频道的都收到了消息

集群模式下的publish广播问题,也会消耗集群内的网络带宽。这种情况建议使用sentinel来专门用于pub/sub来规避

4 集群倾斜

4.1 数据倾斜

一般分为以下几种情况

  1. 节点和槽分配不均匀
  2. 不同的槽对应的键值差异较大
    1. case:大量使用hash_tag,会产生不同的键映射到同一个槽
    2. 可以使用command: cluster countkeysinslot {slot}获取slot的键值数目,然后使用command: cluster getkeysinslot {slot} {count} 循环迭代出槽下所有的键
  3. 集合对象包含大量元素(大key)
    1. 可以使用命令:redis-cli --bigkeys
    2. 大key,比如几百M,可能会在migrate过程中超时失败
  4. 内存配置不一致
    1. 有些压缩数据结构的配置不一致(hash-max-ziplist-value、set-max-intset-entries等)

4.2 请求倾斜

可能情况:热key对应高算法复杂度的命令,或者大对象操作hegtall、smembers

建议:使用hmget代替hgetall避免全部读取

5 读写分离

5.1 只读连接

  1. 集群模式下,从节点是不接受任何读写请求的,从节点接收到的读写命令会重定向到负责槽的主节点。
  2. 需要使用从节点分担读压力,需要连接从节点,输入readonly,从节点接收到的读命令,如果key属于自己正在复制的主节点则直接返回,否则返回重定向信息
    1. readonly是连接级别生效的,每次新建连接都需要执行readonly
    2. readwrite命令可以关闭连接只读状态
    3. 可以通过client list查看客户端连接的状态:flags=N表示普通客户端
/data # redis-cli
127.0.0.1:6379> client list
id=28 addr=10.0.129.186:6379 fd=21 name= age=19730 idle=5 flags=M db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
id=20058 addr=127.0.0.1:34716 fd=23 name= age=8 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client
127.0.0.1:6379> get 100
(error) MOVED 339 10.0.129.186:6379
127.0.0.1:6379> readonly
OK
127.0.0.1:6379> client list
id=28 addr=10.0.129.186:6379 fd=21 name= age=19753 idle=8 flags=M db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
id=20058 addr=127.0.0.1:34716 fd=23 name= age=31 idle=0 flags=r db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client
127.0.0.1:6379> get 100
"100"
127.0.0.1:6379> readwrite
OK
127.0.0.1:6379> get 100
(error) MOVED 339 10.0.129.186:6379

5.2 读写分离

  1. 实现方式,需要对客户端进行以下修改
    1. 维护每个主节点可用的从节点列表(cluster slave master-nodeId 可以获取到主节点下所有从节点的信息)
    2. 读命令进行路由到从节点
    3. 从节点新建的连接开启readonly状态
  2. 其他替代方案
    1. 部署多套redis集群,客户端多写来维护;读选择距离最近的redis集群

6 手动故障转移

6.1 操作方式

在从节点上执行cluster failover,客户端请求会有短暂的阻塞,但不会丢失数据。流程如下:

  1. 从节点通知主节点停止处理请求
  2. 主节点发送给对应从节点,延迟复制的数据
  3. 从节点同步了该数据,直到主从复置的偏移量一致【保证数据不丢失】
  4. 从节点立刻发起投票选举(因为这个执行cluster failover的从节点是唯一的,所以不需要延迟选举)。选举成功之后变成主节点,并向集群广播
  5. 旧节点收到消息后更新自身配置为从节点,解除客户端请求阻塞,这些请求会被重定向到新的主节点上
  6. 旧节点向新的主节点发起全量复制流程

6.2 应用场景

  1. 主节点所在机器要迁移到新的机器
  2. 自动故障转移失败,通过手动转移故障可以恢复部分节点。自动故障转移失败的场景:
    1. 主节点和对应的从节点全部故障了
    2. 健康的从节点没有故障转移的资格,主从复制的短线时间超过:(server.repl_ping_slave_period * 1000) +
      (server.cluster_node_timeout * server.cluster_slave_validity_factor)
    3. 从节点的故障选举失败,没有在cluster_node_timeout*2时间内完成
    4. 集群内超过半数以上的主节点同时故障了

6.3 操作命令

  1. cluster failover:没有实际的failure,但是希望master发生主从切换(具体哪一个从提升为主,看在哪一个主上执行cluster failover),切换是一个安全的方式,没有任何数据丢失。工作的流程见下。最终,旧的master的client连接会自动地转移到新的master;只有旧master的所有replication stream同步完成,副本才会变成新的master。

    1. step1 副本告诉主:停止接受来自client的查询请求
    2. step2 主回复副本当前的replication offset
    3. step3 副本等待replication offset和主的一致,保证主的数据都被同步过来了
    4. step4 副本开始failover,包含一个来自多数master的configuration epoch,然后广播新的配置文件
    5. step5 老的master 收到配置文件的更新:解锁他的client,开始回复redirection messages告诉client去找新的master
  2. cluster failover force:

    1. 从节点收到该请求,直接发起选举,不需要跟主确定主从偏移量(从节点复制延迟的数据会丢失)
    2. 从节点选举成功之后成为主并开启广播
  3. cluster failover takeover:

    1. 集群内超过半数以上的主都挂了,没法投票。从节点收到该请求,不再进行选举流程而是直接更新本地配置纪元并替换主节点

    2. 因为takeover模式没有通过领导选举,可能配置纪元会存在冲突

      1. 如果有冲突,集群会以nodeId更大的为准,可能会导致丢数据(网络分区恢复后,会出现拥有相同slot的两个主节点)

附录

不好意思,我又要推荐了哈哈

发现github上一个分析的很细致的资料,这个人总结的东西有点深度和不同,喜欢的可以自取:

https://github.com/moooofly/MarkSomethingDown

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值