redis高可用概述
[TOC]
高可用方案概述
原生的高可用方案
- Redis共有3种原生的高可用性解决方案,概述如下:
方案 | 版本支持 | 优点 | 缺点 | 使用场景 |
---|---|---|---|---|
主从模式 | redis2.8以前 | 一主多从 读写分离、从库备份 |
不支持故障转移 master故障需要修改客户端的配置 |
解决备份、读写分离 |
sentinel哨兵模式 | redis2.8及以后 | 支持故障转移 | slave故障则影响该节点的客户端 不支持动态扩容 |
着眼于高可用,自动故障转移 |
cluster集群模式 | redis3.0以后 | 自动故障转移 支持分片、动态扩容 |
最佳实践较少 只支持1个db |
解决单机容量、提高并发量 |
业界主流的集群化方案
比较项 | 客户端分片 | Codis | Tweproxy | Redis Cluster |
---|---|---|---|---|
集群模式 | 无中心化 | 中心化 | 中心化 | 无中心化 |
使用方式 | 编写路由规则直连redis | 通过proxy访问 | 通过proxy访问 | 使用Smart Client直连redis Smart Client内置路由规则 |
性能 | 高 | 有性能损耗 | 有性能损耗 | 高 |
支持的数据库数量 | 多个 | 多个 | 多个 | 一个 |
Pipeline | 支持 | 支持 | 支持 | 仅支持单个节点Pipeline 不支持跨节点 |
是否需要升级客户端SDK | 不需要 | 不需要 | 不需要 | 需要 |
是否支持在线水平扩容 | 不支持 | 支持 | 不支持 | 支持 |
Redis版本 | 支持最新版 | 仅支持3.2.8 升级困难 |
支持最新版 | 支持最新版 |
可维护性 | 运维简单 开发使用成本高 |
组件较多 部署复杂 |
只有proxy组件 部署简单 |
运维+开发使用简单 官方持续维护 |
故障自动恢复 | 需部署哨兵 | 需部署哨兵 | 需部署哨兵 | 内置哨兵逻辑 无需额外部署 |
主从模式
原理
同Mysql主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。下图为级联结构。
全量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:
- slave连接master,发送SYNC命令
- master收到SYNC命令后,开始执行BGSAVE命令生成RDB文件,并使用缓冲区记录此后执行的所有写命令
- master执行完BGSAVE后,向所有slave发送快照文件,并在发送期间继续记录被执行的写命令
- slave收到快照文件后丢弃所有旧数据,载入收到的快照
- master快照发送完毕后,开始向salve发送缓冲区的写命令
- slave完成对快照的载入,开始接收命令请求,并执行来自master缓冲区的写命令
优缺点
优点
- 解决数据备份问题
- 做到读写分离,提高服务器性能
缺点
- 每个客户端连接redis实例的时候都是指定了ip和端口号的,如果所连接的redis实例因为故障下线了,而主从模式也没有提供一定的手段通知客户端另外可连接的客户端地址,因而需要手动更改客户端配置重新连接
- 主从模式下,如果主节点由于故障下线了,那么从节点因为没有主节点而同步中断,因而需要人工进行故障转移工作
- 无法实现动态扩容
sentinel哨兵模式
Sentinel(哨兵)是Redis的高可用性解决方案:由一个或多个哨兵(Sentinel)实例组成的Sentinel系统,可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器。在主节点出现故障的情况下,能将从节点中的一个升级为主节点,进行故障转移,保证系统的可用性。
原理
哨兵们是怎么感知整个系统中的所有节点(主节点/从节点/哨兵节点)的
- 首先主节点的信息是配置在哨兵(Sentinel)的配置文件中
- 哨兵节点会和配置的主节点建立起两条连接 命令连接 和 订阅连接
- 哨兵会通过 命令连接 每 10s 发送一次 INFO 命令,通过INFO命令,主节点会返回自己的 run_id 和自己的 从节点信息
- 哨兵会对这些从节点也建立两条 命令连接 和 订阅连接
- 哨兵通过 命令连接 向从节点发送 INFO 命令,获取到他的一些信息
a. run_id
b. role
c. 从服务器的复制偏移量 offset
- 因为哨兵对与集群中的其他节点(主从节点)当前都有两条连接,命令连接 和 订阅连接
a. 通过命令连接向服务器的_sentinel:hello频道发送一条消息,内容包括自己的ip端口、run_id、配置纪元(后续投票的时候会用到)等 b. 通过订阅连接对服务器的_sentinel:hello频道做了监听,所以所有的向该频道发送的哨兵的消息都能被接受到 c. 解析监听到的消息,进行分析提取,就可以知道还有那些别的哨兵服务节点也在监听这些主从节点了,更新结构体将这些哨兵节点记录下来 d. 向观察到的其他的哨兵节点建立命令连接----没有订阅连接
哨兵模式下的故障迁移
主观下线
哨兵(Sentinel)节点会每秒一次的频率向建立了命令连接的实例发送PING命令,如果在 down-after-milliseconds 毫秒内没有做出有效响应包括(PONG/LOADING/MASTERDOWN)以外的响应,哨兵就会将该实例在本结构体中的状态标记为 SRI_S_DOWN 主观下线。
客观下线
当一个哨兵节点发现主节点处于主观下线状态时,会向其他的哨兵节点发出询问,该节点是不是已经主观下线了。如果超过配置参数 quorum 个节点认为是主观下线时,该哨兵节点就会将自己维护的结构体中该主节点标记为 SRI_O_DOWN 客观下线
询问命令 SENTINEL is-master-down-by-addr
参数 | 意义 |
---|---|
ip/port | 当前认为下线的主节点的ip和端口 |
current_epoch | 配置纪元 |
run_id | 标识仅用于询问是否下线 有值标识该哨兵节点希望对方将自己设置为leader 询问时用 ,选举时用run_id |
leader选举
在认为主节点 客观下线 的情况下,哨兵节点之间会发起一次选举,命令还是上面的命令 SENTINEL is-master-down-by-addr
故障迁移
- 在从节点中挑选出新的主节点
a. 通讯正常
b. 优先级排序
c. 优先级相同是选择offset最大的
- 将该节点设置成新的主节点 SLAVEOF NO ONE,并确保在后续的INGO命令时,该节点返回状态为master
- 将其他的从节点设置成从新的主节点复制,SLAVEOF命令
- 将旧的主节点变成新的主节点的从节点
优缺点
优点
- 在主节点故障时能实现故障的转移
- Master-Slave切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
缺点
- 如果是从节点下线了,sentinel不会对其进行故障转移,连接从节点的客户端也无法获取到新的可用从节点
- 无法实现动态扩容
cluster集群模式
在这个图中,每一个蓝色的圈都代表着一个redis的服务器节点。它们任何两个节点之间都是相互连通的。客户端可以与任何一个节点相连接,然后就可以访问集群中的任何一个节点。对其进行存取和其他操作。
一般集群建议搭建三主三从架构,三主提供服务,三从提供备份功能。每一个节点都存有这个集群所有主节点以及从节点的信息。
它们之间通过互相的ping-pong判断是否节点可以连接上。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了,然后去连接它的备用节点。如果某个节点和所有从节点全部挂掉,我们集群就进入faill状态。还有就是如果有一半以上的主节点宕机,那么我们集群同样进入发力了状态。这就是我们的redis的投票机制,具体原理如下图所示:
(1)投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超时(cluster-node-timeout),认为当前master节点挂掉.
(2):什么时候整个集群不可用(cluster_state:fail)?
a:如果集群任意master挂掉,且当前master没有slave.集群进入fail状态,也可以理解成集群的slot映射[0-16383]不完整时进入fail状态. ps : redis-3.0.0.rc1加入cluster-require-full-coverage参数,默认关闭,打开集群兼容部分失败.
b:如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态.
原理
优缺点
优点
- 有效的解决了redis在分布式方面的需求
- 遇到单机内存,并发和流量瓶颈等问题时,可采用Cluster方案达到负载均衡的目的
- 可实现动态扩容
- P2P模式,无中心化
- 通过Gossip协议同步节点信息
- 自动故障转移、Slot迁移中数据可用
缺点
- 架构比较新,最佳实践较少
- 为了性能提升,客户端需要缓存路由表信息
- 节点发现、reshard操作不够自动化
总结
主从复制是为了数据备份,哨兵是为了高可用,Redis主服务器挂了哨兵可以切换,集群则是因为单实例能力有限,搞多个分散压力,简短总结如下:
- 主从模式:备份数据、读写分离、负载均衡,一个Master可以有多个Slaves。
- 哨兵sentinel:监控、自动转移、哨兵发现master挂了后,就会从slave中重新选举一个master。
- cluster是为了解决单机Redis容量有限的问题,将数据按一定的规则分配到多台机器,使内存/QPS不受限于单机。