Redis 集群的原理分析

Redis将所有数据划分问16384个槽位slots,每个节点负责一部分槽位,槽位的信息存在于每个节点中。

当Redis Cluster的客户端来链接集群时,会得到一份集群的槽位信息,这样当客户端需要查找存储每个值时,就直接去链接对应的节点就行了,同时如果槽位信息改变了,存在客户端与服务器不一致情况,需要纠正机制来实现校验和调整。

槽位定位算法

key的hashcode%16835

跳转重定位

当客户端向一个,错误的节点发出了指令,节点发现所访问的槽位不归自己所有时,他会向客户端发送一个特殊的跳转指令,同时客户端更新自己的槽位映射的缓存信息。

redis使用槽位扩容缩容影响数据的查找吗 redis槽位算法_Redis

Redis集群节点间的通信机制

Gossip通信协议

维护集群的元数据信息(集群节点信息,主从角色,节点数量,节点共享数据),有2中通信方式

集中式

优点在于元数据的更新和读取,时效性非常好,一旦元数据出现变更立即就会更新到集中式的存储中,其他节 点读取的时候立即就可以立即感知到;不足在于所有的元数据的更新压力全部集中在一个地方,可能导致元数 据的存储压力很多中间件都会借助zookeeper集中式存储元数据。

Gossip式

gossip协议的优点在于元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到所有节点上 去更新,有一定的延时,降低了压力;缺点在于元数据更新有延时可能导致集群的一些操作会有一些滞后。

网络抖动

突然之间部分连接变得不可访问,然后很快又恢复正常,为解决这种问题,Redis Cluster 提供了一种选项cluster­node­timeout,表示当某个节点持续 timeout 的时间失联时,才可以认定该节点出现故障,需要进行主从切换。如果没有这个选项,网络抖动会导致主从频 繁切换 (数据的重新复制)

Redis集群选举原理分析

当Slave发现Master状态变成Failed时,会尝试Failover,即争取成为新的Master节点,但是一个master下面会有多个Slave,这样就会出现竞争:

1. 发现Mater状态变为Fail

2. 将自己的记录的集群的currentEpoch+1(集群选举周期+1), 并广播FAILOVER_AUTH_REQUEST(发起选举请求)信息

3. 其他节点收到该请求,其他小集群的master节点发出一个ack,master节点只会对第一个收到的消息进行ack。

4. Slave计算,如果收到的ack的个数达到集群个数的一半,该Slave把自己的信息改成该小集群的Mater。

5. Slave把自己的元数据信息和自己的信息通知给其他节点,自己变成该小集群的maser。

 如果手动ack的个数一样, 发起下一轮选举,继续周2,3,5步骤。

以上的2不是马上开始了,会做一个delay的时间,所有就发出去FAILOVER_AUTH_REQUEST请求的时间是不一致的,所有不会每次收到的ack都一样。

DelayTime = 500ms + random(0-500ms) + SLAVE_RANK * 1000ms

SLAVE_RANK -> slave里包含master的数据越多,排名越靠前。

集群脑裂数据丢失问题

主节点和其他节点网络不通了,从节点会变成主节点,原来主节点不知道自己网络不通了所以也会继续接受数据写服务。这时候就会同时存在2个Master节点。当老主节点重新加入的集群后,老主节点变成从节点,这个从节点数据就会从新主节点同步数据,从而老主节点数据就会丢失。

使用: min-slaves-to-write 1这个配置可以预防这个问题

只有至少有一个slave同步成功后才算master的写成功。

Zookeeper,nacos都有类似的设计,半数slave写入成功规则

作为缓存,丢少量的数据没关系,如果缓存中没数据了再重新去数据库中去拿。Redis的作用是高可用性,再打了访问来说挡住洪峰。

为什么redis必须有三个以上master

--选举机制决定的,太少的master会导致选举不成功,半数master的ACK。

Redis集群对批量操作的支持

在key的前面加一个大括{},让么个key都放在同一个slot中去

mset {user1}:1:name Allen {user1}:age 24 {user1}:balance 100000000