4 (1)

Redis 高可用性

Redis 官方文档

GitHub: Redis

Redis Doc: Replication 主从复制

Redis Doc: Sentinel 哨兵

redis/replication.c at 4.0 · antirez/redis · GitHub

Redisson: Redis based In-Memory Data Grid for Java · redisson/redisson · GitHub

Replication 主从复制

Redis 支持简单且易用的主从复制(master-slave replication)功能, 该功能可以让从服务器(slave)成为主服务器(master)的精确复制品。

 

形式

  • 当 master 和 slave 处于正常连接状态,slave 通过 master 发送的命令流去更新当前的数据,以至于可以复制master中的数据变化,比如客户端的写操作,key的过期删除。
  • 当 master 和 slave 因为网络问题或者超时而断开连接,slave 重连后会试图进行局部同步(partial resynchronization):它会尝试去获得因为断开连接而未接收的那一部分命令流。
  • 当局部同步不可行时,slave 会请求一次完全同步(full resynchronization)。此时 master 需要创建一个当前数据的快照,然后发送给 slave,并且继续发送数据变化的命令流。

 

特性

  • redis 使用异步复制,同时 slave 也会定期地异步地告知 master 当前已处理的数据量
  • 一个 master 可以有多个 slave
  • slave 也可以接受其他 slave 的连接。
  • 主从复制不会阻塞 master: 即使有一个或多个 slave 正在进行完全同步或者局部同步,master 也可以继续处理请求。
  • 主从复制对于 slave 来说,也只有极少情况是阻塞的。当 slave 在请求完全同步时,可以通过设置来让请求使用旧数据。另外,也可以设置当同步流断开时给客户端返回error。但是在完全同步的最后,从服务器删除旧数据到新数据完全加载这段时间内,请求会被阻塞。从redis 4.0开始,可以设置删除数据使用不同的线程,但是加载数据依然会在主线程并且会阻塞 slave。
  • 主从复制可以用于读写分离,让多个 slave 处理只读请求来提示可扩展性(比如一些 O(N) 的操作可以在 slave 上进行),或者单纯用于数据备份。
  • 主从复制也可以用来让 master 免于执行持久化操作,让 slave 去执行持久化,以此来提升 master 的性能。但一定要注意此时 master 不能配置自动拉起,否则会丢失所有数据。

 

原理

redis master 会有一个 replication ID,它是一个很大的伪随机字符串来标记当前的数据集。同时 master 会记录一个偏移量 offset 来表示用来发送给 slave 的复制流的字节数,用来表示当前 master 和 slave 的数据更新状态。就算当前没有 slave 连接,offset 也会增加。

所以可以用以下形式来表示当前 master 数据的精确版本号
replication ID, offset

当 slave 连接 master, 它使用PSYNC命令来发送他们已经处理过的老版本号。然后 master 可以根据版本来发送增量的部分。但是当 master 的缓冲池容量不够时,或者 slave 发送了一个已经没有记录的replication ID时,就需要进行完全同步。

当进行完全同步时,master 会起一个后台进程来生成一个 RDB 文件,同时也会缓存客户端所有新的写命令。当保存完毕,master 会将这个数据库文件发送给 slave,slave 会将它保存在硬盘,然后将它加载到内存中。接着 master 会将所有缓存的命令发送给 slave。

Replication
如果 master 同时收到多个并发的 slave 的完全同步请求,也只会执行一个后台保存进程,然后发送给他们。

可以通过配置来实现不用硬盘来做中间存储器的完全同步,以此来减少硬盘性能对同步的影响。

 

 

Sentinel 哨兵

哨兵为 redis 提供了高可用性。

 

功能

  • 监控(Monitoring):哨兵会不断地检查 master 和 slave 是否有按预期工作
  • 通知(Notification):哨兵可以通过API通知系统管理员,或者其他程序,它所监控的redis实例出现的问题
  • 自动故障迁移(Automatic failover):如果 master 不能按预期工作,哨兵会启动一个故障迁移进程,让其中一个 slave 晋升成为 master,而其他的 slave 则使用新的 master,而应用程序也会在连接的时候使用新的地址
  • 配置的提供者(Configuration provider):哨兵会充当客户端的服务发现来源,客户端连接到哨兵来询问某个服务的当前 Redis 主服务器的地址。当故障转移发生时,哨兵会报告新地址。

Replication
 

特性

哨兵是一个分布式系统,它被设计成需要多个哨兵实例协同工作。这样的分布式系统有以下好处:

  • 由多个哨兵认定 master 不可访问,可以降低误报的可能性
  • 当部分哨兵不可用时仍可以工作,保证了系统的高可用性。一个故障转移系统不应该只有单点。

 

Failover 过程

  1. 当某个哨兵实例监控到 master 在设定时间内持续不可访问,就会将 master 标记为主观下线(SDOWN),并报告给其他哨兵
  2. 当某个哨兵实例收集到设定数量的主观下线的报告,就会将 master 标记为客观下线(ODOWN),此时会请求进行故障迁移
  3. 只有当超过半数(>50%)的实例授权同意,然后对这次故障迁移产生的新配置进行版本号标识,才会进行故障迁移
  4. 哨兵发送SLAVEOF NO ONE命令给一个 slave(由优先级规则选出),将其晋升为 master ,然后将更新后的配置广播给其他的哨兵
  5. 如果旧的 master 重新上线,哨兵会发送一个SLAVEOF命令让他去同步新的 master

 

实验

Sentinel Down Failover
3 0 true
1 true
2 false
2 0 true
1 false

 

如何在 Jedis 中使用

如果使用了 spring session 且有多个 JedisConnectionFactory ,则需要给 spring session 使用的加上 primary="true"

 

注意事项

  • 如果要保证redis服务的高可用性,哨兵实例至少应该有3个
  • 配置密码要所有redis实例都配置requirepass 和 masterauth ,否则failover后会出现认证问题,客户端连接不上。
  • 当master、slave、sentinel都部署在一台机器上(比如测试环境),则所有ip使用完整ip,不要使用127.0.0.1或其他,且redis实例也要bind完整ip,不然会识别出错,而且无法正常failover

Categories: 随笔