简单总结哈,LRU+双向链表实现缓存, 和Redis的

    技术2022-07-14  62

     1. Least Recently Used   

    最近最少使用淘汰机制, 访问一个key在map中,也就是 在内存中, 就将此页放到建表头部, , 不在内存中, (假如规定链表只能有三个节点, 当访问第四个时, 如果值不在内存中, 那就释放链表最尾部的节点, 然后将此值包装成节点, 放入头部)  就先去磁盘取.    

    2. 为什么不使用双向链表   

    使用双向链表, 每个节点会增加两个指针的空间消耗

    3. redis不使用链表, 那用什么结构或者属性实现LRU淘汰策略

    redis采用设置  全局 server-lruclock   时钟,  每个节点有一个  lru时间戳    属性, 类似于两个时间戳

    1. 访问节点时候会将server-lruclock 复制给lru , 避免系统调用, 造成上下文切换

    2. 而 全局的server-lruclock跟根据全局变量server.hz来调用系统操作实现更新

    4. redis采用的一些内存策略

    1. 定期删除+惰性删除

    定期删除 , 每隔一定时间, 根据maxmemory_samples设置的个数,  选取这么多节点进行检查过期,  一次性检查全部, 会造成卡顿

    惰性删除, 你访问一个key, 会看看过期没, 过期了就删除

    4.1 那内存还是会满怎么办, 那就出现淘汰策略

    Redis系统提供五种淘汰策略,即参数maxmemory_policy有五种取值:

    noeviction: 如果缓存数据超过了maxmemory限定值,并且客户端正在执行的命令会导致内存分配,则向客户端返回错误响应.

    allkeys-lru: 所有的缓存数据(包括没有超时属性的和具有超时属性的)都参与LRU算法淘汰.

    volatile-lru: 只有超时属性的缓存数据才参与LRU算法淘汰.

    allkeys-random: 所有的缓存数据(包括没有超时属性的和具有超时属性的)都参与淘汰, 但是采用随机淘汰,而不是用LRU算法进行淘汰.

    volatile-random: 只有超时属性的缓存数据才参与淘汰,但是采用随机淘汰,而不是用LRU算法进行淘汰.

    volatile-ttl: 只有超时属性的缓存数据才参与淘汰. 根据缓存数据的超时TTL进行淘汰,而不是用LRU算法进行淘汰.

    4.2 怎样实现LRU呢

    根据3中描述的结构属性,  全局属性和节点私有两个属性差值越大说明, 最近最少访问, 然后淘汰

    如果淘汰策略是allkeys-random或者volatile-random,则从相应数据库中随机选择一个key进行淘汰.

    如果淘汰策略是allkeys-lru或者volatile-lru, 则根据配置的采样值maxmemory_samples,随机从数据库中选择maxmemory_samples个key, 淘汰其中热度最低的key对应的缓存数据.

    如果淘汰策略是volatile-ttl,则根据配置的采样值maxmemory_samples,随机从数据库中选择maxmemory_samples个key,淘汰其中最先要超时的key对应的缓存数据.

    所以采样参数maxmemory_samples配置的数值越大, 就越能精确的查找到待淘汰的缓存数据,但是也消耗更多的CPU计算,执行效率降  

    引用大佬~ https://blog.csdn.net/azurelaker/article/details/85045245

     

    Processed: 0.016, SQL: 9