1172 #赚钱# 一篇文章了解Redis集群知识点


Redis -  集群:AKF拆分(x轴),CAP,主从复制,哨兵机制


单机Redis引发的问题

redis可以做为缓存,对于数据完整性要求不是特别高,即使丢失了数据也可以在Client访问的时候从数据库里拿出数据从新缓存到redis,即淘汰冷数据 缓存热数据。并且能急速的处理数据。
redis还可以作为数据库,但是需要保证可靠和完整性的,不能丢失数据。侧重点在于 速度 + 持久化。

无论作为缓存还是数据库,redis都保证了速度。在业务当中起着重要程度很高。

那么在业务当中,如果只运行一个redis实例会有哪些问题呢?

  1. 单点故障

  2. 容量瓶颈

  3. 访问压力

那么如何解决呢? AKF拆分一定要知道。

AKF拆分

AKF扩展立方体(Scalability Cube),是《架构即未来》一书中提出的可扩展模型,这个立方体有三个轴线,每个轴线描述扩展性的一个维度,他们分别是产品、流程和团队:
X轴 —— 代表无差别的克隆服务和数据,工作可以很均匀的分散在不同的服务实例上;
Y轴 —— 关注应用中职责的划分,比如数据类型,交易执行类型的划分;
Z轴 —— 关注服务和数据的优先级划分,如分地域划分。

使用AKF的方式拆分redis:

在这里插入图片描述
x轴:在x轴方向上,做N个主机的全量镜像 数据的副本,主redis与这些副本的关系为主从。主机可以对外提供read / write ,从机可以对外提供read(读写分离)。结合 高可用, 可以解决单点故障和容量瓶颈的问题,只是解决了 read 的压力,而没有解决 write 的压力。

y轴:在y轴方向上,可以把之前一台redis中的数据按照 业务 功能 来拆分成不同的redis实例存储,并且每个redis实例都可以再次做x轴的镜像副本进行读写分离,当然,x轴和y轴之间不是必须要结合使用。y轴的拆分解决了容量瓶颈问题和数据访问压力的问题。

z轴:如果y轴的某个redis实例过于臃肿,还可以把这个redis实例进行z轴的拆分,也就是把这个redis实例里面的数据按照一定规则查分。比如:取模,优先级等规则再次查分成多个redis,使得不同的数据出现在固定的redis里。

AKF拆分的重点就是把公司的全部数据进行分而治之,使得一个redis实例的数据量足够小,数据量足够小就更容易发挥单机的性能。

但是也会有相应的问题,以x轴主多镜像副本来说,如何保证数据一致性?

数据一致性(主从复制原理)

强一致性

如果 在一个主机和两个备机的情况下,Client发送命令set k1 a到 master,master如何把数据同步给slave呢?

在这里插入图片描述
第一种情况:master收到指令后会先不返回给Client,master写 OK 之后会通知slave写入数据并且阻塞等待,master等待两个slave给自己返回ok再给Client返回。

强一致性: 所有节点同步阻塞,直到数据全部一致。
引发问题:如果其中一台slave挂掉或者网络波动引起超时,即使其他salve都返回写入成功给master,master也会认为所有从机都写入失败,进而都进行回撤,最终客户端会认为写入失败。写入失败代表服务不可用,所以 数据强一致性会破坏可用性!


回到我们的出发点:为什么我们要把单机一变多为集群?
原因之一就是单点故障,解决可用性的问题。但是强一致性中,只要其中一台机器出现异常,就会导致整个模块不可使用,问题又回到了原点。
.
解决办法 : 给 强一致性 降级
采用异步的方式,容忍丢失一部分数据,就是弱一致性。

弱一致性

在这里插入图片描述
master收到Client命令写 ok 后直接返回给Client,master会异步的通知两个slave写操作,如果两个slave挂了导致写入失败,master也挂了。再重启之后slave就拿不到之前的master的写操作了,等于丢了一批数据。

弱一致性:异步,但是会丢失数据。
那么数据怎么可以不丢呢?最终一致性

最终一致性

redis


在这里插入图片描述
在master和slave之间,添加一个 可靠、响应速度够快 的 集群(比如:kafka),master到kafka之间为同步阻塞状态。master在写入的时候并没有直接通知两个slave,而是通知kafka,由kafka通知两个slave。如果master和kafka之间能够足够快的写入响应成功的话,就可以直接给Client返回OK了。
只要最终两个slave从kafka中取到数据,那么最终两个slave就会和master的数据达成一致,数据就不会丢失。

最终一致性:master和slave之间维护一个 可靠的集群。
引发的问题:一个客户端从一个 黑盒化 的集群中取数据。有可能会从master取到,也有可能从slave中取到,在slave和master数据最终达成一致之前,有可能取到不一致的数据。
.
这里和redis无关,redis并没有使用这种方式

CAP

主备,主从

在这里插入图片描述

主备:Client只能访问master,不会访问slave。slave就是为了master挂了后接替master,使Client能够从新的master拿到数据,slave是不会参与业务的。

主从:Client可以访问master,也可以访问slave。

redis对于主从和主备都可以使用,但是企业当中常用的是主从复制的方案。其中复制强调的就是主备的概念,即 slave和master数据相同。

但是无论是主从集群还是主备集群,其中都有一个master的概念。并且一般在master身上,是全量的读写 操作,但是master自己又是一个单点,是单点就会有单点故障,怎么解决?
那么必然会对master做高可用,最终目的就是在muster挂掉后把一个slave切换成一个master,并且对外的表现是不会出问题。

哨兵原理

引导:
归其原因是master会挂掉。当然可以通过人为手工的方式把一个slave切换成master,然后把其他的slave追随新的master。但是人会请假,会离职,会出错不是很靠谱,所以企业想要的是自动的故障转移程序(代替人), 那如果要写一个这样的程序,就要想明白一个问题:人是如何监控的?
程序有时候和人也是相似的,只要是程序就会有单点故障的问题,所以监控程序应该也是一个集群。

在这里插入图片描述
假如,当有三个监控程序监控一个redis的时候,如果这个redis挂了,可能因为网络阻塞延迟的原因,可能是1个或2个或3个都知道redis挂了,应该如何判定?把问题翻转一下:

在这里插入图片描述
也就是说一个redis有没有挂掉,是三个监控一起决策 还是 只需要一个监控决策就可以判定?
如果是需要三个监控者都需要给出redis挂掉的事情,这种是最精确的强一致性。但是也有可能其中一个监控者的网络延迟或者通信失败,会让高可用程序认为redis还活着,进而破坏了可用性。


为了提高可用性,降低对一致性的要求,让一部分监控者给出OK就可以判定redis是否挂了,关键是一部分是指几个呢?

如果1个监控者给出OK就能确定redis挂了,其他两个监控者没有给出OK,并且redis还活着,只能说明给出OK的监控者网络连接有问题。并且三个监控者可能会给出三个不同的决策 ,这种统计是不准确的(不够势力范围)。

这种情况下就会产生网络分区的问题,但是分区并不一定是坏事,具体要看业务的分区容忍性。比如Spring Cloud 服务注册发现中心Eureka集群注册同一种服务(购物车),Eureka集群中有的Eureka负载购物车服务有7台,有的有8台,有的有10台,数据是不一致的。但是不要紧,Consumer通过Eureka调用服务的时候,无论走的哪个Eureka,只要里面购物车服务能走通就可以了。

所以,这里要考虑的是,让一部分监控者给出OK后,另一部分监控者监控者不算数,给出ok的有几个监控者?

还是三个监控者,如果让其中2个给出OK才能确定redis挂了(势力范围为2),那么就需要其中两个监控者互相通信达成一致形成势力范围:
监控者A告诉监控者B自己发现redis挂了,监控者B也告诉监控者A也发现了redis挂了,A和B形成的势力范围为2,就可以直接把redis挂掉。但是监控者C发现redis没有挂 或者 C无法和AB通信 ,无法和AB达成一致,那么C的实例范围只有自己为1,所以C没有决策权。
因为之前给定势力范围为2,所以C是不算数的。

这样做的好处就是没有中间状态。

如果有四个监控者,给出ok的应该有几个监控者?

在这里插入图片描述
有ABCD四个监控者,假设需要势力范围为2就可以达成redis挂掉,那么就可能出现AB和CD都达成势力范围为2的情况,这样就又会出现网络分区的问题而得到两种不同的状态,所以需要把势力范围2改成势力范围3来解决问题。

如果有五个监控者,给出ok的应该有几个监控者?

在这里插入图片描述
如果是五个监控者,势力范围为3也可以解决网络分区的问题,即使其中两监控者达成了一致也只是势力范围2,没有达成势力范围3就不会生效。

因此得出结论:

  • 3个监控者,势力范围2生效。

  • 4个监控者,势力范围3生效。

  • 5个监控者,势力范围3生效。

并且得到公式:势力范围 =  n / 2 + 1  (过半!)

为什么集群使用奇数台?
因为3台和4台都只允许一台出现故障,但是4台出现故障的概率要大于3台出现故障的概率。
而5台和6台都只允许两台出现故障,6台出现故障的概率要大于5台出现故障的概率。
即可以降低风险,又可以节省资金。

在CAP原则中,这种集群方式强调的是 一致性可用性

主从复制演示

Redis使用默认的异步复制,其特点是低延迟和高性能。这也是redis使用弱一致性的原因,尽量减少对技术的整合,有助于维护redis快的特性。

首先创建三个redis的服务,分别为6379、6380、6381。

[root@z8524210 test]# pwd
/root/test
[root@z8524210 test]# cp /etc/redis/* ./						//因为做实验,所以拷贝三个实例的配置文件到当前目录
[root@z8524210 test]# ll
总用量 192
-rw-r--r--. 1 root root 62232 6月   8 22:31 6379.conf
-rw-r--r--. 1 root root 62231 6月   8 22:31 6380.conf
-rw-r--r--. 1 root root 62231 6月   8 22:31 6381.conf
[root@z8524210 test]#123456789

修改三个配置文件:

daemonize no								//关闭redis后台运行,方便观察前台日志
#logfile /var/log/redis_6381.log			//注释掉日志文件
appendonly no								//关闭aof123

删除三个redis实例的持久化文件

[root@z8524210 test]# cd /var/lib/redis/
[root@z8524210 redis]# ll
总用量 0
drwxr-xr-x. 2 root root 44 6月   8 10:49 6379
drwxr-xr-x. 2 root root  6 6月   8 22:28 6380
drwxr-xr-x. 2 root root  6 6月   8 22:28 6381
[root@z8524210 redis]# rm -rf ./* 					//删除并且新建目录
[root@z8524210 redis]# mkdir 6379
[root@z8524210 redis]# mkdir 6380
[root@z8524210 redis]# mkdir 6381
[root@z8524210 redis]# ll
总用量 0
drwxr-xr-x. 2 root root 6 6月   8 23:28 6379
drwxr-xr-x. 2 root root 6 6月   8 23:28 6380
drwxr-xr-x. 2 root root 6 6月   8 23:28 6381
[root@z8524210 redis]#12345678910111213141516

然后开启三个redis:

redis-server ~/test/6379.conf 
redis-server ~/test/6380.conf 
redis-server ~/test/6381.conf123

让6379为master,6380和6381为slave(手动):

####################################   进入6380实例   ######################################

127.0.0.1:6380> help SLAVEOF

  SLAVEOF host port
  summary: Make the server a replica of another instance, or promote it as master. Deprecated starting with Redis 5. Use REPLICAOF instead.
  since: 1.0.0
  group: server				//5.0 之前命令为slaveof ,5.0之后为replicaof
						
127.0.0.1:6380> 
###################################  查看6379日志  #########################################

2068:M 08 Jun 2020 23:40:14.963 * DB loaded from disk: 0.000 seconds
2068:M 08 Jun 2020 23:40:14.964 * Ready to accept connections
2068:M 08 Jun 2020 23:53:17.406 * Replica 127.0.0.1:6380 asks for synchronization			//和6380做同步
2068:M 08 Jun 2020 23:53:17.406 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'a153fbd8fadf46119151a7fa39333767409a2001', my replication IDs are 'c55ecf1cc1cab5ce382e05c10bc92bb7f84cb585' and '0000000000000000000000000000000000000000')
2068:M 08 Jun 2020 23:53:17.406 * Starting BGSAVE for SYNC with target: disk				//使用bgsave的方式持久化rdb文件
2068:M 08 Jun 2020 23:53:17.406 * Background saving started by pid 2380						//执行bgsave的子线程的pid
2380:C 08 Jun 2020 23:53:17.411 * DB saved on disk											//存储到磁盘
2380:C 08 Jun 2020 23:53:17.411 * RDB: 6 MB of memory used by copy-on-write					//使用写时复制
2068:M 08 Jun 2020 23:53:17.506 * Background saving terminated with success					//成功
2068:M 08 Jun 2020 23:53:17.506 * Synchronization with replica 127.0.0.1:6380 succeeded		

#################################   查看6380日志  ############################################

2092:S 08 Jun 2020 23:53:17.405 * Connecting to MASTER 127.0.0.1:6379						//连接到主机6379
2092:S 08 Jun 2020 23:53:17.405 * MASTER <-> REPLICA sync started							//主机和从机开始同步
2092:S 08 Jun 2020 23:53:17.405 * Non blocking connect for SYNC fired the event.
2092:S 08 Jun 2020 23:53:17.405 * Master replied to PING, replication can continue...		//连接相同
2092:S 08 Jun 2020 23:53:17.406 * Trying a partial resynchronization (request a153fbd8fadf46119151a7fa39333767409a2001:1).
2092:S 08 Jun 2020 23:53:17.409 * Full resync from master: 5b2483094a3175bfad7b03ee1310784cfa22b0d3:0
2092:S 08 Jun 2020 23:53:17.409 * Discarding previously cached master state.					//放弃以前的缓存
2092:S 08 Jun 2020 23:53:17.506 * MASTER <-> REPLICA sync: receiving 175 bytes from master	//从master传递过来175b
2092:S 08 Jun 2020 23:53:17.506 * MASTER <-> REPLICA sync: Flushing old data				//刷新以前的老数据
2092:S 08 Jun 2020 23:53:17.506 * MASTER <-> REPLICA sync: Loading DB in memory		//加载到内存
2092:S 08 Jun 2020 23:53:17.506 * MASTER <-> REPLICA sync: Finished with success		//圆满成功123456789101112131415161718192021222324252627282930313233343536

然后测试,从6379中存入数据,从6380也能取出:

#################################	6379写入数据	 #############################################

127.0.0.1:6379> KEYS *
(empty list or set)
127.0.0.1:6379> set k1 aaa
OK
127.0.0.1:6379> 

#################################	6380读取数据	 #############################################

127.0.0.1:6380> KEYS *
1) "k1"
127.0.0.1:6380> get k1							//从6379存入的数据从6380中也能取出。
"aaa"
127.0.0.1:6380> set k2 bbb						//但是在slave中,不能写入数据
(error) READONLY You can't write against a read only replica.
127.0.0.1:6380>1234567891011121314151617

这个时候还没有使用6381追随6379,先往6381中存入数据,然后追随6379,对比数据和日志会发现6381之前的老数据会被清理:

[root@z8524210 ~]# redis-cli -p 6381			//连接6381
127.0.0.1:6381> KEYS *
(empty list or set)
127.0.0.1:6381> set k5 ddd							//在6381中存入数据
OK
127.0.0.1:6381> GET k5
"ddd"
127.0.0.1:6381> REPLICAOF 127.0.0.1 6379		//然后追随
OK
127.0.0.1:6381> 
#################################  追随后,发现之前添加的k5消失了 #############################

127.0.0.1:6381> REPLICAOF 127.0.0.1 6379
OK
127.0.0.1:6381> KEYS *
1) "k1"
127.0.0.1:6381> get k1								//只有k1
"aaa"
127.0.0.1:6381> 

###################################   6379日志给出提示6381连接   ##############################

2068:M 09 Jun 2020 00:23:05.919 * Replica 127.0.0.1:6381 asks for synchronization
2068:M 09 Jun 2020 00:23:05.919 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'c61cd685404832e19aed90d0b03e32025ccd184a', my replication IDs are '5b2483094a3175bfad7b03ee1310784cfa22b0d3' and '0000000000000000000000000000000000000000')
2068:M 09 Jun 2020 00:23:05.919 * Starting BGSAVE for SYNC with target: disk
2068:M 09 Jun 2020 00:23:05.920 * Background saving started by pid 2792
2792:C 09 Jun 2020 00:23:05.922 * DB saved on disk
2792:C 09 Jun 2020 00:23:05.922 * RDB: 2 MB of memory used by copy-on-write
2068:M 09 Jun 2020 00:23:06.019 * Background saving terminated with success
2068:M 09 Jun 2020 00:23:06.019 * Synchronization with replica 127.0.0.1:6381 succeeded

###################################   6381日志   #############################################

2141:S 09 Jun 2020 00:23:05.807 * Before turning into a replica, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
2141:S 09 Jun 2020 00:23:05.807 * REPLICAOF 127.0.0.1:6379 enabled (user request from 'id=3 addr=127.0.0.1:33372 fd=7 name= age=225 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=44 qbuf-free=32724 obl=0 oll=0 omem=0 events=r cmd=replicaof')
2141:S 09 Jun 2020 00:23:05.918 * Connecting to MASTER 127.0.0.1:6379
2141:S 09 Jun 2020 00:23:05.918 * MASTER <-> REPLICA sync started
2141:S 09 Jun 2020 00:23:05.918 * Non blocking connect for SYNC fired the event.
2141:S 09 Jun 2020 00:23:05.919 * Master replied to PING, replication can continue...
2141:S 09 Jun 2020 00:23:05.919 * Trying a partial resynchronization (request c61cd685404832e19aed90d0b03e32025ccd184a:1).
2141:S 09 Jun 2020 00:23:05.920 * Full resync from master: 5b2483094a3175bfad7b03ee1310784cfa22b0d3:2545
2141:S 09 Jun 2020 00:23:05.920 * Discarding previously cached master state.
2141:S 09 Jun 2020 00:23:06.019 * MASTER <-> REPLICA sync: receiving 189 bytes from master
2141:S 09 Jun 2020 00:23:06.019 * MASTER <-> REPLICA sync: Flushing old data
2141:S 09 Jun 2020 00:23:06.019 * MASTER <-> REPLICA sync: Loading DB in memory
2141:S 09 Jun 2020 00:23:06.019 * MASTER <-> REPLICA sync: Finished with success12345678910111213141516171819202122232425262728293031323334353637383940414243444546

如果从机 6381 挂了,6379的日志会给出提示:

2068:M 09 Jun 2020 00:38:12.202 # Connection with replica 127.0.0.1:6381 lost.		//6381丢失了。1

如果在6381挂了的期间,6379写入了新数据,并且6381曾经追随过6379,会在6381启动的时候rdb快照文件的基础上增量更新。但是如果6381启动aof,那么就6379就会从新落rdb发送给6381:

###################################   6379添加数据   ##########################################
127.0.0.1:6379> KEYS *
1) "k1"
127.0.0.1:6379> set k2 asd
OK
127.0.0.1:6379> set k3 zhangsan
OK
127.0.0.1:6379> 


###################################   开启6381 并且指定master   ###############################

//没有开启aof
[root@z8524210 ~]# redis-server ~/test/6381.conf --replicaof 127.0.0.1 6379			
//开启了aof,会导致6379发送全量rdb给6381
[root@z8524210 ~]# redis-server ~/test/6381.conf --replicaof 127.0.0.1 6379	--appendonly yes 

###################################   6379日志   #############################################

2068:M 09 Jun 2020 00:43:51.930 * Replica 127.0.0.1:6381 asks for synchronization		//从机6381请求同步
2068:M 09 Jun 2020 00:43:51.930 * Partial resynchronization request from 127.0.0.1:6381 accepted. Sending 550 bytes of backlog starting from offset 3806.

###################################   6381查询数据   ##########################################

127.0.0.1:6381> KEYS *						//可以看到6379的增量数据
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6381>1234567891011121314151617181920212223242526272829

配置文件中配置主从复制:

  1. replicaof <masterip> <masterport> : 配置master的ip和端口

  2. masterauth <master-password> :访问master的密码

  3. replica-serve-stale-data yes : 在slave启动时,如果master中的数据量很大,在数据传输过程中,slave中的老的数据对外暴露,如果值为 no 需要同步完才能对外提供服务 。

  4. replica-read-only yes :yes表示alve只读;no表示slave支持写入。


在这里插入图片描述
repl-diskless-sync no : 如果为yes,表示直接走网络发送RDB。
6.
在这里插入图片描述
repl-backlog-size 1mb : 在master里会维护一个消息队列缓存临时写入的数据,salve如果挂掉后又启动了,master可能会有一个数据的增量,slave可以从新在master里面拿一份RDB恢复数据,也可以用RDB文件给master一个offset,从master队列中根据offset取出增量的数据恢复,这个配置的1mb就是设置这个队列的大小,如果master访问量大,把slave给出的offset对应的数据挤出,那么slave是无法恢复被挤出的数据的,这个时候就触发一个全量的RDB。
7. min-replicas-to-write 3:要求有三个健康的slave,master才能写成功。
8. min-replicas-max-lag 10:延迟小于min-replicas-max-lag秒的slave才认为是健康的slave

总结:
主从复制搭建,可以在slave中使用replicaof <ip> <port>命令追随master。
master对外提供全量读写,slave对外提供读。
slave挂了可以直接重启,如果以前有追随master记录,那么就不会发生全量rdb。但是开启了aof就一定会发生全量rdb传输。
那么master挂了怎么办? 答案:哨兵机制。

哨兵机制演示

通过之前的主从复制可以发现,master 的日志能够显示出slave的 ip 和 port , 也就是说 master 能够知道slave的ip和端口。

如果master挂掉了,可以使用手动切换slave为新的master,也可以使用哨兵机制:

手动切换,master挂掉之后,让6380成为新的master,6381从新追随6380:

###################################   master挂掉后slave的日志   ###############################

2105:S 09 Jun 2020 10:54:03.246 # Error condition on socket for SYNC: Connection refused
2105:S 09 Jun 2020 10:54:04.254 * Connecting to MASTER 127.0.0.1:6379
2105:S 09 Jun 2020 10:54:04.254 * MASTER <-> REPLICA sync started
2105:S 09 Jun 2020 10:54:04.254 # Error condition on socket for SYNC: Connection refused
2105:S 09 Jun 2020 10:54:05.260 * Connecting to MASTER 127.0.0.1:6379
2105:S 09 Jun 2020 10:54:05.260 * MASTER <-> REPLICA sync started
2105:S 09 Jun 2020 10:54:05.260 # Error condition on socket for SYNC: Connection refused
2105:S 09 Jun 2020 10:54:06.267 * Connecting to MASTER 127.0.0.1:6379

###################################   6380独立   #############################################

127.0.0.1:6380> REPLICAOF no one				//6380执行命令,切端和6379的联系
OK

###################################   6381追随6380   #########################################

127.0.0.1:6381> REPLICAOF 127.0.0.1 6380				//把追随6379改为6380
OK
127.0.0.1:6381> 

###################################   6380日志   #############################################

2105:M 09 Jun 2020 10:55:08.609 * Replica 127.0.0.1:6381 asks for synchronization
2105:M 09 Jun 2020 10:55:08.609 * Partial resynchronization request from 127.0.0.1:6381 accepted. Sending 0 bytes of backlog starting from offset 3881.

###################################   6381日志   #############################################

2120:S 09 Jun 2020 10:55:08.535 * REPLICAOF 127.0.0.1:6380 enabled (user request from 'id=4 addr=127.0.0.1:36690 fd=8 name= age=2689 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=44 qbuf-free=32724 obl=0 oll=0 omem=0 events=r cmd=replicaof')
2120:S 09 Jun 2020 10:55:08.608 * Connecting to MASTER 127.0.0.1:6380
2120:S 09 Jun 2020 10:55:08.608 * MASTER <-> REPLICA sync started
2120:S 09 Jun 2020 10:55:08.608 * Non blocking connect for SYNC fired the event.
2120:S 09 Jun 2020 10:55:08.609 * Master replied to PING, replication can continue...
2120:S 09 Jun 2020 10:55:08.609 * Trying a partial resynchronization (request cea42e5c3400d17502d0f878dc7b24655de0045a:3881).
2120:S 09 Jun 2020 10:55:08.609 * Successful partial resynchronization with master.
2120:S 09 Jun 2020 10:55:08.609 # Master replication ID changed to e5bf1c2a640bf80903102d748d9c7328182db2bb
2120:S 09 Jun 2020 10:55:08.609 * MASTER <-> REPLICA sync: Master accepted a Partial Resynchronization.1234567891011121314151617181920212223242526272829303132333435363738

哨兵自动切换演示:

先把之前的redis都停掉。

建立三个配置文件26379.conf,26380.conf,26381.conf :

port 26379
sentinel monitor mymaster 127.0.0.1 6379 212

port 26380
sentinel monitor mymaster 127.0.0.1 6379 212

port 26381
sentinel monitor mymaster 127.0.0.1 6379 212

启动三个redis并且建立主从复制:

[root@z8524210 test]# redis-server 6379.conf
[root@z8524210 test]# redis-server 6380.conf --replicaof 127.0.0.1 6379
[root@z8524210 test]# redis-server 6381.conf --replicaof 127.0.0.1 6379123

启动三个哨兵:

###############################  启动26379哨兵  #######################################

[root@z8524210 test]# redis-server 26379.conf --sentinel

##############################   26379日志文件   #######################################

5946:X 09 Jun 2020 15:10:35.991 # +monitor master mymaster 127.0.0.1 6379 quorum 2
5946:X 09 Jun 2020 15:10:35.993 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
5946:X 09 Jun 2020 15:10:35.993 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379

/**
*	哨兵能自动发现master上面有哪些slave,因为master被slave追随的时候master就能收到slave的信息,
*	所以哨兵监控master就能知道有哪些slave。
*	但是底层是如何实现的呢?
*/123456789101112131415

###############################  启动26380哨兵  ########################################

[root@z8524210 test]# redis-server 26380.conf --sentinel

##############################   26380日志文件   #######################################

6054:X 09 Jun 2020 15:20:49.154 # +monitor master mymaster 127.0.0.1 6379 quorum 2
6054:X 09 Jun 2020 15:20:49.155 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6054:X 09 Jun 2020 15:20:49.155 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
6054:X 09 Jun 2020 15:20:49.713 * +sentinel sentinel de23d84c56c111dda0e7821065b8c39b2c591b7e 127.0.0.1 26379 @ mymaster 127.0.0.1 6379

/**
*	26380哨兵可以发现6379master 和两个 slave ,并且还发现了 26379 哨兵,并且26379哨兵的日志也显示
*	发现了26380的提示。
*/123456789101112131415

###############################  启动26381哨兵  ###########################################

[root@z8524210 test]# redis-server 26381.conf --sentinel

##############################   26381哨兵 日志   ###########################################

6133:X 09 Jun 2020 15:27:11.952 # +monitor master mymaster 127.0.0.1 6379 quorum 2
6133:X 09 Jun 2020 15:27:11.953 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ mymaster 127.0.0.1 6379
6133:X 09 Jun 2020 15:27:11.953 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6379
6133:X 09 Jun 2020 15:27:12.142 * +sentinel sentinel 2dc647ce306b59f3e474a4d3cd2f751289f851cc 127.0.0.1 26380 @ mymaster 127.0.0.1 6379
6133:X 09 Jun 2020 15:27:12.691 * +sentinel sentinel de23d84c56c111dda0e7821065b8c39b2c591b7e 127.0.0.1 26379 @ mymaster 127.0.0.1 6379

/**
*	26381哨兵可以发现6379master 和两个 slave ,并且还发现了 26379 哨兵和26380哨兵,并且26379和26380的日志
*	也发现了26381的提示。
*/12345678910111213141516

如果这个时候master 6379 挂了,哨兵经过一个时间片后,会从slave 6380 和 6381 之中选举出新的master:

##############################   26379哨兵 日志   ###########################################
5946:X 09 Jun 2020 15:33:14.711 # +sdown master mymaster 127.0.0.1 6379					//提示master 6379 挂了
5946:X 09 Jun 2020 15:33:14.770 # +odown master mymaster 127.0.0.1 6379 #quorum 2/2		//投票数量达到2
5946:X 09 Jun 2020 15:33:16.240 # +failover-end master mymaster 127.0.0.1 6379			//故障转移
5946:X 09 Jun 2020 15:33:16.240 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380		//选举出新的master 6380
5946:X 09 Jun 2020 15:33:16.240 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
5946:X 09 Jun 2020 15:33:16.240 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
5946:X 09 Jun 2020 15:33:46.266 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380

/**
*	从新选取master后,之前的master被降级为slave
*/123456789101112

6380 master可以读写,6381只能读取

##############################   6380    ################################################

127.0.0.1:6380> KEYS *
1) "k1"
127.0.0.1:6380> get k1 
"zhangsan"
127.0.0.1:6380> set k2 aaaa
OK
127.0.0.1:6380> 

##############################   6381   ################################################

127.0.0.1:6381> get k2
"aaaa"
127.0.0.1:6381> set k3 eee
(error) READONLY You can't write against a read only replica.
127.0.0.1:6381>1234567891011121314151617

在回去看之前写的哨兵配置文件,会发现配置文件被哨兵自动修改:

[root@z8524210 test]# cat 26379.conf 
port 26379
sentinel myid de23d84c56c111dda0e7821065b8c39b2c591b7e
# Generated by CONFIG REWRITE
dir "/root/test"
protected-mode no
sentinel deny-scripts-reconfig yes
sentinel monitor mymaster 127.0.0.1 6380 2
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel known-replica mymaster 127.0.0.1 6381
sentinel known-replica mymaster 127.0.0.1 6379
sentinel known-sentinel mymaster 127.0.0.1 26380 2dc647ce306b59f3e474a4d3cd2f751289f851cc
sentinel known-sentinel mymaster 127.0.0.1 26381 5c4932f02396567694b01a54d1ddf11ff65b89db
sentinel current-epoch 1
[root@z8524210 test]# 

/**
*	可以发现之前自己写的只有两行配置文件,分别为:
*	port 26379
*	sentinel monitor mymaster 127.0.0.1 6379 2
*	但是因为master 6379 挂掉后,哨兵自动选取master,并且修改了自身的配置文件,把
*	sentinel monitor mymaster 127.0.0.1 6379 2 
*	改为
*	sentinel monitor mymaster 127.0.0.1 6380 2
*	并且还增加了一些其他的信息
*/123456789101112131415161718192021222324252627

哨兵之间通信的原理?

在这里插入图片描述

哨兵使用了redis自带的发布订阅功能,哨兵会去监控master拿到两个slave分别是谁,同时在存活的master开启发布订阅发现其他的哨兵。

127.0.0.1:6380> PSUBSCRIBE *
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "*"
3) (integer) 1
1) "pmessage"
2) "*"
3) "__sentinel__:hello"
4) "127.0.0.1,26379,de23d84c56c111dda0e7821065b8c39b2c591b7e,1,mymaster,127.0.0.1,6380,1"
1) "pmessage"
2) "*"
3) "__sentinel__:hello"
4) "127.0.0.1,26381,5c4932f02396567694b01a54d1ddf11ff65b89db,1,mymaster,127.0.0.1,6380,1"
1) "pmessage"
2) "*"
3) "__sentinel__:hello"
4) "127.0.0.1,26380,2dc647ce306b59f3e474a4d3cd2f751289f851cc,1,mymaster,127.0.0.1,6380,1"
1) "pmessage"
2) "*"12345678910111213141516171819


https://blog.csdn.net/xi_rurensheng/article/details/106610813