redis数据删除/内存淘汰

如果我们设置一批key只能存活1小时,那么1小时之后,redis是怎么对这批数据进行删除的?

答案:定期删数+惰性删除

(1)定期删除

指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意,这里可不是每隔100ms就遍历所有的设置过期时间的key,那样就是一场性能上的灾难。实际上redis是每隔100ms随机抽取一些key来检查和删除的。

(2)惰性删除

定期删除的问题是可能会导致很多过期key到了时间并没有被删除掉,那怎么办?所以还有惰性删除,也就是在查询某个key的时候,redis会检查一下这个key如果设置了过期时间并且是否过期了,如果过期了就会在此时删除。

通过定期删除和惰性删除两种方式结合,保证过期的key一定会被删除

  • 定期删除是为了节省内存
  • 惰性删除是为了保证过期性

如果定期没删除,也没有查询,这样会导致大量过期的key堆积在内存里怎么办?

答案:内存淘汰机制

allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
手写LRU



public class LRUCache extends LinkedHashMap {

    private final int CACHE_SIZE;

    public LRUCache(int cacheSize){
        /**
         * 这块就是设置一个hashmap的初始大小,
         * 同时最后一个true指的是让linkedHashMap按照访问顺序来进行排序(自动实现LRU)
         * 最近访问的放在头,最老访问的放在尾
         */
        super((int)Math.ceil(cacheSize/0.75)+1, 0.75f, true);
        CACHE_SIZE = cacheSize;
    }
//通过覆盖这个方法,加入一定的条件,满足条件返回true。
//当put进新的值方法返回true时,便移除该map中最老的键和值。
    @override
    protected boolean removeEldestEntry(Map.Entry eldest){
        /**
         * 这个意思就是说当map中当数据大于指定当缓存个数当时候,就会自动删除最老的数据
         */
        return size() > CACHE_SIZE;
    }
    
}



主从复制过程

这个牛客网上问的也不多,先待定二轮复习再补充

Redis哨兵模式

这都是为了提高redis的高可用性

==集群监控==,负责监控redis master和slave进程是否正常工作
==消息通知==,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知管理员
==故障转移==,如果master node挂掉了,会自动转移到slave node上
==配置中心==,如果故障转移发生了,通知client客户端新的master地址




redis 惰性删除参数设置 redis惰性删除怎么用_为什么集群要奇数


  • 命令连接:用来获取主/从服务器的信息
  • 订阅连接:sentinel1会通过命令连接向主从服务器发送自身状态信息,通过订阅连接将此信息通知到其他的哨兵,因此哨兵不需要知道哨兵之间的位置
  • 哨兵之间命令连接:与下线检测的原理相关(因为此时主服务器已经宕机,无法通过订阅连接让哨兵之间通知)

哨兵模式工作流程

  1. 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令。
  2. 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被当前 Sentinel 标记为主观下线。
  3. 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
  4. 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 ,进而对Master进行故障转移

故障转移流程

  1. 选取领头哨兵,采取先到先得的方式,超过半数哨兵的支持的哨兵成为领头哨兵
  2. 从已下线主服务器属下的所有从服务器里面,挑选一个从服务器,并将其转换为主服务器
  3. 让一下先主服务器属下所有从服务器改位复制新的主服务器
  4. 将已下线主服务器设置位新的主服务器的从服务器

挑选从服务器的流程

  1. 从服务器处于在线状态
  2. 从服务器最近五秒回复过哨兵的INFO命令
  3. 跟master断开连接的时长较短,这是为了保证从服务器的数据较新
  4. 从服务器优先级,复制偏移量(哪个slave复制了越多的数据,offset越靠后,优先级就越高),运行ID(run id比较小),进行排序

为什么哨兵至少需要3个

  • 因为挑选领头哨兵的时候需要获得超过半数的投票,所以一般都是把哨兵的节点设置为奇数位。因为(2的majority=2,3的majority=2,5的majority=3,4的majority=3)偶数容易算错
  • 2个哨兵同样可以完成功能,所以其实没有说一定要至少三个,只是两个哨兵的时候如果挂了一个就不可用了,而三个哨兵挂了一个还有两个可用。因此至少3个是为了达到一定的高可用性的常用配置而已。

Redis集群模式


redis 惰性删除参数设置 redis惰性删除怎么用_数据_02


redis分片

将整个数据集按照一定的规则分配到多个节点上,常用的数据分片的方法有:范围分片,哈希分片,一致性哈希算法,哈希槽等。

槽位的概念在集群这里很重要,任何key都要通过槽位分片到不同的节点运行

创建集群的流程

  1. 配置和开启cluster模式
  2. 配置redis实例节点握手
  3. 为每个主节点指派槽位,一般按区间平均分配
  4. 分配主从

扩容集群过程

  1. 准备新节点
  2. 加入集群进行握手
  3. 迁移槽和数据(槽位转移了,对应槽位的数据也会迁移到新的实例上)

缩容过程

  1. 确定下线的节点是否有负责槽,如果是,需要把槽迁移到其他节点,保证节点下线后整个槽节点映射的完整性。
  2. 当下线节点不在负责槽或着本身是从节点时,就可以通知集群内其他节点忘记下线节点,当所有节点忘记该节点后就可以正常关闭。

故障转移

为什么redis cluster至少需要3个主节点?

因为故障检测时没有哨兵,需要超过半数的主节点都主观下线,该故障节点才会被视为客观下线。两个主节点,如果挂了一个,那么只剩一个无法达到超过半数的条件。这与哨兵模式不同,因为两个哨兵不一定会挂。

故障转移过程-----《redis设计与实现》------感觉不会考

主从复制,哨兵,集群的区别

1.主从模式:读写分离,备份,一个Master可以有多个Slaves。

2.哨兵sentinel:监控,自动转移,哨兵发现主服务器挂了后,就会从slave中重新选举一个主服务器。

3.集群:故障转移不再需要哨兵,提供数据分片,提高并发量,一般都是使用它了。