Redis replication主从复制原理及配置
本文主要介绍Redis replication 主从复制原理和配置及基本操作 等
主要参考官方文档:
https://redis.io/topics/replication
http://redisdoc.com/topic/replication.html
一.原理
This system works using three main mechanisms:
系统工作的三个主要机制:
1. When a master and a slave instances are well-connected, the master keeps the slave updated by sending a stream of commands to the slave, in order to replicate the effects on the dataset happening in the master side due to: client writes, keys expired or evicted, any other action changing the master dataset.
当master和slave实例连接良好时,master通过从slave发送命令流来更新slave
2. When the link between the master and the slave breaks, for network issues or because a timeout is sensed in the master or the slave, the slave reconnects and attempts to proceed with a partial resynchronization: it means that it will try to just obtain the part of the stream of commands it missed during the disconnection.
当master和slave连接中断时,因为网络故障或者感知到master或者slave超时。Slave重连并试图进行重新同步:意味着获取失去连接时丢失的命令流
3. When a partial resynchronization is not possible, the slave will ask for a full resynchronization. This will involve a more complex process in which the master needs to create a snapshot of all its data, send it to the slave, and then continue sending the stream of commands as the dataset changes.
当无法重新部分同步(partial resynchronization)时,slave将要求完全重新同步(full resynchronization)。它将包含一个复杂过程,这过程中master需要为所有数据创建一个快照,发送到slave,再继续对变化的数据发送命令流
数据安全性概念
Redis的持久化存储主要提供两种方式:RDB与AOF
http://redisdoc.com/topic/persistence.html
1. RDB(Snapshot)模式
是默认的,即保存某一时刻的数据到硬盘,在下一次触发snapshot前如果服务器crash,在上次snapshot之后修改的数据会丢失。
主要配置redis.conf参数:
save <seconds> <changes>
stop-writes-on-bgsave-error yes
rdbcompression yes
dbfilename dump.rdb
dir ./
参数说明:
save <seconds> <changes>:在X秒内如果key有至少X次改变就触发持久化,例如save 900 1的话就是在900秒如果key有至少1次改变就触发持久化。如果想关闭此功能的话,可以把全部save行都注释或删除或者使用save ""。
stop-writes-on-bgsave-error:在bgsave遇到error的时候是否停止持久化,默认是yes代表是,no代表不是
rdbcompression:是否压缩,默认是yes代表是,no代表不是,如果想节省CPU的话就设为no,但rdb文件会比较大
dbfilename:持久化的文件名字,默认是dump.rdb
dir:持久化的目录名字,默认是redis.conf所在的目录./
2.AOF(append-only file)模式
需要手动开启,开启后以追加的方式默认每秒钟将记录的修改操作保存到硬盘
主要配置redis.conf参数:
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
dir ./
### 以下rewrite参数,AOF模式以追加方式记录所有写操作命令到硬盘,文件会越来越大,为缓解这种问题,redis使用了BGREWRITEAOF用于删除重复多余的写命令,类似BGSAVE,rewrite的时候会删除旧的AOF文件
###
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
参数说明:
appendonly:是否启动aof,默认是no代表不启用
appendfilename:aof的文件名,默认是appendonly.aof
appendfsync:触发的间隔,默认是everysec代表每秒,还可使用always代表有改变都触发,性能差些但数据最安全,no代表让OS自己决定什么时候执行,性能最好但数据不安全
dir:持久化的目录名字,默认是redis.conf所在的目录./
no-appendfsync-on-rewrite:执行rewrite时appendfsync是否暂停,默认no代表不暂停
auto-aof-rewrite-percentage:aof rewrite触发时机,当前aof文件大小超过上一次rewrite后aof文件的百分比后触发rewrite。如200,即当前的aof文件超过上一次重写后aof文件的2倍时才会再次rewrite
auto-aof-rewrite-min-size aof文件重写最小文件大小,即最开始aof文件必须要达到这个文件时才触发,后面的每次重写就不会根据这个变量了(根据上一次重写完成之后的大小).此变量仅初始化启动redis有效.如果是redis恢复时,则lastSize等于初始aof文件大小.
在使用redis复制的设置中,强烈建议在主服务器和从服务器中打开持久性。如果不能开启的话,例如由于磁盘速度非常慢而引起的延迟问题,则应避免在重启OS后自动重新启动服务,以免数据丢失。官方对此有做举例说明:
To better understand why masters with persistence turned off configured to auto restart are dangerous, check the following failure mode where data is wiped from the master and all its slaves:
1. We have a setup with node A acting as master, with persistence turned down, and nodes B and C replicating from node A.
2. Node A crashes, however it has some auto-restart system, that restarts the process. However since persistence is turned off, the node restarts with an empty data set.
3. Nodes B and C will replicate from node A, which is empty, so they'll effectively destroy their copy of the data.
复制功能的运作原理
无论是初次连接还是重新连接, 当建立一个从服务器时, 从服务器都将向主服务器发送一个 SYNC 命令。
接到 SYNC 命令的主服务器将开始执行 BGSAVE , 并在保存操作执行期间, 将所有新执行的写入命令都保存到一个缓冲区里面。
当 BGSAVE 执行完毕后, 主服务器将执行保存操作所得的 .rdb 文件发送给从服务器, 从服务器接收这个 .rdb 文件, 并将文件中的数据载入到内存中。
之后主服务器会以 Redis 命令协议的格式, 将写命令缓冲区中积累的所有内容都发送给从服务器。
即使有多个从服务器同时向主服务器发送 SYNC , 主服务器也只需执行一次 BGSAVE 命令, 就可以处理所有这些从服务器的同步请求。
从服务器可以在主从服务器之间的连接断开时进行自动重连, 在 Redis 2.8 版本之前, 断线之后重连的从服务器总要执行一次完整重同步(full resynchronization)操作, 但是从 Redis 2.8 版本开始, 从服务器可以根据主服务器的情况来选择执行完整重同步还是部分重同步(partial resynchronization)。
部分重同步
从 Redis 2.8 开始, 在网络连接短暂性失效之后, 主从服务器可以尝试继续执行原有的复制进程(process), 而不一定要执行完整重同步操作。
这个特性需要主服务器为被发送的复制流创建一个内存缓冲区(in-memory backlog), 并且主服务器和所有从服务器之间都记录一个复制偏移量(replication offset)和一个主服务器 ID (master run id), 当出现网络连接断开时, 从服务器会重新连接, 并且向主服务器请求继续执行原来的复制进程:
• 如果从服务器记录的主服务器 ID 和当前要连接的主服务器的 ID 相同, 并且从服务器记录的偏移量所指定的数据仍然保存在主服务器的复制流缓冲区里面, 那么主服务器会向从服务器发送断线时缺失的那部分数据, 然后复制工作可以继续执行。
• 否则的话, 从服务器就要执行完整重同步操作。
Redis 2.8 的这个部分重同步特性会用到一个新增的 PSYNC master_run_id offset 内部命令, 而 Redis 2.8 以前的旧版本只有 SYNC 命令, 不过, 只要从服务器是 Redis 2.8 或以上的版本, 它就会根据主服务器的版本来决定到底是使用 PSYNC master_run_id offset 还是 SYNC :
• 如果主服务器是 Redis 2.8 或以上版本,那么从服务器使用 PSYNC master_run_id offset 命令来进行同步。
• 如果主服务器是 Redis 2.8 之前的版本,那么从服务器使用 SYNC 命令来进行同步。
二. replication具体配置
实验:一台机器上配置两个服务器 master 6379 slave 6380
版本:redis_version:3.0.6
Master : 除 appendonly改yes,其它 使用默认值即可
/usr/local/redis/etc/redis.conf
appendonly yes
因为在同一台server上做slave测试需要复制一份配置文件,并分别更改端口号,pid文件名字,dump.rdb名字,aof文件名字
Slave
: /usr/local/redis/etc/redis.conf.6380
pidfile /var/run/redis6380.pid
port 6380
dbfilename dump6380.rdb
appendfilename "appendonly6380.aof"
appendonly yes
slaveof 127.0.0.1 6379
注:从 Redis 2.6 开始, slave支持只读模式, 且为slave的默认模式。
# Since Redis 2.6 by default slaves are read-only.
slave-read-only yes
开启slave
# redis-server /usr/local/redis/etc/redis.conf.6380
查看状态
master中执行:
[root@cloud ~]# redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=57,lag=0
master_repl_offset:57
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:56
127.0.0.1:6379> role
1) "master" --当前server角色
2) (integer) 71 --当前server复制偏移量
3) 1) 1) "127.0.0.1" --下属slave IP
2) "6380" --下属slave port
3) "71" --下属slave复制偏移量
slave中执行:
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0
slave_repl_offset:83567
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380> role
1) "slave" --当前server角色
2) "127.0.0.1" --上层master IP
3) (integer) 6379 --上层master port
4) "connected"
5) (integer) 83581 --目前从master接收到的复制副本偏移量
以上,master-slave 配置完成
注:因为 Redis 使用异步复制, 所以master发送的写数据并不一定会被slave接收到。因此,数据丢失可能性仍然是存在的。
为了进一步保证数据安全,可设置master服务器只在有至少 N 个slave服务器的情况下,才执行写操作
以下是这个特性的运作原理:
• 从服务器以每秒一次的频率 PING 主服务器一次, 并报告复制流的处理情况。
• 主服务器会记录各个从服务器最后一次向它发送 PING 的时间。
• 用户可以通过配置, 指定网络延迟的最大值 min-slaves-max-lag
以及执行写操作所需的至少从服务器数量 min-slaves-to-write 。
slave启用为master
在slave服务器执行命令 SLAVEOF NO ONE 将使得这个从属服务器关闭复制功能,并从slave服务器转变为master服务器,原来同步所得数据集不会被丢弃。
利用“SLAVEOF NO ONE 不会丢弃同步所得数据集”这个特性,可以在主服务器失败的时候,将从属服务器用作新的主服务器,从而实现无间断运行。
上述,介绍了 Redis replication主从复制原理和最简单的配置,后续会对Sentinel,Redis-Cluster等方案做整理