redis集群
为什么要集群
- 性能:Redis 本身的 QPS 已经很高了,但是如果在一些并发量非常高的情况下,性能还是会受到影响。
- 扩展:出于存储的考虑。因为 Redis 所有的数据都放在内存中,如果数据量大, 很容易受到硬件的限制。升级硬件收效和成本比太低,所以我们需要有一种横向扩展的 方法。
- 可用性:如果只有一个 Redis 服务,一旦服务宕机,那么所有的客户端都无法访问,会对业务造成很大的影响。
如果硬件发生故障,而单机的数据无法恢复的话,带来的影响也是灾难性的。
主从复制(master/salve模式)
redis数据库复制多个副本部署在不同服务器上,并保证m节点数据库发生变化时,自动将数据同步给s节点数据库。
一般情况下,m节点数据库可读写,可以有多个s节点数据库。
s节点数据库只读,读写分离,并接受m节点数据库同步过来的数据。
复制策略
乐观复制,允许一定时间内m/s节点不同步,最终一致同步。
slaveof [主节点IP] [主节点端口] //主从依赖,只需在s节点的conf文件中添加配置即可。
bind [IP] // 注掉这个配置,默认是127.0.0.1,会导致s节点访问不了m节点。//bind是绑定本机网卡对应的IP地址。
min-slaves-to-write 3 //当3个及以上slave节点处于连接状态时,master节点才能写,不然只读,在master节点上配置。
min-slaves-max-lag 10 // m/s的心跳连接时间,如果超过10S,则默认s节点断开了。
全量复制
从节点请求主节点,主节点通过bgsave生成.rdb快照,发送给从节点,从节点加载.rdb数据。
快照生成之后的数据,主节点先把它保存在缓存里,最后发给从节点,这属于增量复制。
增量复制
m/s节点会创建一个 backlog,用于保存offset和master id。s节点会让m节点从上次断开的地方开始复制。
无磁盘复制
.rdb文件不落磁盘,m节点直接在内存中创建.rdb文件发送给s节点。
repl-dickless-sync yes //开启无磁盘复制,默认no
无磁盘复制的必要性
- 即便m节点禁用RDB,但全量复制依旧会生成快照,因为时间的不确定,导致下次m节点启动时,加载了该快照,导致数据问题。
- 如果磁盘性能低,全量复制的过程会对性能产生影响。
可用性保证之 Sentinel(哨兵)
从 Redis2.8 版本起,提供了一个稳定版本的 Sentinel,用来解决redis高可用的问题。
它是一个特殊状态的 redis 实例,Sentinel 通过 info 命令获取被监听 Redis 机器的 master,slave 等信息。
哨兵集群
为了保证监控服务器的可用性,我们会对 Sentinel 做集群的部署。Sentinel 既监控 所有的 Redis 服务,Sentinel 之间也相互监控。
注意:Sentinel 本身没有主从之分,只有 Redis 服务节点有主从之分。
服务下线
Sentinel 默认以每秒1次的频率,向 Redis 服务节点发送 PING 命令。如果在 down-after-milliseconds 内都没有收到有效回复,Sentinel 会将该服务器标记为下线 (主观下线)。
之后 Sentinel 节点会继续询问其他的 Sentinel 节点,确认这个节点是否下线, 如果多数 Sentinel 节点都认为 master节点下线,master节点才真正被确认下线(客观下线), 这个时候就需要重新选举 master。
# sentinel.conf
sentinel down-after-milliseconds <master-name> <milliseconds>
故障转移
master节点被标记为下线后, Sentinel 集群选举一个Leader ,由Leader 开始故障转移流程。
Sentinel集群如何选举Leader Sentinel?
Sentinle 通过 Raft 算法,实现 Sentinel 选举。
Raft 算法
Raft 是一个共识算法(consensus algorithm),其目的就是通过复制的方式,解决所有节点数据一致性的问题。大致分为两步:领导选举,数据复制。
- redis master节点 客观下线触发选举。
- Leader Sentinel并不会把自己成为 Leader 的消息发给其他 Sentinel。其他 Sentinel 等待 Leader 从 redis slave节点 选出 master ,并检测到新的 master 正常工作后,就会去掉客观下线的标识,从而不需要进入故障转移流程
redis master 节点选举
四个因素影响选举的结果,分别是断开连接时长、优先级 排序、复制数量、进程 id。
如果某redis节点与哨兵连接断开的比较久,超过了某个阈值,就直接失去了选举权。
如果拥有选举权,那就看谁的优先级高,这个在配置文件里可以设置(replica-priority 100), 数值越小优先级越高。
如果优先级相同,就看谁从 master 中复制的数据最多(复制偏移量最大),选最多 的那个。
如果复制数量也相同,就选择进程 id 最小的那个。
如何让slave成为master?
- 选出 Sentinel Leader 之后,由 Sentinel Leader 向某个节点发送 slaveof no one 命令,让它成为独立节点。
- 然后向其他节点发送 slaveof x.x.x.x xxxx(本机服务),让它们成为这个节点的 子节点,故障转移完成。
Sentinel 的功能总结
- 监控:Sentinel 会不断检查主服务器和从服务器是否正常运行。
- 通知:如果某一个被监控的实例出现问题,Sentinel 可以通过 API 发出通知。
- 自动故障转移(failover):如果主服务器发生故障,Sentinel 可以启动故障转移过 程。把某台服务器升级为主服务器,并发出通知。
- 配置管理:客户端连接到 Sentinel,获取当前的 Redis 主服务器的地址。
哨兵机制的不足
- 主从切换的过程中会丢失数据,因为只有一个 master。
- 只能单点写,没有解决水平扩容的问题。
- 如果数据量非常大,这个时候我们需要多个 master-slave 的 group,把数据分布到 不同的 group 中。