2 Star 6 Fork 1

Bob/interviewGuide

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
docs
ArrayList.md
BATInterview.md
CodingInterviews.md
HTTP.md
HashMap.md
JVMBook.md
JavaBasic.md
JavaJVM.md
JavaMultiThread.md
Kafka.md
MySQLBook1.md
MySQLNote.md
MySQLOptimize.md
MySQLWork.md
Nginx.md
RedisBasic.md
RedisBook1.md
RedisBook2.md
RedisDataStruct.md
RedisStore.md
RedisUserful.md
SystemDesign.md
ZooKeeper.md
bookRecommend.md
idgenerator.md
static
.gitattributes
.gitignore
.nojekyll
README.md
_sidebar.md
index.html
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
RedisUserful.md 6.45 KB
一键复制 编辑 原始数据 按行查看 历史
NotFound9 提交于 5年前 . add content

(PS:扫描首页里面的二维码进群,分享我自己在看的技术资料给大家,希望和大家一起学习进步!)

下面是主要是自己看完《Redis设计与实现》,《Redis深度历险:核心原理与应用实践》后,为了更好得掌握Redis,网上找了一些面试题,查阅书籍和资料后,写的解答。

1.Redis主从同步是怎么实现的?

2.Redis中哨兵是什么?

3.客户端是怎么接入哨兵系统的?

4.Redis哨兵系统是怎么实现自动故障转移的?

Redis主从同步是怎么实现的?

主从节点建立连接后,从节点会进行判断

1.如果这是从节点之前没有同步过数据,属于初次复制,会进行全量重同步 那么从节点会向主节点发送PSYNC?-1 命令,请求主节点进行全量重同步

2.如果这是从节点不说初次复制(例如出现掉线后重连), 这个时候从节点会将之前进行同步的Replication ID(一个随机字符串,标识主节点上的特定数据集)和offset(从服务器当前的复制偏移量)通过PSYNC 命令发送给主节点,主节点会进行判断,

  • 如果Replication ID跟当前的Replication ID不一致,或者是当前buffer缓冲区中不存在对应的offset,那么会跟上面的初次复制一样,进行全量重同步
  • 如果Replication ID跟当前的Replication ID一致并且当前buffer缓冲区中存在对应的offset,那么会进行部分重同步。(部分重同步是Redis 2.8之后的版本支持的,主要基于性能考虑,为了断线期间的小部分数据修改进行全量重同步效率比较低)
全量重同步

主节点会执行BGSAVE命令,fork出一个子进程,在后台生成一个RDB持久化文件,完成后,发送给 从服务器,从节点接受并载入RDB文件,使得从节点的数据库状态更新至主节点执行BGSAVE命令时的状态。并且在生成RDB文件期间,主节点也会使用一个缓冲区来记录这个期间执行的所有写命令,将这些命令发送给从节点,从节点执行命令将自己数据库状态更新至与主节点完全一致。

部分重同步

因为此时从节点只是落后主节点一小段时间的数据修改,并且偏移量在复制缓冲区buffer中可以找到,所以主节点把从节点落后的这部分数据修改命令发送给从节点,完成同步。

命令传播

在执行全量重同步或者部分重同步以后,主从节点的数据库状态达到一致后,会进入到命令传播阶段。主节点执行修改命令后,会将修改命令添加到内存中的buffer缓冲区(是一个定长的环形数组,满了时就会覆盖前面的数据),然后异步地将buffer缓冲区的命令发送给从节点。

Redis中哨兵是什么?

Redis中的哨兵服务器是一个运行在哨兵模式下的Redis服务器,核心功能是监测主节点和从节点的运行情况,在主节点出现故障后, 完成自动故障转移,让某个从节点升级为主节点。

客户端是怎么接入哨兵系统的?

首先Redis中的哨兵节点是一个配置提供者,而不是代理。 区别在于,

配置提供者

前者只负责存储当前最新的主从节点信息,供客户端获取。

代理

客户端所有请求都会经过哨兵节点。

所以实际开发中,通过在客户端配置哨兵节点的地址+主节点的名称(哨兵系统可能会监控多个主从节点,名称用于区分)就可以获取到主节点信息, 下面的代码在底层实现是客户端向依次向哨兵节点发送"sentinel get-master-addr-by-name"命令, 成功获得主节点信息就不向后面的哨兵节点发送命令。 同时客户端会订阅哨兵节点的+switch-master频道,一旦主节点发送故障,哨兵服务器对主节点进行自动故障转移,会将从节点升级主节点, 并且更新哨兵服务器中存储的主节点信息,会向+switch-master频道发送消息,客户端得到消息后重新从哨兵节点获取主节点信息,初始化连接池。

 String masterName = "mymaster";
 Set<String> sentinels = new HashSet<>();
 sentinels.add("192.168.92.128:26379");
 sentinels.add("192.168.92.128:26380");

 JedisSentinelPool pool = new JedisSentinelPool(masterName, sentinels); //初始化过程做了很多工作
 Jedis jedis = pool.getResource();
 jedis.set("key1", "value1");
 pool.close();

Redis哨兵系统是怎么实现自动故障转移的?

1.认定主节点主观下线

因为每隔2s,哨兵节点会给主节点发送PING命令,如果在一定时间间隔内,都没有收到回复,那么哨兵节点就认为主节点主观下线。

2.认定主节点客观下线

哨兵节点认定主节点主观下线后,会向其他哨兵节点发送sentinel is-master-down-by-addr命令,获取其他哨兵节点对该主节点的状态,当认定主节点下线的哨兵数量达到一定数值时,就认定主节点客观下线。

3.进行领导者哨兵选举

认定主节点客观下线后,各个哨兵之间相互通信,选举出一个领导者哨兵,由它来对主节点进行故障转移操作。

选举使用的是Raft算法,基本思路是所有哨兵节点A会先其他哨兵节点,发送命令,申请成为该哨兵节点B的领导者,如果B还没有同意过其他哨兵节点,那么就同意A成为领导者,最终得票超过半数以上的哨兵节点会赢得选举,如果本次投票,没有选举出领导者哨兵,那么就开始新一轮的选举,直到选举出哨兵节点(实际开发中,最先判定主节点客观下线的哨兵节点,一般就能成为领导者。)

4.领导者哨兵进行故障转移

领导者哨兵节点首先会从从节点中选出一个节点作为新的主节点。选择的规则是:

  • 1.首先排除一些不健康的节点。(下线的,断线的,最近5s没有回复哨兵节点的INFO命令的,与旧的主服务器断开连接时间较长的)

  • 2.然后根据优先级,复制偏移量,runid最小,来选出一个从节点作为主节点。

向这个从节点发送slaveof no one命令,让其成为主节点,通过slaveof 命令让其他从节点成为它的从节点,将已下线的主节点更新为新的主节点的从节点。

Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/HNov/interviewGuide.git
git@gitee.com:HNov/interviewGuide.git
HNov
interviewGuide
interviewGuide
master

搜索帮助