1.当键为字符串类型的时候,如果该键值对设置了过期时间,此时再对该键进行set操作,那么将会覆盖已有的键值对,并且会清除该键值对的过期时间。
2.setex命令不仅是原子化的操作,而且会减少一次网络通信的时间;
3.redis不支持对二级数据结构内部元素的过期时间的设置,比如不能为列表中的某个元素设置过期时间;
4.使用keys命令的注意点:①可以在一个不对外提供服务的从节点上进行keys命令,这不会影响主节点对外提供的服务,但是会影响主从节点的复制功能;
②当确认redis数据库中保存的键值对不多时可以执行该命令;③如果确实要进行遍历,可以使用scan命令进行,其会渐进式的遍历所有键。
5.scan命令能够渐进式的遍历当前库中所有的键值对,但是如果遍历期间有键的添加和删除,那么就会出现新的键不一定被遍历到,其职能保证当前遍历期间
所有的键都能被遍历到,而不能保证添加的键以及还未遍历的并且被移除的键被遍历到。
6.redis逐渐弱化多个数据库的原因:
·Redis是单线程的。如果使用多个数据库,那么这些数据库仍然是使用一个CPU,彼此之间还是会受到影响的。
·多数据库的使用方式,会让调试和运维不同业务的数据库变的困难,假如有一个慢查询存在,依然会影响其他数据库,这样会使得别的业务方定位问题非常的困难。
·部分Redis的客户端根本就不支持这种方式。即使支持,在开发的时候来回切换数字形式的数据库,很容易弄乱。
7.flushdb和flushall可以非常方便的清除当前数据库中的数据和清除所有数据库中的数据,但是其也存在两个问题:
①这两个命令会将所有数据都清除,一旦操作,后果不堪设想,其可以通过rename-command配置进行命令的重命名;
②由于redis的单线程模型,因而一旦数据库中数据量较大,那么这两个命令的执行将会阻塞其他命令的执行。
8.慢查询日志使用时的注意点
①慢查询日志的保存条数对于高并发的情况应该适当的加长,线上设置为1000条比较合适,对于超时时间可根据实际业务情况进行设置,对于业务流量比较高的情况,
默认超时时间设置为1ms时,其OPS不到1000,因而线上设置为1ms比较合适
②慢查询日志只是记录了一个命令执行的时间,其不包括网络请求与在队列中等待的时间;
③当慢查询日志比较多的时候,可以通过slowlog get命令获取慢查询日志并且将其持久化到数据库中
9.redis-cli后相关参数说明:
①-r(repeat)选项代表将命令执行多次,如redis-cli -r 5
②-i选项用于指定重复执行的命令的时间间隔,单位是秒,必须与-r选项一起使用,如redis-cli -r 5 -i 1
③-x选项代表从标准输入(stdin)读取数据作为redis-cli的最后一个参数,如echo "world" | redis-cli -x set hello
④-c选项用于标识当前是用于登录集群的
⑤-a选项用于输入redis的密码
⑥--scan选项和--pattern选项用于扫描指定模式的键,相当于使用scan命令
⑦--slave命令将当前客户端模拟为当前redis节点的从节点
⑧--rdb选项会请求redis实例生成并发送rdb持久化文件,并保存在本地
⑨--pipe命令用于将redis通信协议格式的命令发送给redis批量执行
⑩--bigkeys选用使用scan命令对redis的键进行采样,发现其中内存占用比较大的键值。
⑪--eval选项用于执行指定的lua脚本
⑫--latency选项用于测试客户端到目标redis的网络延迟
⑬--stat选项可以实时获取redis中重要的统计信息
⑭--raw和--no-raw命令用于指定返回结果的格式
10.redis-server --test-memory中--test-memory参数是用于测试机器内存是否足够redis使用的,但是其是通过快速占满机器内存来达到测试的目的的
11.pipeline和原生批量命令的区别:
①原生批量命令是原子的,pipeline是非原子的;
②原生批量命令是一个命令对应多个key,pipeline支持多个命令;
③原生批量命令是redis服务端支持实现的,而pipeline需要服务端和客户端的共同实现;
这里需要注意的是pipeline中组装的命令数量不能没有节制,如果命令组装过多,那么将会增加客户端的等待事件,并且会增加一定的网络阻塞。
可以将以此包含大量命令的pipeline拆分成多次较小的pipeline来完成。
12.redis中使用multi和exec命令来执行简单的事务,当执行multi之后开始输入想要执行的命令,当命令都输入完成之后就执行exec命令,redis就会将
这之间输入的命令一次性执行完成,而如果想取消事务,则在输入multi之后不执行exec,而是执行discard即可。当想要在执行事务的时候想要某个键没有
被其他客户端修改过的时候,可以使用watch命令,首先执行watch key,redis就会监控该key,然后执行multi并且输入命令,最后执行exec,在这之间如果
有另外的客户端执对该key执行了修改工作,那么该事务将会回滚。
这里还需要说明的一点是,redis对于事务的回滚是有条件的,当事务中的命令是命令写错了(比如名称写错了),对于这种在编译器就可以检查出的异常在执行的
时候整个事务都会回滚,但是如果是参数错误,对于这种运行期的错误redis将不会回滚,已经执行了的命令其结果将保留,而未执行的命令其也不会再执行。
13.redis中eval和evalsha都是用来执行lua脚本的,但是eval命令是直接发送lua脚本的,而evalsha是发送一个之前执行过的lua脚本的sha校验码的,
使用evalsha命令可以减少lua脚本网络发送的开销。
14.使用如下命令可以将lua脚本文件加载到redis中,并且其会返回生成的sha校验码:
redis-cli script load "$(cat lua_get.lua)"
然后调用evalsha命令可以执行该脚本中的内容。
15.使用redis.call命令调用get命令:
eval 'return redis.call("get", KEYS[1])' 1 hello
16.redis.call和redis.pcall使用方式是一样的,但是其区别在于redis.call命令在执行lua脚本是如果报错,那么其将不会继续执行下去,而redis.pcall
则会继续往下执行。
17.redis使用lua脚本的优点:
①lua脚本在redis中是原子执行的,在使用过程中无法执行其他命令;
②lua脚本可以帮助开发和运维人员开发自己的命令,并且将这些命令存储到redis中达到复用的效果;
③lua脚本可以一次性将多个命令打包,从而减少网络开销
18.使用lua脚本时需要注意的点有:
①lua脚本在执行的时候其他命令将不会执行;
②script kill命令对于正在执行读操作的lua脚本有效,但是对于正在执行写操作的lua脚本无效,此时只能通过shutdown save命令停掉服务;
③lua脚本中数组的下标是从1开始的,而不是从0开始的
19.bitmap是一种数据结构,但是redis内部实际上是使用字符串来保存二进制位数据的;尽管如此,redis中提供了一套操作位的命令。
20.对于用户每天的访问记录,可以使用二进制位的方式来保存每个用户的访问记录。可以将每个用户的id映射到位数组中的某一位,一般是按照顺序来的,
如果用户当天进行了访问,那么就将对应的位设置为1,否则设置为0。而对于用户的访问统计比如月活跃量则可以通过位数组的或操作来统计,如此等等。
但是需要注意的是,这种方式需要对每一个用户都声明一个位数组位,如果存在大量的僵尸用户,那么这个数组中大部分数据的值都是0,这将造成一定的
浪费,此时,使用集合将优于位数组的使用,因为集合只需要存储当前活跃的用户id即可。
21.输入缓冲区过大的原因:
①redis处理命令的速度低于客户端输入命令的速度,并且客户端传入的键中有很多bigkey;
②redis发生阻塞,导致客户端命令都积压在输入缓冲区。
22.监控redis客户端缓冲区大小的方式:
①通过client list命令查看当前客户端的链接情况,根据其qbuf和qbuf-free查看当前使用的缓冲区和剩余的缓冲区;
②通过info clients命令查看当前使用了的最大输入缓冲区:client_biggest_input_buf;
说明:这两种方式各有利弊,第一种方式当客户端较多时效率较低,存在阻塞redis的可能,但是其可以精确了解每个客户端的情况;第二种方式只能查看当前
使用的最大输入缓冲区,效率较高,但是其不能定位到具体是哪个客户端输入缓冲区使用最多。
23.redis的输出缓冲区由两部分组成:固定缓冲区和动态缓冲区。固定缓冲区是一个字节数组,用于返回比较小的对象,而动态缓冲区则是一个链表组成,
主要返回一些比较大的对象。
redis输出缓冲区的配置:client-output-buffer-limit
这里class有三种类型:normal、slave和pubsub,分别表示一般缓冲区、主从服务器缓冲区和订阅缓冲区。hard limit如果设置了,那么当缓冲区达到
这个数值的时候客户端将被立即停止。soft limit和soft seconds则表示当输出缓冲区大小超过soft limit,并且时间超过soft seconds时,那么
客户端将会被立即关闭。
24.监控输出缓冲区的方式:
①通过client list查看当前链接的客户端情况,其obl表示当前使用的固定缓冲区的大小,oll表示当前使用的动态缓冲区的链表长度,omem表示当前使用的总
字节数;
②通过info clients命令查看最大输出缓冲区链表的长度;
说明:这里这两种监控方式和输入缓冲区的基本一致;
25.redis预防输出缓冲区异常的方式:
①设置阈值,超过阈值及时处理;
②限制普通客户端的输出缓冲区的大小,具体配置如:client-output-buffer-limit normal 20mb 10mb 120;
③适当增大slave缓冲区的大小,因为slave缓冲区如果溢出,就会重连,这将产生更大的资源消耗;
④限制容易让输出缓冲区溢出的命令,例如高并发下的monitor命令;
⑤及时监控内存,一旦发现内存抖动频繁,可能就是输出缓冲区过大。
26.client list中client的flag属性标识了当前客户端的类型:N表示普通客户端,S表示slave客户端,O表示正在执行monitor命令的客户端,M表示
当前客户端是master客户端,b表示当前客户端正在等待阻塞事件
27.client list中各个参数的总结:
id:客户端链接的id
addr:客户端链接的ip和端口
fd:socket链接描述符
name:客户端链接名
age:客户端链接存活时间
idle:客户端链接空闲时间
flags:客户端链接标识
db:当前客户端正在使用的数据库索引下标
sub/psub:当前客户端正在订阅的频道或者模式数
multi:当前事务中已执行的命令个数
qbuf:输入缓冲区总容量
qbuf-free:输入缓冲区剩余容量
obl:固定缓冲区的长度
oll:动态缓冲区链表的长度
omem:固定缓冲区和动态缓冲区的总容量
events:文件描述符事件(r/w):r和w分别代表客户端套接字可读和可写
cmd:当前客户端最后一次执行的命令
28.monitor命令可以通过当前客户端监控其他客户端执行的命令,但是该命令在生产环境要慎用,因为每个客户端都有其输入输出缓冲区,如果
当前并发量非常高,那么执行monitor命令的客户端的输出缓冲区可能很快就会溢出。
29.主从节点断开之后主节点和从节点会打印相应日志,并且主节点会继续响应命令,并将写入命令存入积压缓冲区中,默认最大存储量为1M,从节点断开
后首先打印相关日志,然后尝试重连,重连之后会将自己的同步偏移量发送给主节点,对比主节点的runid和偏移量,查看从该偏移量之后的数据是否还在积压缓冲区
中,如果在就从相应的偏移量处开始同步,否则进行全量更新。
30.主节点在处理写命令的时候会将处理结果直接返回给客户端,而同步工作则是异步完成的,其不等待复制完成之后再返回。
31.使用主从节点进行数据读写分离时,主要存在三个问题:①主从节点数据不同步;②在从节点中读取到过期数据;③从节点异常。导致主从节点不同步
的原因在于主节点与从节点进行数据同步时是异步的,因而当并发量较大,从节点相对于主节点势必有一定的延迟,因而对于数据比较敏感的客户端处理比较
麻烦;在从节点中会读取到过期数据的原因在于为了保证主从节点数据一致,从节点不会自动删除过期键等数据,而是通过主节点判断是否过期执行del命令
之后将该命令同步到从节点来删除,因而在从节点中读取数据时可能会读到过期数据,这个问题在3.2版本已经修复;由于读写分离时数据读取是指定了相应
的从节点的,因而当从节点发生异常时需要从代码里控制重新连接另一个节点。
redis提供了集群的功能,对于主从节点存在的上述三个问题,集群都能够很好的解决。
32.对于主节点和从节点的配置有些需要保持一致,但也有不能保持一致的。比如从节点开启AOF,而主节点不开启AOF持久化。而另外一些配置,比如
maxmemory和hash-max-ziplist-entries等配置则尽量保持一致,因为对于最大可使用内存如果不一致,内存较小的节点就可能按照maxmemory-policy
进行内存溢出控制;对于hash-max-ziplit-entries不一致的情况,虽然主从节点保存的数据是一致的,但是其使用的内存是大不相同的。
33.由于全量复制是一个非常消耗资源的操作,因而如何规避全量复制则显得比较重要,以下是规避全量复制的几种策略:
①第一次进行复制:当第一次建立主从关系的时候全量复制不可避免,但是当数据量比较大的时候进行全量复制则会挤占其他操作的资源,因而应尽量避免
在操作高峰期建立主从关系;
②运行id不匹配:当主节点由于故障而重启之后,由于从节点发现主节点的运行id发生了变化,其会认为这是一个新的主节点,因而会进行全量复制,处理方式
有是那种:在配置文件中指定主节点的运行id、运用哨兵或集群当主节点宕机的时候提升其他从节点为主节点;
③复制积压缓冲区不足:当从节点宕机的时候,其会发送当前的复制偏移量与主节点进行比对,但是如果主节点的积压缓冲区的大小不足以保存太大的复制偏移量
差的数据时,从节点就会进行全量复制,这种时候需要根据从节点宕机时长来提升复制积压缓冲区的大小。
34.复制风暴指的是大量从节点对同一主节点或同一台机器的多个主节点短时间内的大量全量复制过程。
35.LRU算法指的是:redis内部保存了一定的过期键,如果对每个键都按时删除将会消耗大量内存,因而采用了两种策略对过期键进行删除:
①懒惰删除:当客户端获取一个键的时候,redis会校验这个键是否过期,如果过期则会将其删除;
②定时任务删除:redis每秒钟运行10次键定时删除策略,该频率在配置文件中通过hz属性配置,每次运行时随机取20个键,删除其中的过期键,并统计
如果其中有超过25%的键过期,那么会继续执行抽样策略,知道低于25%的键过期或者是获取超时(超时时间是25毫秒),如果是获取超时,那么就会以
快模式删除,快模式和慢模式删除策略是一样的,只不过是超时时间是1毫秒,并且2秒内只运行一次。
36.高并发场景下建议使用长度小于36个字节的键名称,因为当键长度小于36个字节的时候redis会使用embstr类型来编码键字符串,其类似于一个c字符串,
而当字节数超过36个字节的时候,redis会使用raw类型来保存键,raw类型是一个redisObject类型的字符串对象,此时redis需要进行相应的内存分配等
操作。
37.对于值对象,如果其比较大,可以采用两种方式解决:序列化和json。在进行序列化的时候需要确认对象中哪些字段是需要进行缓存的,除去不经常访问的
字段有助于节省内存空间,并且在序列化工具的选择上也需要选择效率和压缩比较高的工具,比如protostuff和kryo。对于使用json保存的方式,其存储空间
相对于真实的对象使用对象是增大了的,但是可以使用一些压缩工具进行压缩,比如gzip,其压缩率可达到60%,但是比较好用的是Google的snappy,其压缩率
和压缩效率远高于gzip。
38.redis使用整数对象池技术来处理整数对象共用的问题,redis中只在整数对象池中保存了0-9999这一万个整数。这里需要注意的是redis只对整数类型的数据
进行了对象共用的技术,并且对象共享技术在设置了maxmemory和lru算法的时候是不生效的,因为lru算法需要获取对象的最后访问时间,如果进行了共享,那么其
最后访问时间也是共享的,此时就无法对其使用lru算法。
39.在数据存储的时候,一般使用简单的字符串或者是对象类型将会比较消耗内存,进行内存优化的一种方式是通过将这些数据存储在hash表中,将其设置的key
设置为hash表的key,值作为hash表的值,并且很重要的一点是要保证存储的数据的键值对数量不超过hash-max-ziplist-entries(一般是1000个),并且
其值的大小不超过hash-max-ziplist-value的大小,使其使用ziplist进行数据存储,否则将得不偿失,如果键值对数量数量较大,则可以使用多个hash表
进行存储。
这里需要进行说明的是:①这种方式节省内存的原因是使用了ziplist作为存储结构,因而一定要保证其符合以该数据结构存储的条件;②设置的最大键值对数量
尽量不要超过1000,以为ziplist进行数据存储虽然节省内存,但是其对数据的插入和查询的消耗较高;③使用这种方式进行节省内存的时候,如果值的大小越小,
节省的内存就月明显。
使用hash的ziplist存储时需要注意的点有:①客户端需要预估键的规模,并且设计键的分组规则,加重了客户端的开发成本;②使用这种算法之后将无法使用
超时和LRU算法自动删除过期键,需要手动控制删除;③对于大对象,比如大小为1kb以上的对象,使用hash-ziplist将得不偿失。
40.使用ziplist+hash存储数据之后可以手动维护一个hash表,其中存储了过期时间,然后在客户端使用hscan命令定时扫描并删除过期键。
41.redis主从模式有两个优点:①主节点出现故障的时候从节点可以顶上来;②从节点可以扩展主节点的读能力,分担主节点的压力。
42.redis使用sentinel的主要目的有两个:①在主从模式中,如果主节点挂了,那么从节点是无法自动升级为主节点的,需要手动升级;②主节点挂了之后,
虽然可以将从节点升级为主节点,但是由于主从节点的ip地址是不一致的,这是就需要客户端更新其存储的服务端地址,这在很多情况下是不允许的。
43.redis的sentinel(哨兵)是一群sentinel节点的集合和相应的主从节点,在sentinel中维护了主节点和从节点的相关从属关系,sentinel会定时检查
主节点是否是正常的,如果主节点发生异常,那么首先检测到的sentinel会发送消息给其余的sentinel以求协助确认当前主节点是否是可用的,如果多数sentinel
都认为当前主节点是不可用的时候sentinel就会发送slaveof no one给某个从节点,然后发送slave of "new master"给其余的从节点和之前的主节点,
让这些节点称为新的主节点的从节点,通过这种方式redis可以达到节点的高可用性。
44.redis的sentinel也是一些redis节点,但是他们不存储数据,而是只能发送一部分命令。
45.redis的sentinel有两点需要说明:
①在生产关系中,redis的sentinel应该配置在不同的机器上;
②redis的sentinel与普通的节点没有任何区别,只是添加了一些sentinel节点对其进行监控;
46.redis的sentinel配置说明:
①sentinel monitor
表示当前sentinel监控的节点名称,ip,端口和当主节点宕机时最终需要多少个sentinel确认之后才将从节点升级为主节点,(这里建议quorun的值设置
为sentinel节点总数的一般加一),并且quorum还与sentinel领导者的选举有关,选举领导者的时候必须要有max(quorum, num(sentinels) / 2 + 1)
个sentinel节点参与选举。
②sentinel down-after-milliseconds
表示当前sentinel在向其监控的主节点,相关从节点和其余sentinel节点发送消息之后times时间内没有得到回复,那么当前sentinel就会认为其不可达,
这个值设置得越宽松,那么节点故障不可达的时间就越长,如果这个值设置得越短,那么判断节点是否不可达可能会产生误判。
③sentinel parallel-syncs
该配置表示如果主节点不可达,在选举出新的主节点之后,其余从节点会对新的主节点发起复制操作,这里的参数配置了同一时期有多少个从节点可以对主节点进行
复制,如果设置为1,则表示从节点会依次对主节点进行复制,该值需要合理进行设置,设置多了会增加主节点的磁盘开销。
④sentinel failover-timeout
redis故障转移的时间
⑤sentinel auth-pass
如果主节点设置了密码,该配置则指定了主节点的密码
⑥sentinel notification-script
该配置的作用是在redis故障转移期间,当一些警告级别的事件(-sdown:客观下线,-odown:主观下线)发生时,会出发对应路径的脚本,并向脚本发送相应
事件的参数。该脚本可用作在故障转移的时候发生警告级别事件时发送短信或者邮件以通知相关人员。
⑦sentinel client-reconfig-script
该配置会在每次故障转移完成之后执行对应路径下的相关脚本,并且可以传递故障转移结果的相关参数。相关的参数如下:
sentinel节点的角色,分别为leader和observer,leader表示当前sentinel是领导者,observer表示当前sentinel是其他节点;
这里需要说明的有两点:1.⑥和⑦中的脚本必须有可执行权限,并且以#! /bin/sh开头;2.redis规定执行脚本你的时间最多不超过60s,如果超过将被杀掉;
3.如果脚本以exit 1结束,那么其稍后会再次尝试执行,如果是以exit 2或更高的值结束,那么其不会进行重新执行,正常是以exit 0结束;4.如果运维的
sentinel比较多,那么建议不要使用脚本的方式来通知,这样会增加运维的成本。
47.sentinel可以支持动态的更改设置参数,设置的命令为sentinel set
sentinel set mymaster quorum 2
sentinel set mymaster down-after-milliseconds 30000
sentinel set mymaster failover-timeout 360000
sentinel set mymaster parallel-syncs 2
sentinel set mymaster notification-script /opt/xx.sh
sentinel set mymaster client-reconfig-script /opt/xx.sh
sentinel set mymaster auth-pass masterPassword
需要注意的还是动态设置这些参数只会对当前sentinel有效,并且如果执行成功,其会立即刷新配置文件。
48.sentinel的部署建议
①sentinel节点不应该只部署在同一台“物理”机器上
这是因为在同一台机器上时,所有的sentinel节点都将受到这一台机器的硬件限制,如果硬件损坏,那么所有的节点都将受到影响,为了真正实现sentinel
的高可用,尽量将其部署在不同的机器上。
②部署至少三个且奇数个sentinel节点
至少部署三个节点的原因是为了保证sentinel在判断主节点或其他sentinel节点损坏时的准确性;而部署奇数个节点的原因是sentinel在判定节点是否损坏
时需要至少一半加一个sentinel节点都认定其处于损坏状态,奇数个可以节省一个sentinel节点。
③只使用一套sentinel节点监控多个主节点还是使用多套sentinel节点监控多个主节点?
使用一套sentinel节点监控多个主节点的优点在于其可以节约sentinel节点的资源,而缺点在于如果sentinel节点损坏,那么这些主节点将都会受到影响,并且
当主节点配置过多时,sentinel节点将会占用一定的带宽;使用多套sentinel节点的有点则为其损坏不会影响其他的主节点,并且其节点带宽只与当前主节点有关,
但其缺点则为消耗了多个sentinel节点的资源。
一般在同一业务类型中可以使用同一套sentinel监控多个主节点,如果在不同的业务类型中,则建议使用多套sentinel节点监控多个主节点。
49.sentinel会每隔10s向主节点发送info replication命令,发送该命令的主要作用有三个:
①sentinel可以直接通过主节点获取主从节点的拓扑结构信息;
②当有新的从节点加入进来之后sentinel可以通过该命令更新节点的拓扑结构;
③当进行故障转移时,sentinel可以通过该命令获取新的主从结构;
50.sentinel会订阅数据节点的sentinel:hello频道,并且每隔2s向该数据节点发送其对主节点的判断和当前sentinel节点的信息。订阅该频道的目的
主要有两个:
①发现新的sentinel节点;②sentinel之间交换主节点的状态,作为后面客观下线和领导者选举的依据。
51.sentinel每隔1s会向主节点,从节点和其余sentinel节点发送ping命令,以此来确认其余节点是否可达。
52.主观下线:sentinel会向主节点,从节点和其余sentinel节点发送ping命令,当这些节点超过down-after-milliseconds没有进行回复的话,当前
sentinel节点就会主观的认为该节点处于下线状态。
53.客观下线:如果当前sentinel节点判定某个主节点处于下线状态时,其会向其余的sentinel节点发送sentinel is-master-down-by-addr命令,以获取
其余节点对该主节点是否下线的判断,当超过
54.sentinel选举领头sentinel的规则:当某个sentinel发现主节点处于主观下线状态,那么其就会向其他的sentinel节点发送is-master-down-by-addr
命令,以确认当前主节点处于下线状态。如果当前sentinel收到超过半数的sentinel都认为当前主节点已下线,那么当前sentinel就会将自己的配置纪元自增
一位,并且其会向其他的sentinel继续发送is-master-down-by-addr命令,以向其请求将自己设置为领头sentinel,如果当前sentinel收到回复称收到
请求的sentinel的配置纪元和当前sentinel的相同,并且其返回的运行id和当前sentinel的运行id相同,那么当前sentinel就会被设置为目标sentinel的
局部领导者,当某个sentinel被超过半数的sentinel选举为领导者之后,那么该sentinel将会被设置为领导者。如果没有选举出领导者,那么一段之后会再次
进行选举,直到选出领导者,领导者将会对主节点进行故障转移操作。