Redis淘汰机制+热点数据问题

为什么需要淘汰

Redis是内存数据库,我们能时时刻刻能感受到Redis作者为更好地使用内存而费尽各种心思,例如最明显的是对于同一种数据结构在不同应用场景下提供了基于不同底层编码的实现(如压缩列表、跳跃表等)。

Redis最常见的两种应用场景为缓存和持久存储,当Redis做缓存时,有一个Redis服务器,服务器物理内存大小为1G的,我们需要存在Redis中的数据量很小,这看起来似乎足够用很长时间了,随着业务量的增长,我们放在Redis里面的数据越来越多了,数据量大小似乎超过了1G,但是应用还可以正常运行,这是因为操作系统的可见内存并不受物理内存限制,而是虚拟内存,物理内存不够用没关系,操作系统会从硬盘上划出一片空间用于构建虚拟内存,比如32位的操作系统的可见内存大小为2^32,而用户空间的可见内存要小于2^32很多,大概是3G左右。好了,我们庆幸操作系统为我们做了这些,但是我们需要知道这背后的代价是不菲的,不合理的使用内存有可能发生频繁的swap,频繁swap的代价是惨痛的。所以回过头来看,作为有追求的程序员,我们还是要小心翼翼地使用好每块内存,把用户代码能解决的问题尽量不要抛给操作系统解决。

 所以,为了更好的利用内存,使Redis存储的都是缓存的热点数据,Redis设计了相应的内存淘汰机制(也可以叫做缓存淘汰机制)。

配置文件常见修改

开启淘汰机制

 我们可以通过配置redis.conf中的maxmemory这个值来开启内存淘汰功能

maxmemory <bytes>

修改淘汰策略

根据应用场景,选择淘汰策略

maxmemory-policy noeviction

常见命令修改(动态、无需重启)

设置最大内存

config set maxmemory 100000

设置淘汰策略

config set maxmemory-policy noeviction

内存淘汰的过程是

  1. 首先,客户端发起了需要申请更多内存的命令(如set)。
  2. 然后,Redis检查内存使用情况,如果已使用的内存大于maxmemory则开始根据用户配置的不同淘汰策略来淘汰内存(key),从而换取一定的内存。
  3. 最后,如果上面都没问题,则这个命令执行成功。

提示:maxmemory为0的时候表示我们对Redis的内存使用没有限制。

数据删除策略有三种

  1. 被动删除:只有key被操作时(如GET),Redis才会被动检查该key是否过期,如果过期则删除之并且返回NIL。
  2. 主动删除:定期删除过期的数据,可以配置
  3. 当前已用内存超过maxmemory限定时,触发数据淘汰策略

被动删除特点

  1. 这种删除策略对CPU是友好的,删除操作只有在不得不的情况下才会进行,不会其他的expire key上浪费无谓的CPU时间。
  2. 但是这种策略对内存不友好,一个key已经过期,但是在它被操作之前不会被删除,仍然占据内存空间。如果有大量的过期键存在但是又很少被访问到,那会造成大量的内存空间浪费。

Redis提供了6种数据淘汰策略

  1. volatile-lru从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。注意:redis并不是保证取得所有数据集中最近最少使用的键值对,而只是随机挑选的几个键值对中的, 当内存达到限制的时候无法写入非过期时间的数据集。
  2. volatile-ttl从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰。注意:redis 并不是保证取得所有数据集中最近将要过期的键值对,而只是随机挑选的几个键值对中的, 当内存达到限制的时候无法写入非过期时间的数据集。
  3. volatile-random从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰。当内存达到限制的时候无法写入非过期时间的数据集。
  4. allkeys-lru从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰。当内存达到限制的时候,对所有数据集挑选最近最少使用的数据淘汰,可写入新的数据集。
  5. allkeys-random从数据集(server.db[i].dict)中任意选择数据淘汰,当内存达到限制的时候,对所有数据集挑选随机淘汰,可写入新的数据集。
  6. no-enviction当内存达到限制的时候,不淘汰任何数据,不可写入任何数据集,所有引起申请内存的命令会报错。

淘汰策略选择

根据使用经验, 一般来说回收策略可以这样来配置:

  • allkeys-lru:如果期望用户请求呈现幂律分布(power-law distribution),也就是,期望一部分子集元素被访问得远比其他元素多时,可以使用allkeys-lru策略。在你不确定时这是一个好的选择
  • allkeys-random:如果期望是循环周期的访问,所有的键被连续扫描,或者期望请求符合平均分布(每个元素以相同的概率被访问),可以使用allkeys-random策略。
  • volatile-ttl:如果你期望能让 Redis 通过使用你创建缓存对象的时候设置的TTL值,确定哪些对象应该是较好的清除候选项,可以使用volatile-ttl策略。

另外值得注意的是,为键设置过期时间需要消耗内存,所以使用像allkeys-lru这样的策略会更高效,因为在内存压力下没有必要为键的回收设置过期时间。

非精准的LRU

上面提到的LRU(Least Recently Used)策略,实际上Redis实现的LRU并不是可靠的LRU,也就是名义上我们使用LRU算法淘汰键,但是实际上被淘汰的键并不一定是真正的最久没用的,这里涉及到一个权衡的问题,如果需要在全部键空间内搜索最优解,则必然会增加系统的开销,Redis是单线程的,也就是同一个实例在每一个时刻只能服务于一个客户端,所以耗时的操作一定要谨慎。为了在一定成本内实现相对的LRU,早期的Redis版本是基于采样的LRU,也就是放弃全部键空间内搜索解改为采样空间搜索最优解。自从Redis3.0版本之后,Redis作者对于基于采样的LRU进行了一些优化,目的是在一定的成本内让结果更靠近真实的LRU。

Redis热点数据问题

问题:由于内存限制,导致了Redis中只能存储最多1W条的数据信息,如何确保这1w条数据是最热门的数据?

解决方案

  1. 热点数据排序(点击次数)
    既然热门数据,那么就需要有排序,使用redis中的zset数据类型是很自然的想法。数据中的某个唯一字段作为zset中的value,而点击次数作为score,记为click_zset。这样就可选出最热门的数据。而数据,则直接用HashMap存储。
  2. 热点数据时间(近期访问)
    既然只能存1w条数据且需要是热门数据,那么,点击次数是一方面,时效性也是一方面,如何保证?可以另起一个zset,数据的字段为value,而每次点击时更新当前时间戳为其score,记为time_zset这样,就可以记录时间。在后台跑一个任务,间隔一定时间段删除两个zset中长时间没有发生点击事件的键,并删除hash数据,为产生的新数据腾出数据空间。
  3. 处理新热点数据
    如果有空间,则保存到自己的hashmap,并将key存到两个zset中。
    而没有空间时,就应该在click_zset中取出点击次数排在最前第1w位后面的键,删除对应的hash数据。然后看这1w个score的值,然后把key放入两个zset中即可。

参考

https://blog.csdn.net/u013679744/article/details/79203933

https://www.cnblogs.com/chenpingzhao/p/5022467.html

http://blog.720ui.com/2016/redis_action_02_maxmemory_policy/

http://ifeve.com/redis-lru/

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Another Redis Desktop Manager是一个用于管理Redis数据库的图形化工具。它是Redis Desktop Manager的一个分支,提供了类似的功能,但在某些方面更加完善。你可以使用Another Redis Desktop Manager来连接和管理Redis服务器,执行命令,查看和编辑键值对,监视服务器状态等。它还提供了一些高级功能,如导入和导出数据,执行Lua脚本,查看慢查询日志等。你可以通过以下步骤来使用Another Redis Desktop Manager: 1. 下载和安装Another Redis Desktop Manager:你可以从官方网站(https://github.com/qishibo/AnotherRedisDesktopManager/releases)下载适用于你的操作系统的安装包,并按照安装向导进行安装。 2. 启动Another Redis Desktop Manager:安装完成后,你可以在应用程序菜单中找到Another Redis Desktop Manager,并点击启动。 3. 连接到Redis服务器:在Another Redis Desktop Manager的主界面上,点击左上角的“+”按钮,然后填写Redis服务器的连接信息,包括主机名、端口号、密码等。点击“连接”按钮,连接到Redis服务器。 4. 管理Redis数据库:连接成功后,你可以在左侧的导航栏中看到Redis服务器的数据库列表。点击数据库,可以查看和编辑键值对,执行命令等。 5. 使用其他功能:除了基本的键值对管理,Another Redis Desktop Manager还提供了其他一些功能,如执行Lua脚本、导入和导出数据、查看慢查询日志等。你可以在菜单栏或工具栏中找到这些功能,并根据需要使用它们。 请注意,以上步骤仅为一般指导,具体操作可能会因版本和配置而有所不同。建议你参考Another Redis Desktop Manager的官方文档或用户手册,以获取更详细的信息和指导。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值