存储在内存中的PHP Stats对象并发更新=数据丢失?
我想把系统中对象的统计数据抽象到一个地方。此时,每个对象在MySQL表中的行上增加一个计数器,即存储在内存中的PHP Stats对象并发更新=数据丢失?,php,apc,Php,Apc,我想把系统中对象的统计数据抽象到一个地方。此时,每个对象在MySQL表中的行上增加一个计数器,即updatesometable SET views=views+1,其中id=? 为了获得显著的性能提升,而不是每次使用对象时都将此更新写入DB,我想使用apc将singleton analytics对象存储在此对象内的内存增量计数器中,并定期将此对象保存回DB 然而,我的理解是对的,如果两个人访问同一个页面并增加stats对象,那么如果他们都$obj->views=$obj->views+1,其中一
updatesometable SET views=views+1,其中id=?
为了获得显著的性能提升,而不是每次使用对象时都将此更新写入DB,我想使用apc将singleton analytics对象存储在此对象内的内存增量计数器中,并定期将此对象保存回DB
然而,我的理解是对的,如果两个人访问同一个页面并增加stats对象,那么如果他们都$obj->views=$obj->views+1
,其中一个视图可能会丢失,因为从apc获得的stats对象将具有相同的总视图计数,它们都增加一个,然后互相覆盖
我该如何解决这个问题?如果您分三步行动:
- 从APC获取条目
- 正在努力
- 将其推回APC
更好的解决方案是为每个计数器设置一个APC条目;并使用函数将其递增 这可能意味着有多个条目(每个计数器一个)——但这也意味着,在大多数情况下(当增加计数器时,这是最容易做到的),您不必关心并发性:APC将为您处理这一问题
唯一需要解决的问题是您何时需要:
- 获取计数器的值
- 将该值存储到数据库
- 然后重置计数器
- 考虑到这种情况不会再次发生(与增量相比,此操作应该非常罕见),并接受释放一点数据
- 自己处理一个锁定机制:
- 创建一个显示“此计数器已锁定”的APC条目
- 执行抓取+数据库操作+重置
- 拆下锁
- 同时,如果其他脚本想要增加计数器,它应该检查锁条目是否存在;如果是这样,等待几毫秒,直到锁被移除
作为两个旁注,现在:
- 在需要几个web服务器的那一天,您可以使用memcached做同样的事情——请参阅
- 在这两种情况下,APC和memcached都是缓存机制,而不是持久数据存储!这意味着他们可以在需要时逐出您的数据(当他们没有足够的内存用于新条目时,或者当您的条目变得太旧时,就会发生这种情况)
- 比MySQL更快
- 保存到磁盘