缓存学习(九):分布式Redis之副本、哨兵

目录

1.配置主从节点

2.复制原理

2.1 复制流程

2.1.1 全量复制

2.1.2 断点续传

2.2 PSYNC协议

2.3 心跳机制

3 哨兵Sentinel

3.1 简介

3.2 配置

3.3 搭建

3.4 命令

3.5 哨兵实现原理

3.5.1 Pub/Sub

3.5.2 Leader与Epoch

3.5.3 监控和从节点选取

3.6 Jedis对哨兵的支持


1.配置主从节点

主从关系的配置有三种方式:

需要注意的是,如果主节点配置了requirepass,从节点需要配置materauth才能连接,下面是一个连接示例(6379端口实例为主节点,此处启动的6380端口实例为从节点):

root@Yhc-Surface:~# redis-server --port 6380 --slaveof localhost 6379
...
24:S 28 Apr 2019 14:31:19.041 * Connecting to MASTER localhost:6379
24:S 28 Apr 2019 14:31:19.046 * MASTER <-> REPLICA sync started
24:S 28 Apr 2019 14:31:19.048 * Non blocking connect for SYNC fired the event.
24:S 28 Apr 2019 14:31:19.049 * Master replied to PING, replication can continue...
24:S 28 Apr 2019 14:31:19.050 * Partial resynchronization not possible (no cached master)
24:S 28 Apr 2019 14:31:19.056 * Full resync from master: 1197e315344ccb5e97581f126ca28388080feba1:0
24:S 28 Apr 2019 14:31:19.082 * MASTER <-> REPLICA sync: receiving 1070 bytes from master
24:S 28 Apr 2019 14:31:19.084 * MASTER <-> REPLICA sync: Flushing old data
24:S 28 Apr 2019 14:31:19.084 * MASTER <-> REPLICA sync: Loading DB in memory
24:S 28 Apr 2019 14:31:19.086 * MASTER <-> REPLICA sync: Finished with success

可以看到,6380节点启动后自动连接主节点并进行了一次全量复制。 此时在6379插入一条数据,在6380进行查询:

127.0.0.1:6379> set hello world
OK

127.0.0.1:6380> get hello
"world"

断开连接只需要在从节点执行slaveof no one命令即可,同理,如果要更换主节点,也只需要使用slaveof命令即可,但是更换主节点后,原本的数据会丢失(断开与主节点的连接则不会清空数据):

127.0.0.1:6380> slaveof localhost 6381
OK
127.0.0.1:6380> get hello
(nil)

在Redis副本机制中,会在初次连接以及长时间断开连接时进行全量复制,之后每次执行写入操作都会自动复制,如果短期断开连接,则从会在重新连接后,进行增量同步,无论哪种复制方式,都默认是异步的。在默认情况下,从节点只处理读请求。

Redis副本有三种结构:

最简单的是一主一从结构,这种方式可以帮助主节点分担至少一半的读请求,此外还可以在主节点处关闭持久化,将持久化的压力转移到从节点上,不过这样做的一个后果是,如果主节点下线后又立即重启,会因为没有日志或快照,导致主节点数据清空,经过同步后把从节点的数据也清空了。这种时候,需要先断开主从节点之间的连接,然后重启主节点,再倒转主从关系。

第二种结构是星型结构,即一主多从,这种结构适合读多写少的场景,缺点是初次连接时容易造成主节点拥塞,一个改进思路是让从节点分批上线。

第三种结构是树状结构,即某些从节点作为其他从节点的主节点,实现级联复制,这样一来可以避免多写对主节点造成的压力,二来可以实现指数级的数据扩散速度,缺点就是比较难管理。

Redis副本的相关信息可以通过info replication或role命令查看,示例如下:

127.0.0.1:6379> role
1) "master"
2) (integer) 8637
3) 1) 1) "127.0.0.1"
      2) "6380"
      3) "8637"
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6380,state=online,offset=8637,lag=1
master_replid:32e1f0aa4381c3fd906a21b7a748ff1fa93be2b2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:8637
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:8637

对于role命令,其在主节点上输出有三部分,1)是其角色,有master和slave、sentinel三种,2)是主节点复制偏移量,3)是连接的从节点。在从节点上输出有5部分,分别是:角色(slave)、主节点IP、主节点端口、复制状态(connected、connecting、sync三种)、一共从主节点接收了多少数据。sentinel的下面再介绍。

对于info replication,内容比较长,但是自描述性较好就不做介绍了。

2.复制原理

2.1 复制流程

2.1.1 全量复制

首先看一下主从双方的日志,首先是主节点;

192:M 28 Apr 2019 15:25:47.935 * Replica 127.0.0.1:6380 asks for synchronization
192:M 28 Apr 2019 15:25:47.936 * Full resync requested by replica 127.0.0.1:6380
192:M 28 Apr 2019 15:25:47.936 * Starting BGSAVE for SYNC with target: disk
192:M 28 Apr 2019 15:25:47.948 * Background saving started by pid 200
200:C 28 Apr 2019 15:25:47.959 * DB saved on disk
192:M 28 Apr 2019 15:25:48.050 * Background saving terminated with success
192:M 28 Apr 2019 15:25:48.052 * Synchronization with replica 127.0.0.1:6380 succeeded

然后是从节点:

196:S 28 Apr 2019 15:25:47.922 * Connecting to MASTER localhost:6379
196:S 28 Apr 2019 15:25:47.931 * MASTER <-> REPLICA sync started
196:S 28 Apr 2019 15:25:47.931 * Non blocking connect for SYNC fired the event.
196:S 28 Apr 2019 15:25:47.933 * Master replied to PING, replication can continue...
196:S 28 Apr 2019 15:25:47.933 * Partial resynchronization not possible (no cached master)
196:S 28 Apr 2019 15:25:47.950 * Full resync from master: 32e1f0aa4381c3fd906a21b7a748ff1fa93be2b2:0
196:S 28 Apr 2019 15:25:48.051 * MASTER <-> REPLICA sync: receiving 175 bytes from master
196:S 28 Apr 2019 15:25:48.053 * MASTER <-> REPLICA sync: Flushing old data
196:S 28 Apr 2019 15:25:48.056 * MASTER <-> REPLICA sync: Loading DB in memory
196:S 28 Apr 2019 15:25:48.057 * MASTER <-> REPLICA sync: Finished with success

根据以上内容,可以推断出如下复制流程:

  • 首先,从节点连接主节点,由于是初次连接,因此,连接成功后需要进行全量复制,为了确保可以进行复制,首先进行了一次PING
  • 如果PING成功,则由从节点发出SYNC信号,发起全量同步事件
  • 主节点收到SYNC后,开始BGSAVE操作,将当前数据保存为快照
  • 快照保存完毕后,开始发送给从节点,从节点清空旧数据并载入主节点发来的新数据

SYNC是Redis的同步协议,不过目前已经改用PSYNC,后者支持部分同步,如果直接向6379端口发送SYNC,会有如下输出:

root@Yhc-Surface:~# echo 'SYNC' | nc localhost 6379
$410
REDIS0009       redis-ver5.0.4
redis-bits@ctime¨]used-memB repl-stream-db repl-id(32e1f0aa4381c3fd906a21b7a748ff1fa93be2b2repl-offsetMaof-pre:hobbymalet@K@__   K   programming
sexualage redisgood helloworld testmyteststream  jb        <<     nameagesexual   zhangsan  male  jb  dO*1
$4
PING
*1
$4
PING
*1
$4
PING
... //每隔几秒输出一次 *1\r\n$4\r\nPING\r\n

SYNC实际就是传输RDB的内容。PSYNC会在下面介绍。

可以看到,当进行全量同步时,有如下日志:

Full resync from master: 32e1f0aa4381c3fd906a21b7a748ff1fa93be2b2:0

这里的master被一个字符串标记了,以冒号为分隔,由两部分组成,前面较长的一串被称为副本ID,是一个伪随机串,用来标记数据集,后面的0是偏移量,用来标记从数据集的哪一部分开始复制,这里由于是全量复制,所以肯定是从0开始。

该流程建立在没有开启 repl-diskless-sync 的情况下,该选项开启后不会先保存RDB再发送,而是直接发送数据

以上两段日志未能体现的是:1)如果在复制期间有写请求到达主节点,这些请求正常响应后,都会存入backlog队列,等到快照发送完毕后再发给从节点 2)从节点如果开启了AOF,则会再同步完毕后立刻执行一次rewrite

2.1.2 断点续传

上面的复制流程是全量复制的,当主从节点断开一段时间后(从节点关闭,不能使用slave no one,后者会导致从节点进入主节点模式,导致副本ID变化,使得每次重连都会进行全量同步)

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值