【问题标题】:Redis expiration, memory leak by specification?Redis过期,按规范内存泄漏?
【发布时间】:2015-06-16 11:11:59
【问题描述】:

Redis 为我们提供了EXPIRETTL 函数。根据documentationTTL命令可以用来区分不存在和过期的key:

> SET foo 3
OK
> GET foo
"3"
> EXPIRE foo 5
(integer) 1
> TTL foo
(integer) 3
> TTL foo
(integer) 2
> TTL foo
(integer) 1
> TTL foo
(integer) 0
> TTL foo
(integer) -2

根据EXPIRE specification,过期对象实际上是在访问时从存储中删除的,或者通过定期随机选择过期键:

具体来说,这是 Redis 每秒执行 10 次的操作:

从具有相关过期时间的密钥集中测试 20 个随机密钥。

删除所有发现过期的密钥。

如果超过 25 个密钥过期,请从第 1 步重新开始。

但是-2(或允许生成它以代替-1 的信息)呢?是永久保存还是有垃圾回收政策?

还要注意,如果我们为同一个键设置和删除新值,-2 将继续存在:

> SET foo 3
OK
> ttl foo
(integer) -1
> del foo
(integer) 1
> ttl foo
(integer) -2

因此,例如,假设我们有一个脚本,它不断设置具有递增名称的键并使其在 1 秒后过期。过了任意长的时间,我们会不会耗尽内存?

【问题讨论】:

    标签: memory-leaks redis ttl


    【解决方案1】:

    但是-2(或允许生成它代替-1的信息)呢?是永久保存还是有垃圾回收政策?

    -2表示key不在数据库中,例如:

    127.0.0.1:6379> flushall
    OK
    127.0.0.1:6379> ttl somekey
    (integer) -2
    

    【讨论】:

    • 是的。这就是重点。问题是关于我们如何摆脱-2,因为如果我们为无限键累积-2,我们将耗尽我们的内存。当然,非常缓慢。
    • 不需要额外的内存——它相当于 EXISTS。
    • 好吧,我们已经有了答案,但是……它怎么可能不需要额外的内存呢?某处必须有一个数据结构来回忆哪些键与计时器相关联,否则系统如何记住将-2放在哪里?实现方面,在 redis 中,我希望在某个地方存在一些类似字典的结构,并且过期的键正在使用它的一个插槽。
    • -2 表示密钥不存在 - 它要么已过期,要么一开始就从未创建(请参阅我的答案中的示例)。
    • 知道如果我坚持就会发生;)现在就出去做吧!
    【解决方案2】:

    请参阅Redis as a Least-Recently-Used Cache 上的页面——您可以告诉 Redis 不要超过设定的内存量,并选择多个密钥过期和清除策略之一。

    一个微妙的问题是,并非 Redis 中的所有数据类型都可以很好地处理此问题,但带有 ttl set 的集合应该可以工作。还支持足够的日志记录,以便您在调整时跟踪发生的原因和方式。

    【讨论】:

      猜你喜欢
      • 2012-03-07
      • 1970-01-01
      • 1970-01-01
      • 2012-09-14
      • 2014-08-09
      • 2011-09-26
      • 2012-10-25
      • 2011-01-12
      • 1970-01-01
      相关资源
      最近更新 更多