Redis集群的数据一致性

Redis 并不能保证数据的强一致性

一般所说的redis集群概念有3种:

  1. 主从(主从全量)
  2. 哨兵模式(主从全量,其中一个node监控集群状态)
  3. redis-cluster (数据分片存储,分布到各个分区,每个分区可以有多个node再主从全量)

Redis-cluster集群概念

(1)由多个Redis服务器组成的分布式网络服务集群;

(2)集群之中有多个Master主节点,每一个主节点都可读可写;

(3)节点之间会互相通信,两两相连;

(4)Redis集群无中心节点。

在很多集群架构中为了保证集群数据的一致性,都会使用一致性哈希算法,因为一致性哈希算法可以保证无论是增加节点还是减少节点,被影响的数据都是一小部分数据。

Redis 集群没有使用一致性哈希,取而代之的是引入了哈希槽的概念。

Redis 集群没有使用一致性哈希,取而代之的是引入了哈希槽的概念

Redis 集群有16384个哈希槽,每个要保存到Redis的键值对,都会先通过CRC16函数计算,然后再对16384取模,来决定这个键值对要被放置哪个槽。

客户端可以请求任意一个节点,每个节点中都会保存所有16384个slot对应到哪一个节点的信息。如果一个key所属的slot正好由被请求的节点提供服务,则直接处理并返回结果,否则返回MOVED重定向信息,如下:

GET key
一MOVED slot IP:PORT

客户端处理该重定向信息,并且向拥有该key的节点发起请求。实际应用中Redis客户端可以通过向集群请求slot和节点的映射关系并缓存,然后通过本地计算要操作的key所属的slot,查询映射关系并直接向正确的节点发起请求,这样可以获得几乎等价於单节点部署的性能。

哈希槽

集群的每个节点都会负责一部分哈希槽

举个例子,如果当前集群有3个节点M1、M2、M3,那么:

  • 节点 M1可能 包含 0 到 5500号哈希槽
  • 节点 M2可能 包含5501 到 11000 号哈希槽
  • 节点 M3可能包含11001 到 16384号哈希槽

由于Redis集群始终包含16384个哈希操作,因此它很容易添加或者删除节点。如果我想新添加个节点M4,那我只需要从节点 M1,M2,M3中得到部分槽,然后迁移到M4上即可。

或者,如果我想移除节点M4,那我们只需要将M4中的槽移到M1、M2和M3节点上,最后将没有任何槽的M4节点从集群中移除即可

由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加、删除或者改变某个节点的哈希槽数量都不会造成集群不可用的状态。

存入到Redis集群中的每个Key是通过CRC16函数计算后取模再映射到不同的哈希槽中的,但CRC16函数的结果是一个16bit的数,也就是说它的最大值是2**16=65536

在Redis集群中每个节点每秒都会向集群中其他节点发送 ping 消息,以检测其它节点的状态。

在消息头中最占空间的是保存哈希槽位置的bitmap大小。Bitmap的每一个位代表一个槽,如果该位为1,则表示这个槽是属于这个节点的。所以如果哈希槽总数设置为65536,那这个bitmap的大小最大将达到65536/(8*1024)= 8k。

另外,消息体中还会携带有约为集群总节点数量的1/10(至少携带3个)的节点的信息。这样节点数量越多,消息体内容越大。

所以,为降低由于消息过大而造成的通信阻塞影响,Redis的作者将Redis的节点数限制在1000,将哈希槽数限制在16384。

Redis集群的主从架构

为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品。

./redis-trib.rb create --replicas 1 192.168.159.10:7001 192.168.159.10:7002 192.168.159.10:7003 192.168.159.10:7004 192.168.159.10:7005 192.168.159.10:7006

例如有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少B节点所承担的哈希槽这个范围的槽而不可用。默认情况的整个集群也是不能使用的,不过我们可以改

cluster-require-full-coverage

当cluster-require-full-coverage为no时,表示当负责一个插槽的主库下线且没有相应的从库进行故障恢复时集群仍然可用。

集群节点复制

在Redis-Cluster集群中,可以给每一个主节点添加从节点,主节点和从节点直接遵循主从模型的特性。

当用户需要处理更多读请求的时候,添加从节点可以扩展系统的读性能。

故障转移

Redis集群的主节点内置了类似Redis Sentinel的节点故障检测和自动故障转移功能,当集群中的某个主节点下线时,集群中的其他在线主节点会注意到这一点并对已下线的主节点进行故障转移。

集群分片策略

Redis-cluster分片策略是用来解决key存储位置的。

集群将整个数据库分为16384个槽位slot,所有key-value数据都存储在这些slot中的某一个。一个slot槽位可以存放多个数据,key的槽位计算公式为:slot_number=crc16(key)%16384,其中crc16为16位的循环冗余校验和函数。

集群中的每个主节点都可以处理0个至16383个槽,当16384个槽都有某个节点在负责处理时,集群进入上线状态并开始处理客户端发送的数据命令请求。

集群分片策略

集群redirect转向

由于Redis集群无中心节点,请求会随机发给任意主节点;

主节点只会处理自己负责槽位的命令请求,其它槽位的命令请求该主节点会返回客户端一个转向错误;

客户端根据错误中包含的地址和端口重新向正确的负责的主节点发起命令请求。

Redis6.0推出集群代理:redis-cluster-proxy

https://github.com/RedisLabs/redis-cluster-proxy

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章