Redis Cluster
本文所使用 Redis
版本为 Redis 5
。
业界方案
-
- 本质是个
proxy
,通过内存保存着槽位和实例节点之间的映射关系 - 槽位间的信息同步交给
ZooKeeper
管理 - 支持一些
MGET
等命令,实际是自身实现了Merge
功能 Pipeline
操作- 不支持事务、
MSETNX
等命令
- 本质是个
Redis Cluster
Redis Cluster
是 Redis
官方的集群方案,具体文档可阅读:
大致总结下一些要点如下:
-
基本特性:全网状结构(
full mest
),没有中央节点
、调度器
、Proxy
、Merge
的概念,也即是所谓的P2P
架构。每个节点之间都可以通信,如Heartbeat
、Failover
等。采用了一种类似Raft
算法中term(任期)
的概念epoch
(纪元),进行选举等。 -
Redis Cluster Bus
:每个node
需要开启两个监听端口,举例如使用6379
用于监听redis-client
请求,另一个端口16379
(默认 6379 offset 10000) 用于node
之间的通信,如选举、侦测、节点变更等等。 -
gossip protocol
:gossip 协议
是一个去中心化
、容错
、保证最终一致
性的协议。 -
node
:每个node
本质是全双工的通信(基于TCP
)。采用了分布式架构里常见的选举算法
,也即需要大于 1/2 个节点同意
,所以最少也会存在3个
主节点,而通常主节点都会挂载1~n
个slave
,所以一般情况下,redis-cluster
至少有6
个nodes
。官方文档也是以6
个作为示例。 -
shard
:每个shard
也即master-slave
架构,采用异步 replication
方式进行数据同步。但不同于传统的主从架构,master
和slave
本质也是个节点
,可通过协议实现角色互换等。 -
slot 机制
: 使用pow(2, 14) = 1684
个slot
,分配至各个master
,针对每个key
进行一致性 hash
,将其存储至某个master
。其中一致性 hash 算法
为:
|
|
-
MOVED 指令
:在集群下任何node
针对key
的操作,都会根据上述算法move
到slot
对应的节点。redis-client
必须处理该指令,就像操作单机 redis
一样。这里可以理解为301 Moved Permanently
-
ASK 指令
:当node
之间发生MIGRATING
或IMPORTING
的时候,也即表示正在进行slot
的迁移,所以需要ASKING
。也即是个中间态
,因为最终肯定是要迁移完成的(变成MOVED
)。这里可以理解为307 Temporary Redirect
-
readonly
:如果需要在slave
上读数据,那么需要显示的执行readonly
-
集群操作:
redis-cli
提供了很多关于cluster
的操作,可完全代替之前的redis-trib.rb
脚本。redis-cli --cluster help
-
client slot map table
:客户端可以自己实现cache the map between keys and nodes
-
hash tags
: 因为key
是分布在不同slot
,所以在执行如multi
等操作的时候,redis-cluster
是不支持CROSSSLOT Keys
操作的。所以它提供一种hash tags
的方案用于将某些key
放到同一slot
的方案。
注意:这里使用了
{}
用于标记真正被hash
的key
,第一个{
与紧接着其的}
将被认为是key
。
|
|
-
failover
:redis cluster
提供的容错机制,采取了ping-pong
机制进行侦测(是否超时)。:- 故障 failover:自动恢复集群的可用性
- 人为 failover:支持集群的可运维操作
-
write safety
:分区可用性分析(也即网络分区了,互相不可达),需要根据当前client
处于何种分区环境
进行分析。-
the minority side
:位于小分区一端,一直在master
写数据,在此期间,因为Failover
机制,其他分区的某个slave
提升为了master
。那么当分区可用后,原master
的数据丢失(因为该master
的role
成了slave
)。 -
the majority side
:位于大分区一端,因为主从是异步同步的,写操作在master
成功后但slave
未同步完成,master
挂了(master
不可达的时间超过阈值node timeout
的配置),集群通过选举,某slave
为新的master
,那么之前写的数据丢失。 -
这里需要注意的是,因为
master
之间存在心跳检测,所以当某master
发现其与其他master
的通信断了超过NODE_TIMEOUT
后,则会拒绝write
,为readonly
。这时slave
已经知道自己的master
挂了,开始failover
,其他master
在开始参与选举操作。所以如果网络分区时间大于node timeout
,则数据会丢失。
-