Redis-高可用篇-④高可用方案
Redis-高可用篇-④高可用方案
学习核心
- Redis的三种集群模式
- 如何保证缓存的高可用性?
学习资料
- CAP理论 VS BASE 理论
- todo :三种集群模式的搭建 实践部分待定
- Redis 集群搭建
CAP VS BASE
1.CAP理论
CAP 理论作为分布式系统的基础理论,它描述的是一个分布式系统在以下三个特性中:
- 一致性(Consistency)
- 可用性(Availability)
- 分区容错性(Partition Tolerance)
最多满足其中的两个特性,即分布式系统要么满足 CA,要么 CP,要么 AP,而无法同时满足 CAP。而基于这三者又如何取舍?
- CA:优先保证一致性和可用性,放弃分区容错。这也意味着放弃系统的扩展性,系统不再是分布式的,有违设计的初衷
- CP:优先保证一致性和分区容错性,放弃可用性。在数据一致性要求比较高的场合,例如:Zookeeper、Hbase 等是比较常见的做法,一旦发生网络故障或者消息丢失,就会牺牲用户体验,等恢复之后用户才逐渐能访问
- AP:优先保证可用性和分区容错性,放弃一致性。在 Spring Cloud 体系中使用的 Eureka 注册中心就是这种架构,但放弃一致性只是指放弃强一致性,保证最终一致性
2.BASE 理论
BASE 全称是 Basically Available(基本可用)、Soft State(软状态)和 Eventually Consistent(最终一致性)三个短语的缩写,来自 ebay 的架构师提出
可以说BASE理论是CAP中一致性的妥协。和传统事务的ACID截然不同,BASE不追求强一致性,而是允许数据在一段时间内是不一致的,但最终达到一致状态,从而获得更高的可用性和性能。
Redis 集群的三种模式
Redis 支持三种集群方案:
- 主从复制模式
- 哨兵(Sentinel)模式
- 切片集群(Cluster)模式
1.主从复制模式
主从复制概念核心
通过持久化功能,Redis保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,因为持久化会把内存中数据保存到硬盘上,重启会从硬盘上加载数据。 但是由于数据是存储在一台服务器上的,如果这台服务器出现硬盘故障等问题,也会导致数据丢失。为了避免单点故障,通常的做法是将数据库复制多个副本以部署在不同的服务器上,这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。
基于主从复制架构概念,将数据库分为两类:一类是主数据库(master)、一类是从数据库(slave),一个主数据库可以有多个从数据库,但一个从数据库只能绑定一个主数据库。主数据库可进行读写操作,从数据库则一般设置为只读并接收主数据库同步过来的数据。
引入主从复制的目的:
- 避免单点故障,便于做容灾恢复
- 实现读写分离,分担master的读写压力
主从复制优缺点
优点
- 支持读写分离,有效分担master的读写压力
- 以非阻塞方式完成数据同步,在同步期间客户端可以正常提交请求并响应
缺点
- Redis不具备容错和恢复功能,主机从机的宕机都会导致部分读写请求失败,需要人工介入进行修复
- 如果主机突然宕机,部分数据如果还没同步到从机,切换IP后会存在数据不一致问题,降低了系统的可用性
- 如果多个slave同时断线,尽量避免同一时间段重启它们(Slave 启动会发送sync 请求和主机全量同步,当多个 Slave 同时重启可能会导致 Master IO 剧增从而宕机)
- Redis比较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂
2.哨兵(Sentinel)模式
基于主从复制模式(主从同步/复制),当主服务器宕机后,需要手动把一台从服务器切换为主服务器,不免需要人工干预(人工介入选主并更新上游客户端配置),费事费力,还会造成一段时间内服务不可用。因此引入哨兵模式,用于监测主节点是否存活,进而实现主从节点故障转移。
- 监听主从服务器的运行状态
- 自动实现failover(自动故障转移):当监测到master宕机,选出哨兵leader进行主从节点故障转移,将选定的salve切换成master节点,然后通过发布订阅模式通知其他节点进行信息同步
考虑到单个哨兵也可能会出现宕机问题(存在哨兵节点的单点故障问题),可以引入多个哨兵进行监控,哨兵之间相互监控,形成多哨兵模式(即Sentinel需支持集群部署)。
Redis Sentine 方案是一个包含了多个 Sentinel 节点,以及多个数据节点的分布式架构。除了监控 Redis 数据节点的运行状态,Sentinel 节点之间还会互相监控,当发现某个 Redis 数据节点不可达时,Sentinel 会对这个节点做下线处理,如果是 Master 节点,会通过投票选择是否下线 Master 节点,完成故障发现和故障转移。Sentinel 在操作故障节点的上下线时,还会通知上游的业务方,整个过程不需要人工干预,可以自动执行。
哨兵模式概念核心
Redis 在 2.8 版本以后提供的哨兵(Sentinel)机制,它的作用是实现主从节点故障转移。它会监测主节点是否存活,如果发现主节点挂了,它就会选举一个从节点切换为主节点,并且把新主节点的相关信息通知给从节点和客户端。
哨兵一般是以集群的方式部署(至少需要 3 个哨兵节点),哨兵集群工作核心:监控、选主、通知。通过 Redis 的发布者/订阅者机制,哨兵之间可以相互感知,构建哨兵集群。与此同时,哨兵通过 INFO 命令,在主节点里获得了所有从节点连接信息,就能和从节点建立连接,并进行监控
两轮投票+故障转移
第一轮投票:判断主节点下线(监控:主观下线、客观下线)
当哨兵集群中的某个哨兵判定主节点下线(主观下线)后,就会向其他哨兵发起命令,其他哨兵收到这个命令后,就会根据自身和主节点的网络状况,做出赞成投票或者拒绝投票的响应。
当这个哨兵的赞同票数达到哨兵配置文件中的 quorum 配置项设定的值后,这时主节点就会被该哨兵标记为「客观下线」。
第二轮投票:选出哨兵 leader(由该哨兵Leader进行主从故障转移)
某个哨兵判定主节点客观下线后,该哨兵就会发起投票,告诉其他哨兵,它想成为 leader,想成为 leader 的哨兵节点,要满足两个条件:
- 条件1:拿到半数以上的赞成票;
- 条件2:拿到的票数需大于等于哨兵配置文件中的 quorum 值;
故障转移:由哨兵 leader 进行主从故障转移(选主、通知)
选举出了哨兵 leader 后,就可以进行主从故障转移的过程了。该操作包含以下四个步骤:
- 【步骤1】:选主 => 在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为主节点,选择的规则:
- 过滤掉已经离线、历史网络连接状态不好的从节点;
- 进行三轮考察筛选:优先级、复制进度、ID 号。在每一轮考察过程中,如果找到了一个胜出的从节点,就将其作为新主节点
- 【步骤2】:更新主从关系:让已下线主节点属下的所有「从节点」修改复制目标,修改为复制「新主节点」;
- 【步骤3】:通知 => 将新主节点的 IP 地址和信息,通过「发布者/订阅者机制」通知给客户端;
- 【步骤4】:继续监视旧主节点,当这个旧主节点重新上线时,将它设置为新主节点的从节点;
哨兵模式优缺点
- 优点
- 哨兵模式是基于主从模式的,继承了主从模式的优点
- “自动版的主从复制”:主从可以自动切换(减少人工维护成本),系统更健壮、可用性更高
- 缺点
- Redis比较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂
3.切片集群(Cluster)模式
Redis Cluster
为了解决大数据量存储场景中的单机性能瓶颈问题,引入切片集群模式实现扩容的横向扩展机制。
Redis Cluster是一种服务器 Sharding 技术(一种实现横向扩展的方案,官方的集群方案,无中心架构),3.0版本开始正式提供。Redis 的哨兵模式基本已经可以实现高可用、读写分离 ,但是所有的数据都是存在一台服务器上,然后通过主从复制进行同步,如果采用的是基于RDB的持久化技术,主线程需要fork多个不同的进程来完成持久化操作,在大数据量场景下就有可能导致主进程阻塞。因此在 redis3.0上加入了 Cluster 集群模式,实现了 Redis 的分布式存储,进而优化大数据量存储场景性能问题。
对应切片集群模式首先要理解几个概念:
- 集群中的数据分片:哈希槽与数据库实例对应,必须确保所有哈希槽被正确管理才能让集群正常运作
- 切片集群的主从复制模型(主备模式):redis-cluster集群引入主从复制模型(一个主节点对应一个或多个从节点,当主节点宕机就会启用从节点),但主从节点并没有读写分离(slave只用作master宕机的高可用备份)
- 客户端如何访问数据?访问任一实例获取到哈希槽slots与实例节点的映射关系并缓存到本地,然后根据实际的映射信息将请求发送到对应的实例
无中心?
在 Redis Cluster 集群中,所有 Redis 节点都可以对外提供服务,包括路由分片、负载信息、节点状态维护等所有功能都在 Redis Cluster 中实现。Redis 各实例间通过 Gossip 通信,这样设计的好处是架构清晰、依赖组件少,方便横向扩展(有资料参考 Redis Cluster 集群可以扩展到 1000 个以上的节点)。
Redis Cluster 集群中,客户端直接连接服务器,避免了各种 Proxy 中的性能损耗,可以最大限度的保证读写性能。
切片集群模式特点
- 所有的 redis 节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽;
- 节点的 fail 是通过集群中超过半数的节点检测失效时才生效;
- 客户端与 Redis 节点直连,不需要中间代理层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可;
Codis
除了 Redis Cluster,另外一个应用比较多的是 Codis 方案,Codis 是国内开源的一个 Redis 集群方案。Codis 的实现和 Redis Cluster 不同,是一个“中心化的结构”,同时添加了 Codis Proxy 和 Codis Manager。Codis 设计中,是在 Proxy 中实现路由、数据分片等逻辑,Redis 集群作为底层的存储引擎,另外通过 ZooKeeper 维护节点状态,可以参考下面这张 Codis 的官方架构图: