Redis主从复制与哨兵模式

Redis主从复制与哨兵模式

单机部署

单机部署就是一个实例,生产上基本上不会用,也就学习时玩玩。

缺点也很明显:

  • 容易发生单点故障。
  • 一个实例存储全量数据,内存容量有限。
  • 所有请求都怼到一个实例,磁盘IO、网络IO、带宽、CPU等资源都会成为瓶颈。

主从复制

在这里插入图片描述

与主从复制相关的配置:

# master节点ip和port
replicaof <masterip> <masterport>

# master认证的密码
masterauth <master-password>

# 在同步的过程中是否允许客户端获取旧的数据
replica-serve-stale-data yes

# slave节点只允许读
replica-read-only yes

# Disk-backed:master先将数据存在RDB文件并保存到磁盘上,再发送给slave
# Diskless:master直接在内存中生成RDB文件并通过socket发送给slave
repl-diskless-sync no

# 缓冲区大小
# repl-backlog-size 1mb

# 缓冲区被释放的超时时间
# repl-backlog-ttl 3600

# 最少要有三个slave写数据,否则master停止写请求
# min-replicas-to-write 3
# slave延迟超过10s,master停止写请求
# min-replicas-max-lag 10

Redis主从复制分为三个阶段:全量复制、增量复制、命令传播。

全量复制主要分为如下4个步骤:

  1. slave连接master,发送psync2命令请求同步数据。
  2. master执行bgsave命令,生成RDB快照文件,在这期间master执行的所有写命令都会被写入复制缓冲区。
  3. master执行完bgsave命令后,向所有slave发送快照文件。
  4. slave收到RDB文件后,清空slave之前的所有数据,根据RDB文件恢复数据。

增量复制:全量复制完成后,master节点将复制缓冲区的所有指令都会发送给slave,slave会执行这些指令。

命令传播:master每执行一条写命令,都会异步复制到slave中执行。

下面使用主从复制来进行部署redis:

环境配置:

127.0.0.1:6380 master
127.0.0.1:6381 slave
127.0.0.1:6382 slave

在/test/目录分别新建/test/6380、/test/6381、/test/6382三个目录,用来存放redis的数据文件。

启动redis 6380(master),这里为了便于演示,都使用非守护进程的方式启动:

# redis-server --dir /test/6380 --port 6380

启动两条slave,redis 6381和redis 6382:

# redis-server --dir /test/6381 --port 6381
# redis-server --dir /test/6382 --port 6382

现在三台redis还没有任何关系,现在使用REPLICAOF命令对6381进行主从复制(旧版本使用slaveof命令):

# redis-cli -p 6381
127.0.0.1:6381> REPLICAOF 127.0.0.1 6380
OK
127.0.0.1:6381> 

从master的日志中可以看到已经同步成功了:

42312:M 07 Sep 2020 14:41:14.795 * Replica 127.0.0.1:6381 asks for synchronization
42312:M 07 Sep 2020 14:41:14.795 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'af8579453368bfeac1f25dc006fca38b22128189', my replication IDs are '1545bc440107d345a1a7fd4a619a6a5902d4d3f1' and '0000000000000000000000000000000000000000')
42312:M 07 Sep 2020 14:41:14.795 * Replication backlog created, my new replication IDs are '1e42b4709fec51989042b67eaa83151587626407' and '0000000000000000000000000000000000000000'
42312:M 07 Sep 2020 14:41:14.795 * Starting BGSAVE for SYNC with target: disk
42312:M 07 Sep 2020 14:41:14.797 * Background saving started by pid 42330
42330:C 07 Sep 2020 14:41:14.798 * DB saved on disk
42330:C 07 Sep 2020 14:41:14.799 * RDB: 4 MB of memory used by copy-on-write
42312:M 07 Sep 2020 14:41:14.895 * Background saving terminated with success
42312:M 07 Sep 2020 14:41:14.895 * Synchronization with replica 127.0.0.1:6381 succeeded

对6382进行同样的操作,这时我们对master写入一个key,两个slave是可以访问到的,但是slave是不能写入的,只能读。

此时如果把master关掉,两个slave都会报一个错误,数据还是可以读的(提供读服务):

42317:S 07 Sep 2020 14:56:06.979 * Connecting to MASTER 127.0.0.1:6380
42317:S 07 Sep 2020 14:56:06.980 * MASTER <-> REPLICA sync started
42317:S 07 Sep 2020 14:56:06.980 # Error condition on socket for SYNC: Operation now in progress

使用主从复制模式,如果master挂了,需要人工手动指定其中一个slave升为master,这里我把6381升为master:

127.0.0.1:6381> replicaof no one
OK

然后日志就会打印,master模式开启:

42317:M 07 Sep 2020 14:59:10.581 * Discarding previously cached master state.
42317:M 07 Sep 2020 14:59:10.581 # Setting secondary replication ID to 1e42b4709fec51989042b67eaa83151587626407, valid up to offset: 1305. New replication ID is e4f84f7e3161abf266b0cf263e75fe8e157baedb
42317:M 07 Sep 2020 14:59:10.581 * MASTER MODE enabled (user request from 'id=5 addr=127.0.0.1:5325 fd=8 name= age=1089 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=36 qbuf-free=32732 obl=0 oll=0 omem=0 events=r cmd=replicaof user=default')

最后将6382改为同步6381,这样又可以对外提供写服务了:

127.0.0.1:6382> replicaof 127.0.0.1 6381
OK

总结:

  • 主从复制模式分担了master读的压力,但是master节点还是单点的,还是会发生单点故障,数据还是全量的,内存容量可能会不足。
  • 主从复制模式中,master节点一旦挂了,需要人工来指定其中的一个slave为master。

哨兵模式

在这里插入图片描述
哨兵模式相对于主从复制模式,增加了几个哨兵对master节点进行监控。

下面使用哨兵模式来进行部署redis,还是基于上面主从复制的三台实例,在这个基础上部署三台哨兵(这个数据可以随意,一般奇数个)。

在/test/目录分别新建/test/16380、/test/16381、/test/16382三个目录,用来存放sentinel的数据文件,三个目录下新建redis.conf文件,内容如下:

port 16380
sentinel monitor mymaster 127.0.0.1 6380 2

三个sentinel数据目录下的文件内容都差不多,只有端口不一样,其中mymaster可以为任意的名字,一个sentinel可以对多个集群中的master节点进行监控,最后一个数字2的含义为3个节点中有2个节点(2票)判定master挂了就会开始自动故障转移。

先启动三台redis:

# redis-server --dir /test/6380 --port 6380
# redis-server --dir /test/6381 --port 6381 --replicaof 127.0.0.1 6380
# redis-server --dir /test/6382 --port 6382 --replicaof 127.0.0.1 6380

然后启动三台sentinel(也可以使用单独的redis-sentinel命令):

# redis-server /test/16380/redis.conf --sentinel
# redis-server /test/16381/redis.conf --sentinel
# redis-server /test/16382/redis.conf --sentinel

从sentinel的日志中能发现,它能根据master节点找到2个slave,以及其他两个sentinel:

42455:X 07 Sep 2020 15:25:08.148 # Sentinel ID is dae3f9810ed0593b823182204f47095f7cdccaf2
42455:X 07 Sep 2020 15:25:08.148 # +monitor master mymaster 127.0.0.1 6380 quorum 2
42455:X 07 Sep 2020 15:25:08.149 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
42455:X 07 Sep 2020 15:25:08.150 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6380
42455:X 07 Sep 2020 15:25:08.272 * +sentinel sentinel e0074174d033f133d75f70dab2c79c1b92421fa2 127.0.0.1 16380 @ mymaster 127.0.0.1 6380
42455:X 07 Sep 2020 15:25:15.408 * +sentinel sentinel 34e7e9cda9f1a917784322efca2325a9d118be32 127.0.0.1 16382 @ mymaster 127.0.0.1 6380

sentinal可以根据master节点找到其他slave,那么它是怎么找到其他sentinel的呢,原来他们都订阅了同一个频道,并将自己的信息发送到频道中,像一个聊天窗口一样,可以使用下面的命令来查看他们的聊天内容:

127.0.0.1:6380> subscribe __sentinel__:hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "__sentinel__:hello"
3) (integer) 1
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,16380,e0074174d033f133d75f70dab2c79c1b92421fa2,0,mymaster,127.0.0.1,6380,0"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,16382,34e7e9cda9f1a917784322efca2325a9d118be32,0,mymaster,127.0.0.1,6380,0"
1) "message"
2) "__sentinel__:hello"
3) "127.0.0.1,16381,dae3f9810ed0593b823182204f47095f7cdccaf2,0,mymaster,127.0.0.1,6380,0"
...

然后关闭master节点,过了大概30s,6381就称为了master节点,可以从sentinel的日志中发现升级过程:

42401:X 07 Sep 2020 15:47:51.493 # +sdown master mymaster 127.0.0.1 6380
42401:X 07 Sep 2020 15:47:51.550 # +new-epoch 1
42401:X 07 Sep 2020 15:47:51.551 # +vote-for-leader 34e7e9cda9f1a917784322efca2325a9d118be32 1
42401:X 07 Sep 2020 15:47:51.555 # +odown master mymaster 127.0.0.1 6380 #quorum 3/2
42401:X 07 Sep 2020 15:47:51.555 # Next failover delay: I will not start a failover before Mon Sep  7 15:53:51 2020
42401:X 07 Sep 2020 15:47:52.201 # +config-update-from sentinel 34e7e9cda9f1a917784322efca2325a9d118be32 127.0.0.1 16382 @ mymaster 127.0.0.1 6380
42401:X 07 Sep 2020 15:47:52.201 # +switch-master mymaster 127.0.0.1 6380 127.0.0.1 6381
42401:X 07 Sep 2020 15:47:52.201 * +slave slave 127.0.0.1:6382 127.0.0.1 6382 @ mymaster 127.0.0.1 6381
42401:X 07 Sep 2020 15:47:52.201 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381
42401:X 07 Sep 2020 15:48:22.214 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6381

再去看一下sentinel的数据目录的redis.conf文件的内容(sentinel会自动更新配置文件):

port 16380
sentinel myid e0074174d033f133d75f70dab2c79c1b92421fa2
# Generated by CONFIG REWRITE
protected-mode no
user default on nopass ~* +@all
dir "/test"
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 127.0.0.1 6381 2
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel known-replica mymaster 127.0.0.1 6380
sentinel known-replica mymaster 127.0.0.1 6382
sentinel known-sentinel mymaster 127.0.0.1 16382 34e7e9cda9f1a917784322efca2325a9d118be32
sentinel known-sentinel mymaster 127.0.0.1 16381 dae3f9810ed0593b823182204f47095f7cdccaf2
sentinel current-epoch 1

总结:哨兵模式虽然解决主从复制的单点故障问题,变得高可用了,但是其他的缺点仍然未解决。

猜你喜欢

转载自blog.csdn.net/u022812849/article/details/108449830