redis 集群,key不均匀问题

文章详细阐述了Redis的主从复制机制,包括一主二从的场景、主从切换策略,以及全量同步和增量同步的原理。同时,介绍了哨兵模式在选举新master、处理数据倾斜和防止脑裂问题上的作用。此外,提出了优化主从同步的建议,如启用无磁盘复制和调整配置参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 主从复制

1.1 一主二从

  • 主机shutdown后情况如何?从机是上位还是原地待命

从机不动,原地待命,从机数据可以正常使用;等待主机重启动归来

  • 主机shutdown后,重启后主从关系还在吗?从机还能是否复制?

青山依旧在。还可以

1.2 薪火相传

  1. 上一个slave可以是下一个slave的Master,slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风险.
    中途变更转向:会清除之前的数据,重新建立拷贝最新的
    风险是一旦某个slave宕机,后面的slave都没法备份
    2

1.3 反客为主

当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不用做任何修改。
用 slaveof no one 将从机变为主机。

1.4 主从同步原理

1.4.1 全量同步

  • 主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点

  • 两个概念

    • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
    • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

·因此slave做数据同步,必须向master声明自己的replication id 和offset,master才可以判断到底需要同步哪些数据。

master判断发现slave发送来的replid与自己的不一致,说明这是一个全新的slave,就知道要做全量同步了。

master会将自己的replid和offset都发送给这个slave,slave保存这些信息。以后slave的replid就与master一致了。

主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点,流程:
2

  • 主要步骤

    • slave节点请求增量同步
    • master节点判断replid,发现不一致,拒绝增量同步
    • master将完整内存数据生成RDB,发送RDB到slave
    • slave清空本地数据,加载master的RDB
    • master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
    • slave执行接收到的命令,保持与master之间的同步

1.4.2 增量同步

2
先看两个概念: replication bufferrepl_backlog_buffer

repl_backlog_buffer:它是为了从库断开之后,如何找到主从差异数据而设计的环形缓冲区,从而避免全量复制带来的性能开销。如果从库断开时间太久,repl_backlog_buffer 环形缓冲区被主库的写命令覆盖了,那么从库连上主库后只能乖乖地进行一次全量复制,所以 repl_backlog_buffer 配置尽量大一些,可以降低主从断开后全量复制的概率。而在 repl_backlog_buffer 中找主从差异的数据后,如何发给从库呢?这就用到了 replication buffer。

replication buffer:Redis 和客户端通信也好,和从库通信也好,Redis 都需要给分配一个 内存 buffer 进行数据交互,客户端是一个 client,从库也是一个 client,我们每个 client 连上 Redis 后,Redis 都会分配一个 client buffer,所有数据交互都是通过这个 buffer 进行的:Redis 先把数据写到这个 buffer 中,然后再把 buffer 中的数据发到 client socket 中再通过网络发送出去,这样就完成了数据交互。所以主从在增量同步时,从库作为一个 client,也会分配一个 buffer,只不过这个 buffer 专门用来传播用户的写命令到从库,保证主从数据一致,我们通常把它叫做 replication buffer。

1.4.3 repl_backlog原理

这个文件是一个固定大小的数组,只不过数组是环形,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。

repl_baklog中会记录Redis处理过的命令日志及offset,包括master当前的offset,和slave已经拷贝到的offset:
2
slave与master的offset之间的差异,就是salve需要增量拷贝的数据了。

随着不断有数据写入,master的offset逐渐变大,slave也不断的拷贝,追赶master的offset:
2
直到数组被填满:
2
此时,如果有新的数据写入,就会覆盖数组中的旧数据。不过,旧的数据只要是绿色的,说明是已经被同步到slave的数据,即便被覆盖了也没什么影响。因为未同步的仅仅是红色部分。

但是,如果slave出现网络阻塞,导致master的offset远远超过了slave的offset:

2
如果master继续写入新数据,其offset就会覆盖旧的数据,直到将slave现在的offset也覆盖:
2
棕色框中的红色部分,就是尚未同步,但是却已经被覆盖的数据。此时如果slave恢复,需要同步,却发现自己的offset都没有了,无法完成增量同步了。只能做全量同步。
2

1.4.4 为什么还有无磁盘复制模式?

Redis 默认是磁盘复制,但是 ·如果使用比较低速的磁盘,这种操作会给主服务器带来较大的压力 。Redis 从 2.8.18 版本开始尝试支持无磁盘的复制。使用这种设置时,子进程直接将 RDB 通过网络发送给从服务器,不使用磁盘作为中间存储。

无磁盘复制模式:master 创建一个新进程直接 dump RDB 到 slave 的 socket ,不经过主进程,不经过硬盘。适用于 disk 较慢,并且网络较快的时候。

使用 repl-diskless-sync 配置参数来启动无磁盘复制。

使用 repl-diskless-sync-delay 参数来配置传输开始的延迟时间;master 等待一个 repl-diskless-sync-delay 的秒数,如果没 slave 来的话,就直接传,后来的得排队等了;否则就可以一起传

1.5 主从同步优化

从同步可以保证主从数据的一致性,非常重要。

可以从以下几个方面来优化Redis主从就集群:

  • 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

2. 哨兵模式

2.0 哨兵模式 笔记

Sentinel集群选举机制

2.1选举新的master的策略

  1. priority 优先级高
    2

  2. offset 大

  3. 最小的runid 节点

2

2. 俯首称臣

sentinel leader 像选举出来的新 master 执行 slaveof no one 命令,将其升级为 master节点。
sentinel 发送slavleof 命令到其他slave 节点,让他们成为新的master的slave节点。

3. 老master 变成slave 节点

老master 节点恢复后,seltinel leader 让原来的master 降级为salve节点。

3.redis 集群 key 不均匀问题。

如何解决 Redis 数据倾斜、热点等问题
redis中数据倾斜问题的产生和解决方案

redis key 不均衡原因。
数据量倾斜,数据访问倾斜

  1. 数据量倾斜产生的根本原因是:数据在各个redis实例上分布不均匀
    1.1 存在big key
    1.2 Hash Tag 使用不当
    1.3 Slot 分配不均衡
  2. 数据访问倾斜
    2.1 存在 热key, 采用多副本冗余。
    2.2 本地缓存
  3. redis 为什么不采用 一致性hash ,而是分配槽

4 脑裂问题

主从哨兵模式的集群,
master 提供写服务,多个slave 提供读服务。
因为网络问题,导致redis master 节点跟redis slave 节点 和sentinel 节点处于不同的网络分区。
因为此时 假设 master 网络问题,sentinel 感知不到master 的存在,所以将 slave 提升为master 节点。等网络恢复后,存在两个master 。
3

脑裂的危害

原有客户端还像原来的master 写入数据,新的master 节点无法同步这些数据到自身。

当网络问题解决后,sentinel 集群将原先的master 节点降低为slave 节点,此时 大家都会从新的master 同步数据,那么老的master 中的数据造成大量的丢失。

如何解决

min-slvae-to-write:3 主库进行数据同步的最小连接到master 的最少slave 数量,、

  • 比如老大master 已经断连了,表名至少有3个从库,3个从库不到,拒绝写入。

min-slave-max-lag 10 连接到master 的最大延迟时间。

  • 主从复制时,从库给主库发送ack 消息的最大延迟,10s,老master 10s内没收到从的回复,拒绝写入。

Redis 中有两个关键的配置项可以解决这个问题,分别是 min-slaves-to-write(最小从服务器数) 和 min-slaves-max-lag(从连接的最大延迟时间)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值