1. Redis主从配置
经典的 master/slave 模式,即主从复制(replication)。
通过本篇学习,将解决几个问题:
- Replication是什么概念?即经典的 master/slave模式究竟是什么?
- Redis如何进行master/slave配制?如果验证?
- Redis主从复制的原理是什么样的?即其主从复制的实现过程。
- Redis的主从复制有容灾机制吗?master down机了会自去选举一个新的master吗?
1.1. Redis复制的特性
- redis 使用异步复制
- 一个 master 可以有多个 slave。
- slave 可以再分出 slave, 除了将多个 slave 连接到同一个 master 之外, slave 也可以以级联形式连接到另一个 slave。
- master 是以非阻塞的方式为 slaves 提供服务。所以在 master-slave 同步期间,客户端仍然可以提交查询或修改请求。
- 复制时,在slave端也是非阻塞的,假设你在redis.conf中配置redis这个功能,当slave在执行的新的同步时,它仍可以用旧的数据信息来提供查询,否则,你可以配置当redis slaves去master失去联系是,slave会给发送一个客户端错误。
- slave 一般用于 read-only 查询操作,例如耗费资源的 sort 操作,也可以简单的用于数据安全。
- 通过复制可以避免 master 全量写硬盘的消耗(在 master 的 redis.config 配置中注释掉所有”save”命令),然后连接一个用来持久化数据的 slave 即可。但是这样要确保 master 不会自动重启( 由于 master 没做持久化,在重启后会以空 dataset 启动,此时会自动同步给 slave ,导致 slave 也会清空本地数据,变成空 dataset)。
1.2. master 关闭持久化时的数据安全
- 建立开启持久化配置: 强烈建立在使用 redis 复制时, 在 master 和 slave 启用持久化。
- 禁止master自动重启: 由于某些原因,如磁盘慢问题,不能在 master 开启持久化时,一定要配置 master 避免自动重启
看一下下面的过程就可以理解,在 master 关闭持久化时,设置自动重启会带来数据安全危险:
- 节点A为 master,持久化设置为关闭状态,节点B和C为 slave,从A复制数据。
- 某时刻,节点 A crashed,内存数据在 A 挂掉的时候全部丢失, 由于自动重启设置, A 以空数据集重新启动。
- 节点B和C将从节点A复制,节点A为空,导致节点B和C的副本数据被清空。
由上所述,在 master 上关闭持久化并设置自动重启是一件非常危险的操作。
1.3. redis复制是怎么进行工作的?
每一个 master 都会有两个信息:
用来标识数据集的ID, 一般是随机字符串, 可以在 slave 的 log-redis.log 文件中找到。
# 全量数据同步后面会有 master: ID:offset 13065:S 12 Oct 10:42:43.056 * Full resync from master: 62a809fabb384640d7ce03b3053b305f65e6abe1:339 13065:S 12 Oct 10:42:43.070 * MASTER <-> SLAVE sync: receiving 94 bytes from master 13065:S 12 Oct 10:42:43.070 * MASTER <-> SLAVE sync: Flushing old data
一个 offset , 标识需要发送到slave的字节量, 同心用 master 的 offset 和 slave 的 offset 进行比较来判断同步是否完成;
$ bin/redis-cli info replication # Replication role:master connected_slaves:2 # slave0 中的 offset 如果和 master_repl_offset 一致, 表示 slave 数据和 master 一致 slave0:ip=127.0.0.1,port=6380,state=online,offset=1305,lag=0 slave1:ip=127.0.0.1,port=6381,state=online,offset=1305,lag=0 master_repl_offset:1305 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:1304
ReplicationId, offset
唯一标识 master 的一个确切数据集版本。
1.3.1. Redis复制过程
- slave连接到master, 使用数据同步命令PSYNC发送
master replicationId
和其已处理的offset
到master
- master收到slave的同步数据请求,判断是否可采用部分增量数据同步方式,如果可以,则发送增量数据给slave,以下情况会触发全量数据同步:
- slave发送给master的ReplicationID已过期或未知
- master缓存区的backlog数据量不足以满足slave的需求
- 全局数据同步的话,master会启动一个后台进程,将数据库快照保存到rdb文件,与此同时,master主进程会缓存收到的客户端的所有对数据修改命令。
- 后台快照保存完成后,master把其发送给slave
- slave保存到磁盘上,然后加载进内存。
- master接着发送收集到的所有缓存区的命令给slave
当master和slave因一些故障当机时,slaves会自动的重链,如果master收到多个slave的同步请求,master会执行一个后台保存,以确保所有的slaves都是正常的。
当master和slave能够维持链接,就会有一个完整的同步进行。