【问题标题】:Configuring redis to consistently evict older data first配置 redis 以始终首先驱逐旧数据
【发布时间】:2012-02-19 02:43:52
【问题描述】:

我在 redis 中存储了一堆实时数据。我在所有键上设置了 14400 秒(4 小时)的 TTL。我已将 maxmemory 设置为 10G,目前内存中的空间不足以容纳 4 小时的数据,而且我没有使用虚拟内存,因此 redis 在数据过期之前将其逐出。

我同意 redis 驱逐数据,但我希望它首先驱逐最旧的数据。因此,即使我没有完整的 4 小时数据,至少我可以拥有一定范围的数据(3 小时、2 小时等),其中没有间隙。我试图通过设置maxmemory-policy=volatile-ttl 来实现这一点,认为最旧的键将首先被驱逐,因为它们都具有相同的 TTL,但它不是那样工作的。看来 redis 有点武断地驱逐数据,所以我的数据最终出现了空白。例如,今天 2012-01-25T13:00 的数据在 2012-01-25T12:00 的数据之前被驱逐。

是否可以将 redis 配置为始终先驱逐旧数据?

这是我的 redis.cnf 文件中的相关行。如果您想查看更多配置,请告诉我:

maxmemory 10gb
maxmemory-policy volatile-ttl
vm-enabled no

【问题讨论】:

    标签: caching redis


    【解决方案1】:

    AFAIK,无法将 Redis 配置为始终首先驱逐旧数据。

    当在 maxmemory-policy 中选择 *-ttl 或 *-lru 选项时,Redis 不会使用精确的算法来选择要删除的键。精确的算法需要内存中的额外列表(对于 *-lru)或额外的堆(对于 *-ttl),并将其与正常的 Redis 字典数据结构交叉引用。在内存消耗方面会很昂贵。

    使用当前机制,驱逐发生在主事件循环中(即在执行每个命令之前,在每次循环迭代中检查潜在的驱逐)。直到内存回到 maxmemory 限制之下,Redis 随机选择一个包含 n 个键的样本,并选择最空闲的一个(对于 *-lru)或最接近其过期限制的一个(对于 *-ttl)作为过期。默认情况下,仅考虑 3 个样本。结果是不确定的。

    提高此算法的准确性并缓解问题的一种方法是增加考虑的样本数量(配置文件中的 maxmemory-samples 参数)。 不要将它设置得太高,因为它会消耗一些 CPU。这是驱逐准确性和 CPU 消耗之间的权衡。

    现在,如果您确实需要一致的行为,一种解决方案是在 Redis 之上实现您自己的驱逐机制。例如,您可以添加一个列表(对于不可更新的键)或一个排序集(对于可更新的键),以便跟踪应该首先被驱逐的键。然后,添加一个守护进程,其目的是定期检查(使用 INFO)内存消耗并查询列表/排序集的项目以删除相关键。

    请注意其他缓存系统有自己的方法来处理这个问题。例如对于 memcached,每个slab 有一个 LRU 结构(这取决于对象大小),因此驱逐顺序也不准确(尽管在实践中比 Redis 更具确定性)。

    【讨论】:

    • 感谢简洁的回答。现代 Redis 现在是一致的还是使用相同的驱逐策略?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 2020-10-13
    • 2018-03-23
    • 1970-01-01
    相关资源
    最近更新 更多