文章目录
写在前面
Redis 支持简单且易用的主从复制(master-slave replication)功能, 该功能可以让从服务器(slave server)成为主服务器(master server)的精确复制品。
1. 复制原理
Redis的主从复制主要分为以下几个步骤:
- 当建立一个从服务器时, 从服务器都将向主服务器发送一个 SYNC 命令
- 主服务器接收到SYNC命令之后开始执行 BGSAVE , 并在保存操作执行期间, 将所有新执行的写入命令都保存到一个缓冲区里面
- 当 BGSAVE 执行完毕后, 主服务器将执行保存操作所得的 .rdb 文件发送给从服务器, 从服务器接收这个 .rdb 文件, 并将文件中的数据载入到内存中。
- 之后主服务器会以 Redis 命令协议的格式, 将写命令缓冲区中积累的所有内容都发送给从服务器
2.配置
Redis的复制遵循的基本原理是:配从不配主。
在从服务器的配置文件中设置
slaveof ipAddress port
当然,也可以用以下在从服务器中用以下命令。
slaveof ipAddress port
3. 读写分离
所谓的读写分离指的是:主服务器写,从服务器只读。
在从服务器的redis.conf
文件中配置
slave-read-only yes
4. 主服务器只在有至少 N 个从服务器的情况下,才执行写操作
从 Redis 2.8 开始, 为了保证数据的安全性, 可以通过配置, 让主服务器只在有至少 N 个当前已连接从服务器的情况下, 才执行写命令。
以下是这个特性的运作原理:
- 从服务器以每秒一次的频率 PING 主服务器一次, 并报告复制流的处理情况。
- 主服务器会记录各个从服务器最后一次向它发送 PING 的时间。
- 用户可以通过配置, 指定网络延迟的最大值 min-slaves-max-lag , 以及执行写操作所需的至少从服务器数量 min-slaves-to-write 。
如果至少有 min-slaves-to-write 个从服务器, 并且这些服务器的延迟值都少于 min-slaves-max-lag 秒, 那么主服务器就会执行客户端请求的写操作。
你可以将这个特性看作 CAP 理论中的 C 的条件放宽版本: 尽管不能保证写操作的持久性, 但起码丢失数据的窗口会被严格限制在指定的秒数中。
可以在redis配置文件中配上如下命令
min-slaves-to-write <number of slaves>
min-slaves-max-lag <number of seconds>
5 复制机制实战模式
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
但是只要是重新连接master,一次完全同步(全量复制)将被自动执行
本机中建立三个redis的服务器
端口 | 端口号 | 主从 |
---|---|---|
port | 6379 | 主 |
port | 6380 | 从 |
port | 6381 | 从 |
需要修改的配置文件
appendfilename "appendonly6379.aof"
dbfilename dump6379.rdb
logfile "6379.log"
pidfile /var/run/redis_6380.pid
5.1 查看节点的配置信息
info replication
具体的信息:
# Replication
role:master
connected_slaves:0
master_replid:98cc791f79ec72ed8e954d939c4a32bf6f253107
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
5.2 设置从机的节点信息
默认情况下只配置从机的跟随信息
从库配置:slaveof 主库IP 主库端口
SLAVEOF 127.0.0.1 6379
一旦连接上主机,从机 会备份主机所有的信息
注意点:
- 从机只允许读不允许写
127.0.0.1:6380> set k6 v6
(error) READONLY You can't write against a read only replica.
- 主机挂了,从机如何做?
从机还会原地等待,直到主机重新连接,一旦主机重新连接会继续承担主机责任。
- 从机挂了,一旦从机重新连接会如何?
从机会与主机断开连接,称为另一个主机,如果还是需要与原主机形成主从关系,还是需要重新建立起关联,除非配入了配置文件中。
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379
OK Already connected to specified master
- 主机挂了,从机如何成为主机?
从机可以通过如下命令成为主机:
SLAVEOF no one
使当前数据库停止与其他数据库同步,转成主数据库
127.0.0.1:6380> SLAVEOF no one
OK
然后通过新的连接建立起主从关系
127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
OK
5.3 哨兵模式
一旦master挂了,自动从slaver中选择一个服务器作为master。
反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
example:
- 一主二从
- 新建sentinel.conf文件
- 配置哨兵,填写内容。
sentinel monitor 被监控数据库名字(自己起名字) 127.0.0.1 6379 1
sentinel monitoer host6379 127.0.0.1 6379 1
最后数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多少后成为主机
4. 启动哨兵
/usr/local/var/db/redis/sentinel.conf
sentinel的文件地址
redis-sentinel /usr/local/var/db/redis/sentinel.conf
启动之后的内容:
redis redis-sentinel /usr/local/var/db/redis/sentinel.conf
10279:X 20 Feb 2020 19:54:46.057 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
10279:X 20 Feb 2020 19:54:46.058 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=10279, just started
10279:X 20 Feb 2020 19:54:46.058 # Configuration loaded
10279:X 20 Feb 2020 19:54:46.059 * Increased maximum number of open files to 10032 (it was originally set to 4864).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.5 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 10279
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
10279:X 20 Feb 2020 19:54:46.061 # Sentinel ID is 170869946001af78516f578cf651d7854b7b1766
10279:X 20 Feb 2020 19:54:46.061 # +monitor master host6379 127.0.0.1 6379 quorum 1
10279:X 20 Feb 2020 19:54:46.065 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:54:46.066 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
可以看到sentinel
后台选举的日志:
10279:X 20 Feb 2020 19:57:53.519 # +sdown master host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.519 # +odown master host6379 127.0.0.1 6379 #quorum 1/1
10279:X 20 Feb 2020 19:57:53.519 # +new-epoch 1
10279:X 20 Feb 2020 19:57:53.519 # +try-failover master host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.522 # +vote-for-leader 170869946001af78516f578cf651d7854b7b1766 1
10279:X 20 Feb 2020 19:57:53.522 # +elected-leader master host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.522 # +failover-state-select-slave master host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.598 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.598 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.673 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.845 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.845 # +failover-state-reconf-slaves master host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:53.898 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:54.876 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:54.876 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:54.978 # +failover-end master host6379 127.0.0.1 6379
10279:X 20 Feb 2020 19:57:54.978 # +switch-master host6379 127.0.0.1 6379 127.0.0.1 6380
10279:X 20 Feb 2020 19:57:54.979 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6380 // 选举6380作为master
10279:X 20 Feb 2020 19:57:54.979 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380 // 选举6380作为master
一旦选举了新的master
之后,即使原来挂掉的master
正常连接,会成为slaver
。
可以看到如下两个slaver
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=32172,lag=0 // 6381作为slaver
slave1:ip=127.0.0.1,port=6379,state=online,offset=32172,lag=0 // 6379作为slaver
master_replid:561e44624ae1f8b195f0ac001f036290894974cf
master_replid2:9aa285e0ed5f95030ef8b4722fcd4feda0a578b8
master_repl_offset:32172
second_repl_offset:11329
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:32172
reference:
[1]: http://doc.redisfans.com/topic/replication.html