Python 添加';对象';添加到带有过期计时器的堆栈,并在过期时收到通知

Python 添加';对象';添加到带有过期计时器的堆栈,并在过期时收到通知,python,caching,Python,Caching,我需要在我的应用程序中保留一个对象(JSON)一段时间(通常为180秒),在某个时间点,客户端可能会回来,也可能不会通过其密钥请求该对象 棘手的是,当这个对象过期时,我需要得到通知,这样如果客户端还没有请求它,我就可以将它返回到可用池中 显而易见的解决方案是在数据库中使用时间戳之类的东西,然后使用周期脚本来检查过期的项目,但这并不是最好的解决方案 理想情况下,我正在寻找像memcache这样的东西,它可以在项目过期时调用事件,肯定有这样的产品吗 我目前的框架是基于python、cherrpy、m

我需要在我的应用程序中保留一个对象(JSON)一段时间(通常为180秒),在某个时间点,客户端可能会回来,也可能不会通过其密钥请求该对象

棘手的是,当这个对象过期时,我需要得到通知,这样如果客户端还没有请求它,我就可以将它返回到可用池中

显而易见的解决方案是在数据库中使用时间戳之类的东西,然后使用周期脚本来检查过期的项目,但这并不是最好的解决方案

理想情况下,我正在寻找像memcache这样的东西,它可以在项目过期时调用事件,肯定有这样的产品吗


我目前的框架是基于python、cherrpy、mongo和memcachce的,但我很乐意添加到其中。

我可能会使用
线程。Timer
Timer
对象将在一段时间后调用具有给定参数的指定函数。因此,编写一个函数,将JSON对象返回到池中,并启动一个计时器,指定已保留的特定JSON对象。此外,您可以在计时器启动之前取消计时器,如果客户机在保留过期之前实际请求对象,则需要执行此操作


为了跟踪池,我可能会使用
dict
,其中JSON对象是键,如果对象未签出,则值为
None
;如果对象已签出,则值为
Timer
实例。一个单独的
列表
可以用来跟踪下一步应该给出什么对象<代码>弹出()从列表末尾取出对象,并在返回对象时将其重新打开。当心更新这两种结构的可能竞争条件

我几乎可以肯定,围绕redis命令的解决方案应该能够满足需要。它使用起来很简单。下面是使用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客户端选项。提供注释@temporary(after=None,at=None)

通知部分


Redis不会通知你的。可能是应用程序有逻辑假设N秒后到期,是的,您可以随时用不昂贵的EXISTS命令确认。另一个选择可能是使用greenlet来关注时间。就像它创建redis对象一样,休眠N秒,然后用redis和notify唤醒confirm。我之所以建议使用greenlet,主要是因为它比Python线程轻得多。

除非有其他进程将使用此对象池,否则似乎没有理由在需要分配对象池之前将过期的对象返回到该池。如果在分配新对象之前检查过期对象并将其返回到池中,则应充分涵盖清理

<> P>为了简化清理本身,考虑创建一个列表(ExpReiTimeTime,Object)元组,并使用<强> BISECT.IOSUTE()<强> >使列表按第一个值排序——期满时间:

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)允许单个计时器宣布下一个过期对象,计时器将重置为列表的新头


我希望这有帮助

我认为Redis应该这样做,但我从未使用过它,我唯一的问题是当对象过期时,它能以某种方式通知应用程序吗?在我的答案中添加了通知建议。