Redis 集群的实现原理是什么?

Redis 集群的实现原理是什么?

概述

redis集群是通过多个redis实例组成的。每个实例存储部分数据(每个实例中的数据是不重复的).

详解:

  • 实现机制

    • 哈希槽机制来分配数据,将整个键空间划分成16384个槽。
  • 存储: 每个实例负责一定范围的哈希槽,数据的key经过哈希函数计算后,对16384取余,即可定位到对应的节点。

  • 查询:

    • 客户端在发送请求的时候,会通过集群的任意节点进行连接

      • 如果该节点存储了对应的数据则直接返回

      • 反之会根据该请求的键值计算哈希槽,并路由到正确的节点。

redis集群中节点之间是怎么实现信息同步的?

  1. redis集群内每个节点都会保存集群的完整拓扑信息,包括每个节点的ID、IP地址、端口、负责的哈希槽范围等。

  2. 节点之间使用Gossip协议进行状态交换,以保持集群的一致性和故障检测。

  3. 每个节点会周期性的发送PING和PONG消息,交换集群信息,使得集群信息得以同步。

Gossip协议是什么?

Gossip协议主要特点:

  1. 分布式信息传播: 每个节点定期向其他节点发送其状态信息,确保所有节点对集群的状态有一致的视图。

  2. 低延迟和高效率: Gossip协议设计为轻量级的通信方式,能够快速传播信息,减少单点故障带来的风险。

  3. 去中心化: 没有中心节点,所有节点平等的参与信息传播,提高了系统的鲁棒性。

工作原理:

  1. 报告状态: 每个节点在特定的事件间隔内,向随机选择的其他节点发送其自身的状态信息,包括节点的主从关系、槽位分布等。

  2. 信息更新: 接收到状态信息的节点会根据所接受的数据更新自己的状态,并将更新后的状态继续传播给其他节点。

  3. 节点检测: 通过周期性交换状态信息,节点可以检测到其他节点的存活状态。如果某个节点未能在预定时间响应,则该节点会被标记为故障节点。

  4. 容错处理: 在检测到节点故障后,集群中的其他节点可以采取措施,例如:重新分配槽位,以保持系统的高可用性。

Gossip协议的优点:

  1. 快速收敛: Goosip协议能够快速传播信息,确保集群状态的迅速更新。

  2. 降低网络负担:由于信息是以随机节点间的对话方式传播,避免了集中式的状态查询,从而降低了网络流量。

Redis集群的分片原理

  1. redis集群会将数据分散到16384个哈希槽中

  2. 集群中每个节点负责一定范围的哈希槽

  3. 在redis集群中,使用CRC16哈希算法计算键的哈希槽,以确定该键应该存储在哪个节点。

  4. 16384=2的14次方

图示:

每个节点会拥有一部分的槽位,然后对应的键值会根据其本身的key,映射到一个哈希槽中,其主要流程如下:

  1. 根据键值的key,按照CRC16算法计算一个16bit的值,然后将16bit的值对16384进行取余运算,最后得到一个对应的哈希槽编号。

  2. 根据每个节点分配哈希槽区间,对应编号的数据落在对应的区间上 ,就能找到对应的分片实例。

如下图:

注意: redis的客户端可以访问集群中的任何一个节点,正常情况下,当前节点是包含这个数据的。如果,槽被转移了,客户端还未来得及更新槽的信息,当前实例没有这个数据,那么会返回MOVED响应给客户端,然后将客户端重定向到对应的实例。(这里的原因是,集群中每个节点,都保存有集群中完整的拓扑信息。)

redis集群中,请求key的详解实例:

前提: redis客户端直接连接的并不是对应key的节点

假设: 客户端连接的是集群中的node1,但是需要访问的数据存储在node3中,键为user:1001

查询过程:

  1. 计算哈希值

    1. 客户端使用CRC16算法计算user:1001的哈希值,假设为12345

    2. 计算哈希槽:12345%16384 = 12345

  2. 查询请求

    1. 因为客户端连接的是集群中的node1节点,所以客户端发送查询命令get user:1001到node1
  3. node1响应

    1. node1检测到请求对应的user:1001属于node3,

    2. node1给客户端返回一个moved错误,告诉客户端请求的键在另一个节点上。moved错误中会返回目标节点的信息。

  4. 客户端重新连接

    1. 客户端根据返回的目标节点信息,与新的节点node3进行连接
  5. 再次发送查询请求

    1. 客户端向node3发送请求命令 get user:1001
  6. 获得结果

    1. node3查询到user:1001的值,假设为{“name”:"凯歌","age":"18"},并返回结果给客户端。

为什么哈希槽个数是16384?

  1. 消息大小的考虑:

    1. 正常的心跳包需要带上节点的完整配置数据,心跳是比较频繁的。所以需要考虑数据包的大小,如果使用16384数据包只需要2k,如果使用65535则需要8k

    2. 实际上槽位信息使用了一个长度为16384位的数组来表示,节点拥有哪个槽位,旧件对应位置的数据信息设置为1,否则为0

    3. 计算公式:

      1. 16384/8/1024=2KB
  2. 集群规模的考虑:

    1. 一般集群的节点个数不会超过1000个,16384够用并且保证了每个分片上的槽的数量又不会太少。
0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
凯歌
下载 APP