在不更改过期时间的情况下替换memcached中的项目

时间:2009-09-16 16:22:58

标签: replace memcached

我在memcached上有几个项目应该在创建时间后24小时到期。我需要更新这些项目,同时保持到期时间不变。

我该怎么做?显然,替换功能需要一个到期参数。

2 个答案:

答案 0 :(得分:3)

如果您需要这种类型的到期控制,您需要将存储项目的到期时间与项目本身一起进行。

通常通过序列化层实现此方法。写入memcached的条目存储为条目本身和时间戳。当反序列化该条目时,将检查时间戳,如果它已过期,则读取条目将被丢弃并视为缓存未命中。

[ entry, expiresAt ]

原始memcached条目上的TTL通常设置为无穷大,只能手动或通过LRU策略从缓存中删除条目。

在memcached常见问题解答中,有preventing stampeding requests部分涉及此技术。

答案 1 :(得分:0)

您需要在缓存值时存储它及其原始超时值。这是一个Python实现:

class ExpiringCache(BaseCache):
    """A cache that allows you to update values without changing when the
    data will expire. We do this by storing when the value was
    inserted in the cache and decrementing the timeout when we update.

    """
    def get(self, key, *args, **kwargs):
        raw_value = super(ExpiringCache, self).get(key, *args, **kwargs)

        # we get None on a cache miss, but otherwise it's a 3-tuple
        if raw_value is None:
            return None

        value, start_time, timeout = raw_value
        return value

    def set(self, key, value, *args, **kwargs):
        timeout = kwargs.get('timeout')

        raw_value = (value, now(), timeout)
        super(ExpiringCache, self).set(key, raw_value, *args, **kwargs)

    def update(self, key, value, timeout=None):
        """If this value is still in the cache, update it but reduce the
        timeout. If it's not present, just set it.

        """
        raw_value = super(ExpiringCache, self).get(key)

        if raw_value is None:
            self.set(key, value, timeout=timeout)
            return

        original_value, start_time, original_timeout = raw_value

        if not original_timeout:
            # we are caching without a timeout, so just set the new value
            self.set(key, value, timeout=original_timeout)
            return

        elapsed_time = (now() - start_time).total_seconds()
        remaining_timeout = timeout - elapsed_time

        if remaining_timeout > 0:
            self.set(key, value, timeout=remaining_timeout)