• redis内存淘汰机制与lru


    https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247486210&idx=1&sn=77fb08edcaeaa07eb55b029f24f76ac1&chksm=96cd4b4ea1bac2584a471468e89fa6f5ad4103b21f14cd726e8b3d47ddcc55261befdf319fc6&mpshare=1&scene=1&srcid=05157y1N1aj5Gv2Y118LPJNj&key=259ddc97107c0c69acb90391a5e7354d2de386bc05b14c366352634e5a3e1d4698537d8a65bd7bbd08fd91d8bcf075d3b4cba14b647d69f3700e605449546964900f0d589f8ca3fa581373df52b60f9f&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=bYp8tOH0gLQNlxdvvvx7dfnhmidIEkms7qrgkKSic6LsIYkoC0g1IX3prIh0P6kU

    面试官:我看你简历提到xxx项目使用了redis

    小弱鸡:嗯,因为xxxx的性能问题,经过排查之后,发现性能瓶颈在数据库上面,所以引入了redis

    面试官:行,那你了解redis的过期策略吗?

    小弱鸡:有了解过,因为redis是基于内存来进行高性能、高并发的读写操作的,既然是内存,那肯定有空间的限制,如果只有10g内存,一直往里面写数据,那肯定不行,所以采用一些过期策略把不需要的数据删除、或者是淘汰掉。

    面试官:那都有哪些过期策略?

    小弱鸡:我了解的有 定期删除、惰性删除两种

    面试官:你先讲讲定期删除怎么实现?

    小弱鸡好像有点兴奋:所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

    面试官:为什么是随机抽取?

    小弱鸡:假如在redis 里插入10w个key,并且都设置了过期时间,如果每次都检查所有key,那cpu基本上都消耗在过期key的检查上了,redis对外的性能也会大大降低,简直就是一场灾难。

    面试官:随机检查会存在什么问题?

    小弱鸡:可能导致本已经过期的key没有被扫描到,而继续留在内存中,并占用空间,等待被删除。

    面试官:这种情况怎么解决?

    小弱鸡又兴奋了:这时候就需要第二种过期策略了,惰性删除,就是在获取某个 key 的时候,redis 会检查一下 ,如果这个 key 设置了过期时间,并且已经过期了,那么就直接删除,返回空。

    面试官面带一丝笑意:嗯,那再考虑一种情况,如果大量的key没有被扫描到,且已过期,也没有被再次访问,即没有走惰性删除,这些大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,这种情况下,怎么办?

    小菜鸡想了会,抓了抓脑袋:redis内部提供了内存淘汰机制,应该有好几种策略,但我只知道LRU算法。

    面试官:嗯,那你手写一个LRU算法?

    小菜鸡*花一紧,这不是给自己挖坑么!!! 如果从头开始写一个完整的LRU算法,那会要了命,幸好小菜鸡还记得 LinkedHashMap,可以基于 LinkedHashMap实现一个简单版本的LRU算法

    1. class LRUCache<K, V> extends LinkedHashMap<K, V> {

    2. private final int CACHE_SIZE;

    3. * @param cacheSize 缓存大小

    4. */

    5. // true 表示让 linkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最老访问的放在尾部。

    6. public LRUCache(int cacheSize) {

    7. super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);

    8. CACHE_SIZE = cacheSize;

    9. }

    10. @Override

    11. // 当 map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。

    12. protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {

    13. return size() > CACHE_SIZE;

    14. }

    15. }

    小菜鸡写完之后,轻轻舒了一口气。

    (1)volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。

    (2)volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

    (3)volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

    (4)allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

    (5)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

    (6)no-enviction:禁止淘汰数据

  • 相关阅读:
    在SQL SERVER 2005中还原数据库时出现错误:system.data.sqlclient.sqlerror 媒体集有 2 个媒体簇 但只提供了 1 个。必须提供所有成员。 (microsoft.sqlserver.smo)
    Mysql的Root密码忘记,查看或修改的解决方法
    Win7系统如何设置FTP详细过程
    该设备或资源(127.0.0.1)未设置为接受端口“16823”上的连接。
    window7防火墙无法更改某些设置,错误代码0×80070422
    访问FTP站点下载文件,提示“当前的安全设置不允许从该位置下载文件”的解决方案
    解决SQL Server 阻止了对组件 'Ad Hoc Distributed Queries' 的 STATEMENT'OpenRowset/OpenDatasource' 的访问的方法
    按状态选择链接元素
    类选择器与ID选择器的比较
    关于创建Web图像时应记住的五个要素
  • 原文地址:https://www.cnblogs.com/silyvin/p/11190488.html
Copyright © 2020-2023  润新知