前言
提示:这里为每天自己的学习内容心情总结;
Learn By Doing,Now or Never,Writing is organized thinking.
目前的想法是,根据 Java Guide 和 JavaLearning 和 小林coding进行第一轮复习,之后根据 Tiger 和 CS-Notes 进行最后的重点复习。
先多,后少。
提示:以下是本篇文章正文内容
一、今天学习了什么?
- Redis;
二、关于问题的答案
1.Redis
Q:Redis是单线程的吗?
针对于命令是单线程去执行的,但是比如关闭文件、持久化、内存释放是利用了后台线程。
Q:Redis 的网络模型?
I/O复用。
Q:Redis 6.0 之后为什么引入了多线程模型呢?
解决网络传输的瓶颈。
Q:Redis 的过期删除?
过期删除,指的是设置键值对的过期时间时,当键值对过期了,就会将该键值对从内存中删除。
如何判断键值对已经过期呢?底层原理是什么?
Redis 将设置了过期时间的键值对,统一放倒了过期字典中,过期字典就是一个哈希表,key 为键值对的 key,value 为这个键值对的过期时间。
每次从数据库中使用键值对时,首先需要判断该键值对是否存在于过期字典中,如果存在过期字典中,需要和系统当前时间进行比对,是否过期。
Redis的过期删除策略有哪些?
- 定时删除,事件;
- 惰性删除,使用;
- 定期删除,间隔时间;
Redis 采用的是 惰性删除 + 定期删除,两个结合使用,平衡 CPU 和 内存。
Q:内存淘汰策略。
当 Redis 的运行内存,超过了允许的内存上限时,就需要根据对应的内存淘汰策略淘汰掉内存中的数据。
有哪些内存淘汰的策略呢?
常见的就是 LRU & LFU。
LRU,least recently used,最近最少使用的,选择淘汰掉最近最少使用的数据。
底层实现原理,是在 Redis 对象的结构体中添加了一个字段,记录这个对象上次被访问的时间,然后根据哪一个数据是最久没有被使用到的,淘汰掉。
可能出现缓存污染的情况,如果某次操作一次性读取了很多数据到内存中,但是这些数据都只会被使用一次,内存中就会缓存很多无用数据。
LFU,least frequently used,最近最不常使用,会选择淘汰掉内存中访问频次最低的数据。
解决了 LRU 可能出现的缓存污染问题,基于 LFU,Redis 的结构体中还会记录另外一个字段是数据的访问频次。
Q:主从复制?
利用 AOF 和 RDB 恢复数据,只能保证单个机器的数据能恢复,如果硬盘或者机器宕机发生问题,会导致数据丢失,此时需要引入集群。
Redis 有主从复制,保障数据的安全性,主服务器负责读写,从服务器负责读,利用 主从复制 保证数据的一致性。
Q:主从复制第一次同步?
使用 replicaof 命令可以让两台服务器,成为主从关系,第一次主从同步数据,分为三步(A-主服务器,B-从服务器)。
第一步,建立连接。
执行了 replicaof 命令后,B 就会发送 psync 命令给 A,psync 命令包含两个参数:
- runID,每一台 Redis 服务器在启动的时候,都会随机生成一个 runID 用于唯一标识,当第一次主从同步时,runID 为 ? ;
- offset,B复制数据的进度,第一次主从同步时,offset 为 -1;
当 A 接收到来自 B 的 psync 命令后,会将 A 的 runID 和 offset 都发送过去,准备执行全量同步。
第二步,准备执行全量同步。
A 会执行 bgsave 创建 RDB 文件,然后将 RDB 文件 发送给 B。从服务器接收到 RDB 文件后,会清理原有数据,之后加载 RDB 文件。
在执行 RDB 的全过程中,主服务器的新增写操作命令,会写入到 replication buffer 缓冲区中。
第三步:准备执行新增写命令。
从服务器加载 RDB 文件成功后,会给主服务器发送一个确认消息。然后 A 会将位与 replication buffer缓冲区中的新增的写操作命令发送给 B,B执行。
主从服务器完成第一次数据同步后,会建立一个 TCP 长连接,之后主服务器的新增写命令会通过长连接发送给从服务器。
Q:主从复制的增量复制?
如果从节点因为网络原因而下线,这段时间内主节点接收到的写请求,会被存放在一个缓冲区中 repl_backlog_buffer ,当从节点上线后,会重新进行数据同步。
底层是通过两个重要的参数:
- repl_backlog_buffer,是一个环形的缓冲区,负责写入新的写操作指令;
- offset,记录的是写入读取的位置;
进行增量复制的时候,当从节点上线后,会发送命令给主节点,上报从节点的 offset,主节点判断从节点的 offset 是否在环形缓冲区中,进行不同的同步操作:
- 如果在环形缓冲区中,发生增量同步,只需要同步主节点和从节点的差值;
- 如果不在环形缓冲区中,发送全量同步;
Q:如何判断某个 Redis 节点是否在正常工作呢?
利用 ping-pong 机制:
- 主节点会每隔一定的时间,给从节点发送 ping 指令;
- 从节点会每隔一定的时间,给主节点发送 offset,目的是判断连接状态和同步数据。
Q:主从复制中两个 Buffer(replication buffer 、repl backlog buffer)有什么区别?
有两个区别,分别是作用的时间段 和 当数据满了之后的对应操作。
- replication buffer:
- 既作用于 全量复制 ,也作用于 增量复制;
- 如果数据满了,会导致连接断开,需要清除内存,重新进行全量复制。
- repl_backlog_buffer:
- 只作用于增量复制;
- 是一个唤醒数据区,如果写满,会覆盖之前的数据,继续写。
Q:如何应对主从数据不一致?
主从数据不一致,是因为主节点给从节点同步数据的操作是异步的。
保证网络畅通良好,不要将主从节点放在不同的机房;监控主从节点的复制进度,如果某个从节点的数据同步差,就让客户端不能连接这个从节点,保证客户端访问的数据一致性。
Q:主从切换如何减少数据的丢失呢?
有两个行为可能导致数据丢失:主从异步复制导致数据丢失、集群脑裂导致数据丢失。
Q:哨兵架构?
哨兵架构是为了解决主从集群模式下,主节点宕机后的主从故障转移而存在的。
主要有三个功能:监控、选主、通知。
Q:工作机制?监控
监控所有的节点工作状态,以 ping-pong 的形式检测节点是否在线。如果某个节点没有在规定的时间内给哨兵节点响应,哨兵节点会主观认为这 Redis 节点已经下线了。
对于主节点,还需要判断客观下线。超过规定的值 quorum 。
Q:选主?
首先,在哨兵集群中选举出来 leader,默认是发现主节点主观下线的那个哨兵节点作为候选者,会发起投票,要求超过半数并且达到 quorum 值。
由 leader 发起选举新的主节点,三个步骤:
- 优先级;
- offset;
- runID;
Q:通知?
选举出来了新的主节点之后,将新主节点的信息由 发布/订阅模式 传送给客户端。
Q:缓存穿透?
针对的是缓存和数据库中都不存在的数据。
缓存空值、拒绝非法请求、布隆过滤器(比特数组&哈希函数)。
Q:缓存击穿?
针对的是缓存中的热点数据失效。
互斥锁、后台线程更新。
Q:缓存雪崩?
由于 Redis 同时间大量数据失效 or Redis 宕机。
互斥锁、均匀设定过期时间、后台线程更新;熔断、限流、集群。
总结
提示:这里对文章进行总结:
明天要学习完 Redis,然后开始复习Java se 和 网络,还要刷题,看面经。