我在redis中存储了一堆实时数据。我在所有按键上设置的TTL为14400秒(4小时)。我已将maxmemory设置为10G,当前该空间不足以容纳4个小时的数据,而且我没有使用虚拟内存,因此redis在数据过期之前将其逐出。
我可以重新驱逐数据,但我希望它先驱逐最旧的数据。因此,即使我没有完整的4个小时的数据,至少我也可以拥有一定范围的数据(3个小时,2个小时等),没有任何差距。我尝试通过设置来完成此操作maxmemory- policy=volatile- ttl,以为最早的键将被首先退出,因为它们都具有相同的TTL,但这种方式无法正常工作。看来redis任意地驱逐了数据,所以最终我的数据出现了空白。例如,今天从2012-01-25T13:00驱除的数据先于2012-01-25T12:00驱除。
maxmemory- policy=volatile- ttl
是否可以将redis配置为始终一致地逐出旧数据?
这是我的redis.cnf文件中的相关行。让我知道您是否要查看其他配置:
maxmemory 10gb maxmemory-policy volatile-ttl vm-enabled no
AFAIK,无法将Redis配置为始终一致地逐出旧数据。
在maxmemory-policy中选择 -ttl或 -lru选项时,Redis不会使用精确的算法来选择要删除的密钥。一个精确的算法需要在内存中有一个额外的列表(用于 -lru)或一个额外的堆(对于 -ttl),并将其与常规Redis字典数据结构进行交叉引用。就存储器消耗而言,这将是昂贵的。
使用当前机制,在主事件循环中会发生逐出(即在执行每个命令之前,在每次循环迭代中检查潜在的逐出)。在内存返回到最大内存限制以下之前,Redis会随机选择一个n个键的样本,然后选择最空闲的一个(对于 -lru)或最接近其到期限制的一个(对于 -ttl)作为过期。默认情况下,仅考虑3个样本。结果是不确定的。
提高此算法准确性并缓解问题的一种方法是增加考虑的样本数(配置文件中的maxmemory- samples参数)。请勿将其设置得太高,因为它将消耗一些CPU。这是逐出精度与CPU消耗之间的折衷方案。
现在,如果您确实需要一致的行为,一种解决方案是在Redis之上实现自己的驱逐机制。例如,您可以添加一个列表(用于不可更新的密钥)或一个已排序的集合(用于可更新的密钥),以便跟踪应首先收回的密钥。然后,添加一个守护程序,该守护程序的目的是定期检查(使用INFO)内存消耗,并查询列表/排序集中的项以删除相关键。
请注意,其他缓存系统也有自己的方式来处理此问题。例如,对于memcached,每个平板都有一个LRU结构(取决于对象大小),因此逐出顺序也不准确(尽管实际上比Redis更具有确定性)。