缓存淘汰和过期删除
过期删除策略和内存淘汰策略有什么区别?
区别:
内存淘汰策略是在内存满了的时候,redis 会触发内存淘汰策略,来淘汰一些不必要的内存资源,以腾出空间,来保存新的内容
过期键删除策略是将已过期的键值对进行删除,Redis 采用的删除策略是惰性删除+定期删除。
介绍一下Redis 内存淘汰策略
在 32 位操作系统中,maxmemory 的默认值是 3G,因为 32 位的机器最大只支持 4GB 的内存,而系统本身就需要一定的内存资源来支持运行,所以 32 位操作系统限制最大 3 GB 的可用内存是非常合理的,这样可以避免因为内存不足而导致 Redis 实例崩溃。
Redis 内存淘汰策略共有八种,这八种策略大体分为「不进行数据淘汰」和「进行数据淘汰」两类策略。
1、不进行数据淘汰的策略:
noeviction(Redis3.0之后,默认的内存淘汰策略) :它表示当运行内存超过最大设置内存时,不淘汰任何数据,这时如果有新的数据写入,会报错通知禁止写入,不淘汰任何数据,但是如果没用数据写入的话,只是单纯的查询或者删除操作的话,还是可以正常工作。
2、进行数据淘汰的策略:
针对「进行数据淘汰」这一类策略,又可以细分为「在设置了过期时间的数据中进行淘汰」和「在所有数据范围内进行淘汰」这两类策略。
在设置了过期时间的数据中进行淘汰:
volatile-random:随机淘汰设置了过期时间的任意键值;
volatile-ttl:优先淘汰最早过期的键值,越早过期的越先淘汰
volatile-lru(Redis3.0 之前,默认的内存淘汰策略):淘汰所有设置了过期时间的键值中,最久未使用的键值;
volatile-lfu(Redis 4.0 后新增的内存淘汰策略):淘汰所有设置了过期时间的键值中,最少使用的键值;
在所有数据范围内进行淘汰:
allkeys-random:随机淘汰任意键值;
allkeys-lru:淘汰整个键值中最久未使用的键值;
allkeys-lfu(Redis 4.0 后新增的内存淘汰策略):淘汰整个键值中最少使用的键值。
介绍一下Redis过期删除策略
Redis 选择「惰性删除+定期删除」这两种策略配和使用,以求在合理使用 CPU 时间和避免内存浪费之间取得平衡。
惰性删除
Redis 在访问或者修改 key 之前,都会调用 expireIfNeeded 函数对其进行检查,检查 key 是否过期:
如果过期,则删除该 key,至于选择异步删除,还是选择同步删除,根据 lazyfree_lazy_expire 参数配置决定(Redis 4.0版本开始提供参数),然后返回 null 客户端;
如果没有过期,不做任何处理,然后返回正常的键值对给客户端。
定期删除
Redis 的定期删除是每隔一段时间「随机」从数据库中取出一定数量的 key 进行检查,并删除其中的过期key。
Redis的缓存失效会不会立即删除?
不会,Redis 的过期删除策略是选择「惰性删除+定期删除」这两种策略配和使用。
惰性删除策略的做法是,不主动删除过期键,每次从数据库访问 key 时,都检测 key 是否过期,如果过期则删除该 key。
定期删除策略的做法是,每隔一段时间「随机」从数据库中取出一定数量的 key 进行检查,并删除其中的过期key。
那为什么我不过期立即删除?
在过期 key 比较多的情况下,删除过期 key 可能会占用相当一部分 CPU
时间紧张的情况下,将 CPU 时间用于删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。所以,定时删除策略对 CPU 不友好
集群
Redis主从同步中的增量和完全同步怎么实现?(又叫部分复制和全量复制)
Redis的主从同步是如何实现的?
Redis使用psync命令完成主从数据同步,同步过程分为全量复制和部分复制
完全同步
完全同步发生在以下几种情况:
初次同步:当一个从服务器(slave)首次连接到主服务器(master)时,会进行一次完全同步。
从服务器数据丢失:如果从服务器数据由于某种原因(如断电)丢失,它会请求进行完全同步。
主服务器数据发生变化:如果从服务器长时间未与主服务器同步,导致数据差异太大,也可能触发完全同步。
主从服务器间的第一次同步的过程可分为三个阶段:
第一阶段是建立链接、协商同步;
第二阶段是主服务器同步数据给从服务器;
第三阶段是主服务器发送新写操作命令给从服务器。
实现过程:
从服务器发送SYNC命令:从服务器向主服务器发送SYNC命令,请求开始同步。
主节点回复 FULLRESYNC;
主服务器 执行bgsave命令进行rdb的持久化
传输RDB文件:主服务器将生成的RDB文件发送给从服务器。
从服务器接收并应用RDB文件:从服务器接收RDB文件后,会清空当前的数据集,并载入RDB文件中的数据。
主服务器记录写命令:在RDB文件生成和传输期间,主服务器会记录所有接收到的写命令到缓冲区。
传输写命令:一旦RDB文件传输完成,主服务器会将缓冲区中的命令补发给从服务器,从服务器会执行这些命令,以保证数据的一致性。
增量同步
实现过程:
增量同步允许从服务器从断点处继续同步,而不是每次都进行完全同步。它基于PSYNC命令,使用了运行ID(run ID)和复制偏移量(offset)的概念。
一般出现在网络中断的情况下
从服务器发送SYNC命令(把之前的runid 和 offset作为psync的参数):从服务器向主服务器发送SYNC命令,请求开始同步。
主节点回复 CONTINUE;然后根据offset去缓冲区查找合适的数据发送给从节点,最终完成一致性
实时复制
主节点把自己的修改操作通过tcp长连接的方式传输给从节点,tcp长连接需要通过心跳包的机制来维护状态,主节点每10s对从节点发送ping命令,从节点收到就返回pong,从节点每隔1s发送请求,上报自己的offset
redis主从和集群可以保证数据一致性吗 ?
redis 主从和集群在CAP理论都属于AP模型,即在面临网络分区时选择保证可用性和分区容忍性,而牺牲了强一致性。这意味着在网络分区的情况下,Redis主从复制和集群可以继续提供服务并保持可用,但可能会出现部分节点之间的数据不一致。
哨兵机制原理是什么?
Redis 在 2.8 版本以后提供的哨兵(Sentinel)机制,它的作用是实现主从节点故障转移。它会监测主节点是否存活,如果发现主节点挂了,它就会选举一个从节点切换为主节点,并且把新主节点的相关信息通知给从节点和客户端。
哨兵其实是一个运行在特殊模式下的 Redis 进程,所以它也是一个节点。从“哨兵”这个名字也可以看得出来,它相当于是“观察者节点”,观察的对象是主从节点。
当然,它不仅仅是观察那么简单,在它观察到有异常的状况下,会做出一些“动作”,来修复异常状态。
哨兵节点主要负责三件事情:监控、选主、通知。
哨兵机制的选主节点的算法介绍一下
当redis集群的主节点故障时,Sentinel集群将从剩余的从节点中选举一个新的主节点,有以下步骤:
故障节点主观下线
故障节点客观下线
Sentinel集群选举Leader
Sentinel Leader决定新主节点
故障节点主观下线
Sentinel集群的每一个Sentinel节点会定时对redis集群的所有节点发心跳包检测节点是否正常。如果一个节点在down-after-milliseconds时间内没有回复Sentinel节点的心跳包,则该redis节点被该Sentinel节点主观下线。
故障节点客观下线
当节点被一个Sentinel节点记为主观下线时,并不意味着该节点肯定故障了,还需要Sentinel集群的其他Sentinel节点共同判断为主观下线才行。
该Sentinel节点会询问其他Sentinel节点,如果Sentinel集群中超过quorum数量的Sentinel节点认为该redis节点主观下线,则该redis客观下线。
如果客观下线的redis节点是从节点或者是Sentinel节点,则操作到此为止,没有后续的操作了;如果客观下线的redis节点为主节点,则开始故障转移,从从节点中选举一个节点升级为主节点。
Sentinel集群选举Leader
如果需要从redis集群选举一个节点为主节点,首先需要从Sentinel集群中选举一个Sentinel节点作为Leader。
每一个Sentinel节点都可以成为Leader,当一个Sentinel节点确认redis集群的主节点主观下线后,会请求其他Sentinel节点要求将自己选举为Leader。被请求的Sentinel节点如果没有同意过其他Sentinel节点的选举请求,则同意该请求(选举票数+1),否则不同意。
如果一个Sentinel节点获得的选举票数达到Leader最低票数(quorum和Sentinel节点数/2+1的最大值),则该Sentinel节点选举为Leader;否则重新进行选举。
举个例子,假设哨兵节点有 3 个,quorum 设置为 2,那么任何一个想成为 Leader 的哨兵只要拿到 2 张赞成票,就可以选举成功了。如果没有满足条件,就需要重新进行选举。
Sentinel Leader决定新主节点
当Sentinel集群选举出Sentinel Leader后,由Sentinel Leader从redis从节点中选择一个redis节点作为主节点:
过滤故障的节点
选择优先级slave-priority最大的从节点作为主节点,如不存在则继续
选择复制偏移量(数据写入量的字节,记录写了多少数据。主服务器会把偏移量同步给从服务器,当主从的偏移量一致,则数据是完全同步)最大的从节点作为主节点,如不存在则继续
选择runid(redis每次启动的时候生成随机的runid作为redis的标识)最小的从节点作为主节点
Redis集群的模式了解吗 优缺点了解吗
当 Redis 缓存数据量大到一台服务器无法缓存时,就需要使用 Redis 切片集群(Redis Cluster )方案,它将数据分布在不同的服务器上,以此来降低系统对单主节点的依赖,从而提高 Redis 服务的读写性能。
Redis Cluster 方案采用哈希槽(Hash Slot),来处理数据和节点之间的映射关系。在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽,这些哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中,具体执行过程分为两大步:
根据键值对的 key,按照 CRC16 算法计算一个 16 bit 的值。
再用 16bit 值对 16384 取模,得到 0~16383 范围内的模数,每个模数代表一个相应编号的哈希槽。
接下来的问题就是,这些哈希槽怎么被映射到具体的 Redis 节点上的呢?有两种方案:
平均分配: 在使用 cluster create 命令创建 Redis 集群时,Redis 会自动把所有哈希槽平均分布到集群节点上。比如集群中有 9 个节点,则每个节点上槽的个数为 16384/9 个。
手动分配: 可以使用 cluster meet 命令手动建立节点间的连接,组成集群,再使用 cluster addslots 命令,指定每个节点上的哈希槽个数。
为了方便你的理解,我通过一张图来解释数据、哈希槽,以及节点三者的映射分布关系。
Redis集群模式优点/缺点
优点:
高可用性:Redis集群最主要的优点是提供了高可用性,节点之间采用主从复制机制,可以保证数据的持久性和容错能力,哪怕其中一个节点挂掉,整个集群还可以继续工作。
**高性能:**Redis集群采用分片技术,将数据分散到多个节点,从而提高读写性能。当业务访问量大到单机Redis无法满足时,可以通过添加节点来增加集群的吞吐量。
**扩展性好:**Redis集群的扩展性非常好,可以根据实际需求动态增加或减少节点,从而实现可扩展性。集群模式中的某些节点还可以作为代理节点,自动转发请求,增加数据模式的灵活度和可定制性。
缺点:
**部署和维护较复杂:**Redis集群的部署和维护需要考虑到分片规则、节点的布置、主从配置以及故障处理等多个方面,需要较强的技术支持,增加了节点异常处理的复杂性和成本。
**集群同步问题:**当某些节点失败或者网络出故障,集群中数据同步的问题也会出现。数据同步的复杂度和工作量随着节点的增加而增加,同步时间也较长,导致一定的读写延迟。
**数据分片限制:**Redis集群的数据分片也限制了一些功能的实现,如在一个key上修改多次,可能会因为该key所在的节点位置变化而失败。此外,由于将数据分散存储到各个节点,某些操作不能跨节点实现,不同节点之间的一些操作需要额外注意。