1、单机模式
问题:
内存上限和并发问题,单体服务器⽆法承载。
数据量达到⼀定程度写数据量也会很⼤,容易造成缓冲区溢出,造成从节点⽆限的进⾏全量复制导
致主从⽆法正常⼯作。
多核服务器⽐较普遍,对于主进程是单线程⼯作的Redis,只运⾏⼀个实例就显得有些浪费。同
时,管理⼀个巨⼤内存不如管理相对较⼩的内存⾼效。因此,实际使⽤中,通常⼀台机器上同时跑
多个Redis实例。
2. 集群模式 Redis Cluster2. 集群模式 Redis Cluster
Redis集群是Redis提供的分布式数据库⽅案,集群通过分⽚来进⾏数据共享,并提供复制和故障转移功能。
集群的作⽤有如下⼏个:
提⾼系统的存储:分散单机的存储能⼒,同时也可以很⽅便地实现扩展。
提⾼系统的性能:分流单机的访问请求。
提⾼系统的可⽤性:当 master1 宕机后对系统的影响不会那么⼤,仍然可以提供正常的服务。
问题:
数据怎么拆分到多个master节点?
3. 集群数据分⽚
3.1 单机存储结构
单机的存储是当⽤户发起请求后直接把 key 存储到⾃⼰的内存即可。
3.2 集群存储结构
分布式数据库要解决的就是将整块数据,按照规则分配到多个分布式节点,解决的是单个节点处理数量
⼤的问题。
3.2.1 数据分⽚⽅案
数据分⽚⽐较经典的算法有哈希算法和⼀致性哈希算法。
哈希算法:
调整机器数量时,会基于最新的 master 节点数量去取模,尝试去取数据。这会导致⼤部分的请求过来,全部⽆法拿到有效的缓存,导致⼤量的流量涌⼊数据库。
⼀致性哈希算法:
将整个 hash 值空间组织成⼀个虚拟的圆环,整个空间按顺时针⽅向组织。
将各个 master 节点(使⽤服务器的 ip 或主机名)进⾏ hash,这样就能确定每个节点在其哈希环上的位置。来了⼀个 key,⾸先计算 hash 值,并确定此数据在环上的位置,从此位置沿环顺时针“⾏⾛”,遇到的第⼀个 master 节点就是 key 所在位置。
如果⼀个节点挂了,受影响的数据仅仅是此节点到环空间前⼀个节点(沿着逆时针⽅向⾏⾛遇到的第⼀个节点)之间的数据,其它不受影响。增加⼀个节点也同理。
Redis Cluster在设计中没有使⽤⼀致性哈希,⽽是引⼊哈希槽(hash slot)来实现数据分⽚;
3.2.2 哈希槽
Redis Cluster 采⽤的是虚拟槽(slot)分⽚算法。这个槽是⽤来存放缓存信息的单位,在 Redis 中将存
储空间分成了 16384 个槽,也就是说 Redis Cluster 槽的范围是 0 -16383。
在存储信息的时候,集群会对 Key 进⾏ CRC16 校验并对 16383 取模 slot = CRC16(key)%16383 。
当⽤户发起⼀个 key 指令后需要做的事情如下:
通过 CRC16(key) 计算出来⼀个值。
⽤这个值取模 16383,会得到⼀个值,我们就先认为是 28。
这个值 28 就是 key 保存的空间位置。
Redis 在集群启动后就已经把存储空间划分了 16384 个槽位,每台主机保存⼀部分。
3.3 集群模式的请求路由
集群模式不同于哨兵,哨兵模式下客户端直接连接哨兵集群,由哨兵集群负责路由;集群模式下客户端直接连接master主机,路由功能需要在集群内部实现。
⽤户发起请求 key, master节点接收后计算 key 的槽位置,再根据槽位置找出对应的节点。如果访问的槽就在节点本身,那么就会直接返回 key 对应数据。否则会回复 moved 重定向错误,并且给客户端返回正确的节点。
Moved重定向过程:
4. 节点之间的通信节点之间通讯的⽬的是为了维护节点之间的元数据信息。元数据就是每个节点维护的⼀份在⾃⼰看来当
前整个集群的状态,主要包括:
当前集群状态
集群中各节点负责的slot
集群中各节点的master-slave状态
集群中各节点的存活状态及不可达投票
集群元数据的维护有两种⽅式:集中式、 Gossip 协议
集中式:
优点:元数据的读取和更新,时效性⾮常好,⼀旦元数据出现了变更,就⽴即更新到集中式的存储中,其它节点读取的时候就可以感知到。
缺点:所有的元数据的更新压⼒全部集中在⼀个地⽅,可能会导致元数据的存储有压⼒。
6. 故障迁移
解决机器的⾼可⽤问题:即使其中⼀个Master节点下线,整个集群依然能够正常向外提供服务。
简单来说就是让下线Master节点的Slave节点来成为新的Master节点,接管旧Master负责的所有slots向
外提供服务。
1. 故障发现到确认(多数投票的⽅案)
如果在 cluster-node-timeout 的时间内 ping 消息未收到pong回复,则会把接收⽅的节点标记为pfail(probable fail) 状态,也就是主观下线。集群不会因为⼀个节点的判断就将其下线,节点之间通过 Gossip 消息传播,集群中节点会不断收集故障节点的下线反馈并且存储到本地的故障节点下线报告中。当有半数以上的集群主节点都标记为主观下线后改变状态为客观下线。最后向集群⼴播⼀条 fail 消息,通知所有节点将故障节点标记为客观下线。
2. 故障转移
当⼀个从节点发现⾃⼰正在复制的主节点进⼊已下线状态时,从节点将开始对下线主节点进⾏故障转移。从节点选举被选中的从节点执⾏SLAVEOF no one命令,成为新的主节点新的主节点撤销所有对已下线主节点的槽位指派,并将这些槽位指派给⾃⼰向集群⼴播⼀条PONG消息,让其他节点知道该节点已成为主节点,并接管槽位新的节点开始接收负责槽相关命令请求,完成故障转移