除了 ZAB 协议,业界上常用的还有 Paxos,Raft 等协议算法,也可以用在 Leader 选举上,也就是是在分布式架构中,这些协议算法承担了“第三者”也就是仲裁者的作用,以承担故障的自动转移
RedisRedis 的高可用需要根据它的部署模式来看看,主要分为「主从模式」和「Cluster 分片模式」两种
主从模式先来看一下主从模式,架构如下
主从模式即一主多从(一个或者多个从节点),其中主节点主要负责读和写,然后会将数据同步到多个从节点上,Client 也可以对多个从节点发起读请求,这样可以减轻主节点的压力,但和 ZK 一样,由于只有一个主节点,存在单点隐患,所以必须引入第三方仲裁者的机制来判定主节点是否宕机以及在判定主节点宕机后快速选出某个从节点来充当主节点的角色,这个第三方仲裁者在 Redis 中我们一般称其为「哨兵」(sentinel),当然哨兵进程本身也有可能挂掉,所以为了安全起见,需要部署多个哨兵(即哨兵集群)
这些哨兵通过 gossip(流言) 协议来接收关于主服务器是否下线的信息,并在判定主节点宕机后使用 Raft 协议来选举出新的主节点
Cluster 分片集群主从模式看似完美,但存在以下几个问题
主节点写的压力难以降低:因为只有一个主节点能接收写请求,如果在高并发的情况下,写请求如果很高的话可能会把主节点的网卡打满,造成主节点对外无法服务
主节点的存储能力受到单机存储容量的限制:因为不管是主节点还是从节点,存储的都是全量缓存数据,那么随着业务量的增长,缓存数据很可能直线上升,直到达到存储瓶颈
同步风暴:因为数据都是从 master 同步到 slave 的,如果有多个从节点的话,master 节点的压力会很大
为了解决主从模式的以上问题,分片集群应运而生,所谓分片集群即将数据分片,每一个分片数据由相应的主节点负责读写,这样的话就有多个主节点来分担写的压力,并且每个节点只存储部分数据,也就解决了单机存储瓶颈的问题,但需要注意的是每个主节点都存在单点问题,所以需要针对每个主节点做高可用,整体架构如下
原理也很简单,在 Proxy 收到 client 执行的 redis 的读写命令后,首先会对 key 进行计算得出一个值,如果这个值落在相应 master 负责的数值范围(一般将每个数字称为槽,Redis 一共有 16384 个槽)之内,那就把这条 redis 命令发给对应的 master 去执行,可以看到每个 master 节点只负责处理一部分的 redis 数据,同时为了避免每个 master 的单点问题,也为其配备了多个从节点以组成集群,当主节点宕机时,集群会通过 Raft 算法来从从节点中选举出一个主节点
ES再来看一下 ES 是如何实现高可用的,在 ES 中,数据是以分片(Shard)的形式存在的,如下图所示,一个节点中索引数据共分为三个分片存储
但只有一个节点的话,显然存在和 Redis 的主从架构一样的单点问题,这个节点挂了,ES 也就挂了,所以显然需要创建多个节点
一旦创建了多个节点,分片的优势就体现出来了,可以将分片数据分布式存储到其它节点上,极大提升了数据的水平扩展能力,同时每个节点都能承担读写请求,采用负载均衡的形式避免了单点的读写压力
ES 的写机制与 Redis 和 MySQL 的主从架构有些差别(后两者的写都是直接向 master 节点发起写请求,而 ES 则不是),所以这里稍微解释一下 ES 的工作原理
首先说下节点的工作机制,节点(Node)分为主节点(Master Node)和从结点(Slave Node),主节点的主要职责是负责集群层面的相关操作,管理集群变更,如创建或删除索引,跟踪哪些节点是集群的一部分,并决定哪些分片分配给相关的节点,主节点也只有一个,一般通过类 Bully 算法来选举出来,如果主节点不可用了,则其他从节点也可以通过此算法来选举以实现集群的高可用,任何节点都可以接收读写请求以达到负载均衡的目的