Redis 的集群模式包括主从模式、哨兵模式以及切片模式。
需要着重强调的是,在 Redis 主从模式集群和哨兵模式集群当中,都只存在一个主节点,和若干个从节点。只有在 Redis Cluster 集群模式下才有可能出现多个 Redis 主节点,因为它们保存着不同分片的数据。
这个问题是我自己提出来的,也是在复习 Redis 的过程中困扰我比较久的。
实际上回答这个问题很简单,Redis 分布式锁的 RedLock 算法是客户端向若干个不同的 Redis 集群或 Redis 单例发送加锁请求。
此外需要注意的是,尽管 Redis Cluster 集群确实包含多个 Redis 主节点,但是 Redis Cluster 集群也不能用于实现 RedLock 算法,因为 RedLock 算法要求加锁的 Redis 实例是完全独立和隔离的,Redis Cluster 集群中的 Redis 主节点保存的是大型缓存的分片数据,不具备独立和隔离性。
综上所述,RedLock 算法中,客户端请求加锁的多个 Redis 主节点一定是不同的 Redis 实例,比如若干个 Redis 集群,或一部分 Redis 集群加上一部分 Redis 单例。
通过哈希槽以及 CRC 算法来实现 key 到数据切片的映射。具体来说,通过 CRC 算法可以将 key 映射到 0~65536 之间的整形数据,再对 16384 取模,将 key 映射为 0~16384 之间的一个整形数据,16384 为切片集群的哈希槽槽数。
Redis 切片集群在创建时可以自动或手动地将哈希槽分配到具体的 Redis 节点。
首先,从节点会建立与主节点之间的 socket 连接。
连接就绪之后,主节点开启 RDB 快照生成,并将生成期间的写命令写入同步缓冲区。
RDB 快照生成完成后,通过 socket 连接传输给从节点,从节点加载快照完成初次同步,再读取主节点同步缓冲区当中的写命令并加载,完成主从同步。
在主从模式下,主节点和从节点会各自维护一个 offset 字段,用于相互告知当前 Redis 数据的同步进度。
主从模式下,主从同步完成之后,主节点和从节点会自动维护一个 offset 字段,在增量同步时,主从节点比对 offset 来确定需要同步哪些增量数据。如果从节点下线后再次上线,要读取的数据在 repl_backlog_buffer 当中,则采用增量同步,否则重新进行全量同步。
无法完全避免,只能尽可能地降低主从复制的不一致程度。具体来说,可以让主从节点位于同一个机房,降低同步的延迟。或者由外部程序监控主从复制的进度,如果主从复制之间的进度差距大于阈值,让客户端不再访问从节点读取数据,而是直接访问主节点。
从节点只读,因此不能给删除过期的 key,此时如果客户端访问从节点中过期的 key,仍然能够得到 value。从节点当中过期的 key 依赖于主节点同步 DEL 命令来删除。
异步复制。主节点接收到写命令后,先写入缓冲区,再等待时机异步发送给从节点。异步复制确保了主从集群的高可用性。
哨兵机制是对普通主从集群的升级,哨兵机制进一步为主从集群引入了故障监测与故障自动转移。具体来说,一个哨兵集群中会引入至少 3 个 Sentinel 哨兵节点,对 Redis 主从节点进行监视,并通过 Raft 协议确保彼此之间消息的一致性。当 Redis 从节点宕机时,会通知集群管理员,当主节点宕机时,为了确保服务可用,会自动选举一个从节点成为新的主节点,实现故障自动转移。一个哨兵集群需要至少 3 个 Sentinel 节点,1 个主节点以及 1 个及以上的从节点。
生产环境中通常部署 3 个或 5 个 Sentinel 节点(奇数个),这些节点应该分布在不同的物理机器或可用区上。
一. 故障检测阶段
二. 领导者选举阶段
三. 选举新的主节点
领导者 Sentinel 根据以下方式选取 Redis 从节点成为主节点:
replica-priority
,优先级高的从节点会被选取。四. 执行故障转移
五. 配置传播
选举算法细节
一个 Redis Sentinel 集群当中,如果 Redis 主节点突然与集群失联,而此时客户端向主节点写入数据,此时写入的数据会赞存在缓冲区当中。Sentinel 集群发现主节点丢失,会推举领导者 Sentinel 在从节点中推举新的主节点。旧的主节点重新上线之后,由于此时已经有了新的主节点,会短暂地出现两个主节点同时存在的情况,此之谓集群的脑裂。
旧的主节点发现已经有新的主节点之后,会自动降级为从节点,然后从新的主节点通过全量同步的方式同步数据,方才客户端的写命令由于没有写入到新的主节点当中,会丢失。因此集群的脑裂会造成短暂的数据不一致。
异步复制同步丢失
主节点仅在足够多的从节点同步了数据时才会允许写入操作,避免数据未同步就宕机。如果从节点延迟超过阈值或从节点数量不足,主节点会拒绝写入。
合理配置 Sentinel 参数
适当延长 Sentinel 判断主节点客观下线的延迟时间,避免由于网络抖动而产生脑裂,导致数据不一致。