Redis 集群的实现原理是什么?
Redis 集群的实现原理是什么?
概述
redis集群是通过多个redis实例组成的。每个实例存储部分数据(每个实例中的数据是不重复的).
详解:
-
实现机制:
- 哈希槽机制来分配数据,将整个键空间划分成16384个槽。
-
存储: 每个实例负责一定范围的哈希槽,数据的key经过哈希函数计算后,对16384取余,即可定位到对应的节点。
-
查询:
-
客户端在发送请求的时候,会通过集群的任意节点进行连接
-
如果该节点存储了对应的数据则直接返回
-
反之会根据该请求的键值计算哈希槽,并路由到正确的节点。
-
-
redis集群中节点之间是怎么实现信息同步的?
-
redis集群内每个节点都会保存集群的完整拓扑信息,包括每个节点的ID、IP地址、端口、负责的哈希槽范围等。
-
节点之间使用Gossip协议进行状态交换,以保持集群的一致性和故障检测。
-
每个节点会周期性的发送PING和PONG消息,交换集群信息,使得集群信息得以同步。
Gossip协议是什么?
Gossip协议主要特点:
-
分布式信息传播: 每个节点定期向其他节点发送其状态信息,确保所有节点对集群的状态有一致的视图。
-
低延迟和高效率: Gossip协议设计为轻量级的通信方式,能够快速传播信息,减少单点故障带来的风险。
-
去中心化: 没有中心节点,所有节点平等的参与信息传播,提高了系统的鲁棒性。
工作原理:
-
报告状态: 每个节点在特定的事件间隔内,向随机选择的其他节点发送其自身的状态信息,包括节点的主从关系、槽位分布等。
-
信息更新: 接收到状态信息的节点会根据所接受的数据更新自己的状态,并将更新后的状态继续传播给其他节点。
-
节点检测: 通过周期性交换状态信息,节点可以检测到其他节点的存活状态。如果某个节点未能在预定时间响应,则该节点会被标记为故障节点。
-
容错处理: 在检测到节点故障后,集群中的其他节点可以采取措施,例如:重新分配槽位,以保持系统的高可用性。
Gossip协议的优点:
-
快速收敛: Goosip协议能够快速传播信息,确保集群状态的迅速更新。
-
降低网络负担:由于信息是以随机节点间的对话方式传播,避免了集中式的状态查询,从而降低了网络流量。
Redis集群的分片原理
-
redis集群会将数据分散到16384个哈希槽中
-
集群中每个节点负责一定范围的哈希槽
-
在redis集群中,使用CRC16哈希算法计算键的哈希槽,以确定该键应该存储在哪个节点。
-
16384=2的14次方
图示:
每个节点会拥有一部分的槽位,然后对应的键值会根据其本身的key,映射到一个哈希槽中,其主要流程如下:
-
根据键值的key,按照CRC16算法计算一个16bit的值,然后将16bit的值对16384进行取余运算,最后得到一个对应的哈希槽编号。
-
根据每个节点分配哈希槽区间,对应编号的数据落在对应的区间上 ,就能找到对应的分片实例。
如下图:
注意: redis的客户端可以访问集群中的任何一个节点,正常情况下,当前节点是包含这个数据的。如果,槽被转移了,客户端还未来得及更新槽的信息,当前实例没有这个数据,那么会返回MOVED响应给客户端,然后将客户端重定向到对应的实例。(这里的原因是,集群中每个节点,都保存有集群中完整的拓扑信息。)
redis集群中,请求key的详解实例:
前提: redis客户端直接连接的并不是对应key的节点
假设: 客户端连接的是集群中的node1,但是需要访问的数据存储在node3中,键为user:1001
查询过程:
-
计算哈希值:
-
客户端使用CRC16算法计算user:1001的哈希值,假设为12345
-
计算哈希槽:12345%16384 = 12345
-
-
查询请求:
- 因为客户端连接的是集群中的node1节点,所以客户端发送查询命令get user:1001到node1
-
node1响应:
-
node1检测到请求对应的user:1001属于node3,
-
node1给客户端返回一个moved错误,告诉客户端请求的键在另一个节点上。moved错误中会返回目标节点的信息。
-
-
客户端重新连接:
- 客户端根据返回的目标节点信息,与新的节点node3进行连接
-
再次发送查询请求
- 客户端向node3发送请求命令 get user:1001
-
获得结果
- node3查询到user:1001的值,假设为{“name”:"凯歌","age":"18"},并返回结果给客户端。
为什么哈希槽个数是16384?
-
消息大小的考虑:
-
正常的心跳包需要带上节点的完整配置数据,心跳是比较频繁的。所以需要考虑数据包的大小,如果使用16384数据包只需要2k,如果使用65535则需要8k
-
实际上槽位信息使用了一个长度为16384位的数组来表示,节点拥有哪个槽位,旧件对应位置的数据信息设置为1,否则为0
-
计算公式:
- 16384/8/1024=2KB
-
-
集群规模的考虑:
- 一般集群的节点个数不会超过1000个,16384够用并且保证了每个分片上的槽的数量又不会太少。
