Redis(二)复制和哨兵

二、复制

###################################################
A Redis可以配置slaveof <B Redis host> <B Redis port>来复制B Redis
或者
连上A Redis的客户端执行命令slaveof <B Redis host> <B Redis port>

这样,则A Redis是从节点,B Redis是主节点。

从Redis连上主Redis,向主Redis发送SYNC命令来完成对主Redis的复制:
1.从Redis向主Redis发送SYNC命令
2.主Redis收到SYNC命令后执行BGSAVE命令,即fork一个子进程生成RDB文件,在开始生成RDB文件之时并使用一个缓冲区
记录客户端的写操作命令
3.主Redis的BGSAVE命令执行完成,主Redis将生成好的RDB文件发送给从Redis,从Redis接收到RDB文件,将自己原有的数据(如果有的话)全部清除干净,将RDB文件加载到内存中,在RDB文件的加载期间,从Redis是阻塞无法处理客户端请求的
4.主Redis将记录在缓冲区的写命令发送给从Redis,从Redis执行主Redis发过来的写操作命令,这样,从Redis的数据库状态就可以跟
主Redis当前的数据库状态达成一致
5.接着主、从Redis就使用命令传播操作来同步数据

从Redis的首次复制日志
2465:S 26 Dec 18:31:23.844 * The server is now ready to accept connections on port 6378
2465:S 26 Dec 18:31:23.844 * Connecting to MASTER 127.0.0.1:6379
2465:S 26 Dec 18:31:23.844 * MASTER <-> SLAVE sync started
2465:S 26 Dec 18:31:23.844 * Non blocking connect for SYNC fired the event.
2465:S 26 Dec 18:31:23.844 * Master replied to PING, replication can continue...
2465:S 26 Dec 18:31:23.845 * Partial resynchronization not possible (no cached master)
2465:S 26 Dec 18:31:23.846 * Full resync from master: a92ac8df2027429ebed78fdce7d5aa3c42bc8261:1
2465:S 26 Dec 18:31:23.914 * MASTER <-> SLAVE sync: receiving 37 bytes from master
2465:S 26 Dec 18:31:23.914 * MASTER <-> SLAVE sync: Flushing old data
2465:S 26 Dec 18:31:23.914 * MASTER <-> SLAVE sync: Loading DB in memory
2465:S 26 Dec 18:31:23.914 * MASTER <-> SLAVE sync: Finished with success

主Redis接受从Redis首次复制日志
2427:M 26 Dec 18:31:23.845 * Slave 127.0.0.1:6378 asks for synchronization
2427:M 26 Dec 18:31:23.845 * Full resync requested by slave 127.0.0.1:6378
2427:M 26 Dec 18:31:23.845 * Starting BGSAVE for SYNC with target: disk
2427:M 26 Dec 18:31:23.845 * Background saving started by pid 2468
2468:C 26 Dec 18:31:23.853 * DB saved on disk
2468:C 26 Dec 18:31:23.854 * RDB: 6 MB of memory used by copy-on-write
2427:M 26 Dec 18:31:23.914 * Background saving terminated with success
2427:M 26 Dec 18:31:23.914 * Synchronization with slave 127.0.0.1:6378 succeeded

从2.8版本开始,Redis使用PSYNC命令代替SYNC命令来执行复制时的同步操作,
PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)
其中,部分重同步主要由几部分来构成:
A.主Redis的复制偏移量(replication offset)和从Redis的复制偏移量
B.主Redis的复制积压缓冲区(replication backlog)
C.Redis的运行ID(run ID)

部分重同步的相关概念
//===================================================================
复制偏移量:
主Redis每次向从Redis传播N个字节的数据时,都会在自己的复制偏移量上加N;
同理,从Redis每次接收到N个字节时,也会在自己的复制偏移量上加N。
复制积压缓冲区:
由主Redis维护的一个固定长度(默认为1MB)的FIFO队列,在主Redis向从Redis进行写命令传播的同步,
它也会将写命令入队到复制积压区里,并记录着队列里每个节点对应其复制偏移量。
运行ID:
每个Redis运行后都有自己的ID,可以在Redis客户端执行info命令,查看Redis的运行ID
127.0.0.1:6378> info
# Server
redis_version:3.0.7
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:3519b46925a7a925
redis_mode:standalone
os:Linux 3.10.0-327.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.5
process_id:2014
run_id:b0651e4b5ca36e776ec7d6d50f1aa8e626b4e1d5
tcp_port:6378
uptime_in_seconds:14794
uptime_in_days:0
hz:10
lru_clock:6429075
config_file:/home/redis-3.0.7/redis-6378.conf
<其他信息省略>

从上面info命令的返回结果中可以看出运行ID(run_id)为b0651e4b5ca36e776ec7d6d50f1aa8e626b4e1d5

如果查看服务器的客户端连接详情,可以使用client list命令查看客户端列表:

127.0.0.1:6379> client list
id=2 addr=127.0.0.1:51191 fd=6 name= age=318 idle=183 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=client
id=3 addr=127.0.0.1:51192 fd=7 name= age=4 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client


部分重同步PSYNC
//==========================================================
1.如果是首次同步主Redis的数据,则从Redis会发送操作跟SYNC命令是一样的。
2.如果从Redis已经复制过主Redis,那么从Redis在开始新一次的复制会向主Redis发送PSYNC <run_id> <offset>,
其中run_id就是上一次复制的主Redis运行ID,offset就是从Redis当前的复制偏移量。
主Redis接收从Redis的PSYNC复制命令,会检查复制积压缓冲区是否有offset + 1的偏移量
A.如果复制积压缓冲区存在offset + 1偏移量,则主Redis返回+CONTINUE回复,表示主Redis会执行部分重同步操作,只需要将复制积压缓冲区中偏移量offset + 1往后的数据全部发给从Redis就OK了。
B.如果复制积压缓冲区不存在offset + 1偏移量,则主Redis会返回+FULLRESYNC <run_id> <offset>,表示主Redis会执行完整重同步操作,其中offset是主Redis当前的复制偏移量。

Redis的心跳检测
Redis的复制在命令传播阶段,从Redis默认会以一秒的频率向主Redis发送命令
replconf ack <offset>
其中offset是从Redis当前的复制偏移量

如果主Redis发现从Redis发送过来的复制偏移量不相同,则把自己有变化的数据发送给从Redis


三、Sentinel(哨兵)

###################################################
Sentinel是Redis高可用的解决方案:
由一个或多个Sentinel实例组成Sentinel系统可以监视一个或多个主Redis服务器,以及主Redis属下的从Redis,
当被监视的主Redis进入下线状态时,Sentinel会将它的其中一个从Redis升级为主Redis,其他从Redis复制新的主Redis,
当旧的主Redis重新上线时,会以从Redis的角色来复制新的主Redis。

启动,这里我是将启动命令编辑在shell脚本中:
#!/bin/sh

# /home/redis-3.2.1/src/redis-sentinel /home/redis-3.2.1/sentinel.conf &
# or
/home/redis-3.2.1/src/redis-server /home/redis-3.2.1/sentinel.conf --sentinel &

其中,哨兵的配置文件sentinel.conf中有一项:
sentinel monitor <master-name> <ip> <redis-port> <quorum>
如:
sentinel monitor mymaster 127.0.0.1 6379 1
master-name是给主Redis起下名字,如mymaster
quorum指有多少个Sentinel实例认为主Redis是下线状态,那主Redis将会被认为下线状态,则会进行故障转移处理

注意,sentinel.conf只需要配置主Redis就可以,而不需配置它的从Redis,因为Sentinel可以根据主Redis而读到它的从Redis,通过向主Redis发送info命令就可以知道从Redis列表。


通过命令get-master-addr-by-name就可以查找到Sentinel的master节点

127.0.0.1:26379> sentinel get-master-addr-by-name mymaster
1) "192.168.20.111"
2) "6379"

客户端订阅哨兵服务器的+switch-master事件
===================================================
通过订阅+switch-master事件,客户端可以知道master服务器的切换。
+switch-master <master name> <oldip> <oldport> <newip> <newport> :配置变更,主服务器的 IP 和地址已经改变。 这是绝大多数外部用户都关心的信息。

比如,订阅的+switch-master事件,主服务器发生改变,哨兵服务器会推送消息:

mymaster 192.168.20.111 6378 192.168.20.111 6379

这表示旧的主服务器192.168.20.111 6378已经切换到新的主服务器192.168.20.111 6379

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值