我需要在我的应用程序中保留一个对象(JSON)一段时间(通常为180秒)在某些时候,客户端可能会或可能不会返回并通过其密钥请求此对象。
棘手的部分是我需要在此对象过期时收到通知,因此如果客户端尚未请求它,我可以将其返回到可用池。
显而易见的解决方案是在数据库中使用类似时间戳的内容,然后使用定期脚本来检查过期项目,但这不是最好的解决方案。
理想情况下,我正在寻找像memcache这样的东西可以在一个项目到期时调用一个事件,肯定有这样的产品吗?
我目前的框架基于python,cherrpy,mongo,memcachce,但我很乐意添加它。
答案 0 :(得分:1)
除非有其他进程将使用此对象池,否则在您需要分配一个对象之前,似乎没有理由将过期的对象返回到池中。如果检查过期对象并在分配新对象之前将它们返回到池中,则应该充分覆盖清理。
为了简化清理本身,请考虑创建(expire_time,object)元组列表并使用 bisect.insort()来保持列表按第一个值排序 - 过期时间:
que_tuple = (time.time() + EXPIRY_DELAY, obj)
bisect.insort(my_list, que_tuple)
每次去保留另一个对象时,都可以检查过期的项目是否返回到池中。通过使用排序列表,您只需检查第0个元素是否已过期,然后按顺序清除元素,直到找到未过期的元素。像这样:
time_to_act, obj = my_list[0]
while time.time() > time_to_act:
return_to_pool( obj ) # whatever is necessary to clean-up your objects
my_list.pop(0)
time_to_act, obj = my_list[0]
如果确定您确实需要实现计时器,则此队列概念仍然有用。否则,您可以为每个对象的到期时间设置一个计时器。通常,可用的系统计时器数量有限,您可能会发现自己的资源不足。到期队列(my_list)允许单个计时器宣布下一个到期对象,并且计时器将重置为列表的新头部。
我希望这有帮助!
答案 1 :(得分:0)
我可能会使用threading.Timer
。 Timer
对象将在一段时间后使用给定的参数调用指定的函数。因此,编写一个将JSON对象返回给池的函数,并启动一个指定已保留的特定JSON对象的计时器。此外,您可以在计时器触发之前取消计时器,如果客户端在预订到期之前实际请求该对象,您将要执行该计时器。
为了跟踪池,我可能会使用dict
,其中JSON对象是键,如果对象未签出,则值为None
,或{{1实例,如果它被检出。可以使用单独的Timer
来跟踪下一个应该发出的对象;当一个物体被取出时,从列表末尾开始list
,当它返回时,pop()
重新开始。请注意更新这两种结构的可能竞争条件!
答案 2 :(得分:-1)
我几乎可以肯定围绕redis expire命令的解决方案应该是必要的。它使用起来很简单。以下是使用Redis cli的示例。
redis> HMSET myhash field1 "Hello" field2 "World"
OK
redis> HGET myhash field1
"Hello"
redis> EXPIRE myhash 180
(integer) 1
redis> HGET myhash field2
"World"
redis> HGET myhash field2 # after 180 secs
(nil)
此外,Python有各种redis客户端选项。 redis-natives-py提供注释@temporary(after = None,at = None)。
通知部分
Redis不会通知你。可能是应用程序有逻辑假设在N秒后过期,是的,你可以随时用不昂贵的EXISTS命令确认。其他选择可能是使用greenlets来注意时间。就像它创建redis对象一样,睡眠N秒并唤醒确认redis并通知。我建议greenlet主要是因为它比Python线程更轻量级。