redis 主从模型

虽然 Redis 可以实现单机的数据持久化, 但无论是 RDB 也好或者 AOF 也好, 都解决不了单点宕机问题,即一旦 redis 服务器本身出现系统故障、硬件故障等问题后, 就会直接造成数据的丢失, 因此需要使用另外的技术来解决单点问题。

主备模式, 可以实现 Redis 数据的跨主机备份。

程序端连接到高可用负载的 VIP, 然后连接到负载服务器设置的 Redis 后端 real server, 此模式不需要在程序里面配置 Redis 服务器的真实 IP 地址, 当后期 Redis 服务器 IP 地址发生变更只需要更改redis 相应的后端 real server 即可, 可避免更改程序中的 IP 地址设置。

redis 主备数据不一致 redis主备模式_redis

Slave 主要配置:
Redis Slave 也要开启持久化并设置和 master 同样的连接密码, 因为后期 slave 会有提升为 master 的可能,Slave 端切换 master 同步后会丢失之前的所有数据。一旦某个 Slave 成为一个 master 的 slave, Redis Slave 服务会清空当前 redis 服务器上的所有数据并将 master 的数据导入到自己的内存,但是断开同步关系后不会删除当前已经同步过的数据

下面配置node1的redis为主(master),node2的redis为从(slave)

实验:配置redis主从

  • yum安装redis
    yum -y install redis
  1. 主服务器配置
# vim /etc/redis.conf
...
61 bind 0.0.0.0
...
480 requirepass 123456
...

重启服务

systemctl restart redis
  1. 从服务器配置
vim /etc/redis.conf
...
61 bind 0.0.0.0
...
480 requirepass 123456
...
265 slaveof 192.168.99.122 6379
...
272 masterauth 123456

重启服务

systemctl restart redis

验证连接

# redis-cli
127.0.0.1:6379> info replication

redis 主备数据不一致 redis主备模式_redis 主备数据不一致_02


  • 编译安装redis
    过程见上面
  1. 从服务器配置
# vim /etc/redis/redis.conf
...
69 bind 0.0.0.0
...
171 logfile "/apps/redis/log/redis.log"
...
263 dir "/apps/redis/data"
...
281 slaveof 192.168.99.122 6379
...
287 masterauth 123

重启redis

systemctl restart redis
  1. 主服务器配置
# vim /etc/redis/redis.conf
...
171 logfile "/apps/redis/log/redis.log"
...
263 dir "/apps/redis/data"

重启redis

systemctl restart redis

验证连接

# redis-cli
127.0.0.1:6379> info replication

主从复制过程

Redis 支持主从复制分为全量同步和增量同步, 首次同步是全量同步,主从同步可以让从服务器从主服务器备份数据,而且从服务器还可与有从服务器,即另外一台 redis 服务器可以从一台从服务器进行数据同步, redis 的主从同步是非阻塞的,其收到从服务器的 sync(2.8 版本之前是 PSYNC)命令会 fork 一个子进程在后台执行 bgsave 命令,并将新写入的数据写入到一个缓冲区里面, bgsave执行完成之后并生成的将 RDB 文件发送给客户端,客户端将收到后的 RDB 文件载入自己的内存.

然后主 redis 将缓冲区的内容在全部发送给从 redis,之后的同步从服务器会发送一个 offset 的位置(等同于 MySQL 的 binlog 的位置)给主服务器,主服务器检查后位置没有错误将此位置之后的数据包括写在缓冲区的积压数据发送给 redis 从服务器,从服务器将主服务器发送的挤压数据写入内存,这样一次完整的数据同步,再之后再同步的时候从服务器只要发送当前的 offset 位 置给主服务器,

然后主服务器根据响应的位置将之后的数据发送给从服务器保存到其内存即可。Redis 全量复制一般发生在 Slave 初始化阶段,这时 Slave 需要将 Master 上的所有数据都复制一份。

具体步骤如下:
1)从服务器连接主服务器,发送 SYNC 命令;
2)主服务器接收到 SYNC 命名后,开始执行 BGSAVE 命令生成 RDB 快照文件并使用缓冲区记录此后执行的所有写命令;
3)主服务器 BGSAVE 执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令
7) 后期同步会先发送自己 slave_repl_offset 位置, 只同步新增加的数据, 不再全量同步。

redis 主备数据不一致 redis主备模式_redis_03

主从同步优化

Redis 在 2.8 版本之前没有提供增量部分复制的功能, 当网络闪断或者 slave Redis 重启之后会导致主从之间的全量同步,即从 2.8 版本开始增加了部分复制的功能。

1、 yes 为支持 disk, master 将 RDB 文件先保存到磁盘在发送给 slave,
no 为 maste直接将 RDB 文件发送给 slave,默认即为使用 no, Master RDB 文件不需要与磁盘交互。

repl-diskless-sync yes

2、 Master 准备好 RDB 文件后等等待传输时间

repl-diskless-sync-delay 5

3、 slave 端向 server 端发送 ping 的时间区间设置,默认为 10 秒

repl-ping-slave-period 10

4、 设置超时时间

repl-timeout 60

5、 是否启用 TCP_NODELAY,
如设置成 yes,则 redis 会合并小的 TCP 包从而节省带宽,但会增加同步延迟(40ms),造成 master 与 slave 数据不一致.
假如设置成 no,则 redis master 会立即发送同步数据,没有延迟,前者关注性能,后者关注一致性

repl-disable-tcp-nodelay no

6、 master 的写入数据缓冲区, 用于记录自上一次同步后到下一次同步过程中间的写入命令,
计算公式: b repl-backlog-size = 允许从节点最大中断时长 * 主实例 offset 每秒写入量,
比如 master 每秒最大写入 64mb, 最大允许 60 秒,那么就要设置为 64mb*60 秒=3840mb(3.8G)

repl-backlog-size 1mb

7、 如果一段时间后没有 slave 连接到 master,则 backlog size 的内存将会被释放。
如果值为 0 则表示永远不释放这部份内存。

repl-backlog-ttl 3600

8、 slave 端的优先级设置,值是一个整数,数字越小表示优先级越高。当 master 故障时将会按照优先级来选择 slave 端进行恢复,如果值设置为 0,则表示该 slave 永远不会被选择。

slave-priority 100

9、 设置当一个 master 端的可用 slave 少于 N 个,延迟时间大于 M 秒时,不接收写操作。
Master 的重启会导致 master_replid 发生变化, slave 之前的 master_replid 就和 master 不一致从而会引发所有 slave 的全量同步。

min-slaves-to-write 0 
min-slaves-max-lag 10

10、 slave 切换 master

# 127.0.0.1:6379> SLAVEOF no one
OK
# 127.0.0.1:6379> info Replication

测试能否写入数据:

# 127.0.0.1:6379> set key1 value1
OK

Slave 节点再有 Slave

redis 主备数据不一致 redis主备模式_数据_04

常见问题汇总

  1. master 密码不对:
    即配置的 master 密码不对,导致验证不通过而无法建立主从同步关系。
  2. redis 主备数据不一致 redis主备模式_redis_05

  3. Redis 版本不一致:
    不同的 redis 版本之间存在兼容性问题, 因此各 master 和 slave 之间必须保持版本一致。
  4. redis 主备数据不一致 redis主备模式_服务器_06

  5. 无法远程连接:
    在开启了安全模式情况下,没有设置 bind 地址和密码