redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?

midoujava 2019-09-18 原文

redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?

如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时候,想当然的认为写进 redis 的数据就一定会存在,后面导致系统各种 bug,谁来负责?

常见的有两个问题:

  • 往 redis 写入的数据怎么没了?

可能有同学会遇到,在生产环境的 redis 经常会丢掉一些数据,写进去了,过一会儿可能就没了。我的天,同学,你问这个问题就说明 redis 你就没用对啊。redis 是缓存,你给当存储了是吧?

啥叫缓存?用内存当缓存。内存是无限的吗,内存是很宝贵而且是有限的,磁盘是廉价而且是大量的。可能一台机器就几十个 G 的内存,但是可以有几个 T 的硬盘空间。redis 主要是基于内存来进行高性能、高并发的读写操作的。

那既然内存是有限的,比如 redis 就只能用 10G,你要是往里面写了 20G 的数据,会咋办?当然会干掉 10G 的数据,然后就保留 10G 的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。

  • 数据明明过期了,怎么还占用着内存?

这是由 redis 的过期策略来决定。

redis 过期策略是:定期删除+惰性删除

所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

假设 redis 里放了 10w 个 key,都设置了过期时间,你每隔几百毫秒,就检查 10w 个 key,那 redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。注意,这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,那样就是一场性能上的灾难。实际上 redis 是每隔 100ms 随机抽取一些 key 来检查和删除的。

但是问题是,定期删除可能会导致很多过期 key 到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个 key 的时候,redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。

获取 key 的时候,如果此时 key 已经过期,就删除,不会返回任何东西。

但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整?

答案是:走内存淘汰机制

redis 内存淘汰机制有以下几个:

  • noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧,实在是太恶心了。
  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。
  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的 key 给干掉啊。
  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key(这个一般不太合适)。
  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。

你可以现场手写最原始的 LRU 算法,那个代码量太大了,似乎不太现实。

不求自己纯手工从底层开始打造出自己的 LRU,但是起码要知道如何利用已有的 JDK 数据结构实现一个 Java 版的 LRU。

  1. class LRUCache<K, V> extends LinkedHashMap<K, V> {
  2. private final int CACHE_SIZE;
  3. /**
  4. * 传递进来最多能缓存多少数据
  5. *
  6. * @param cacheSize 缓存大小
  7. */
  8. public LRUCache(int cacheSize) {
  9. // true 表示让 linkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最老访问的放在尾部。
  10. super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
  11. CACHE_SIZE = cacheSize;
  12. }
  13. @Override
  14. protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
  15. // 当 map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
  16. return size() > CACHE_SIZE;
  17. }
  18. }
发表于
2019-09-18 21:52 米兜Java 阅读() 评论() 编辑 收藏

 

版权声明:本文为midoujava原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/midoujava/p/11545621.html

redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?的更多相关文章

  1. 庐山真面目之十三微服务架构中如何在Docker上使用Redis缓存

    一、介绍         1、开始说明        在微服务器架构中,有一个组件是不能少的,那就是缓存组件。 […]...

  2. Springboot-shiro-redis实现登录认证和权限管理

    Springboot-shiro-redis实现登录认证和权限管理 Springboot-shiro-redi […]...

  3. Redis 的底层数据结构(压缩列表)

    上一篇我们介绍了 redis 中的整数集合这种数据结构的实现,也谈到了,引入这种数据结构的一个很大的原因就是, […]...

  4. Redis数据类型(下)

    集合Set      Redis 的集合不是 个线性结构,而是一个哈希表结构,它的内部会根据 hash 分子来 […]...

  5. 如何从10亿数据中快速判断是否存在某一个元素

    前言 当 Redis 用作缓存时,其目的就是为了减少数据库访问频率,降低数据库压力,但是假如我们某些数据并不存 […]...

  6. Redis可视化工具 Redis Desktop Manager

    1、前言   从接触Redis也有两年,平时就使用它来做缓存层,它给我的印象就是很强大,内置的数据结构很齐全, […]...

  7. 【Azure Redis 缓存】如何得知Azure Redis服务有更新行为?

    问题描述 Azure Redis作为微软云提供的一种PaaS服务,由于PaaS的特性,服务端的安装和维护、修补 […]...

  8. Redis 相关运维操作

    背景   Redis作为目前全球最流行的KV存储,除了使用之外,还需要做好日常的运维工作。关于运维相关的工作, […]...

随机推荐

  1. 机器人视觉系统笔记

    机器人视觉系统研究 杭电图书馆 科学出版社 总页数:202   唯一QQ:1825587919 唯一WX:ly […]...

  2. 华为HMS游戏排行榜请求报错HTTP 502

    问题现象: 请求华为HMS游戏排行榜getRankingIntent接口后报错如下: 日志信息: 在Andro […]...

  3. 反爬虫破解系列-汽车之家利用css样式替换文字破解方法

    网站: 汽车之家:http://club.autohome.com.cn/ 以论坛为例 反爬虫措施: 在论坛发 […]...

  4. Linux修改时区

    从CentOS 7开始,使用了一个新的命令timedatectl timedatectl 命令 (1) 读取时 […]...

  5. android 3.0+百度地图api地图如何移动到指定的经纬度处

    由于百度地图api,2.0+和3.0+的改动比较大,api基本上被全换过了,有些同学可能2.0+的api使用的 […]...

  6. PDF转图片

     有人可能问,族长今天为什么要写有关“PDF生成图片”呢?         我之所以写这篇文章,是因为最近的项 […]...

  7. 快递鸟单号查询api接口免费接入申请示例

    1.背景 :           现在网购的用户越来越多,不管是商家还是用户还是企业,大家对物流的跟踪也是越来 […]...

  8. 常见的系统架构

    一、软件架构 软件架构(software architecture)是一系列相关的抽象模式,用于指导大型软件系 […]...

展开目录

目录导航