使用memcache实现高并发计数器
2009 12 23 12:10 PM 8046次查看
分类:Google App Engine 标签:Google App Engine
思路很简单,使用2个memcache,一个用于存储增加的计数器,另一个用于上锁。
锁有时间限制,如果未到期,那么就更新memcache里的计数器;如果到期,就创建一个新锁,并把memcache里的值增加到数据库里,并删除现有的memcache里的计数器。
实现代码如下(我稍微改了下):
def incrementCounter(key, update_interval=10):
"""Increments a memcached counter.
Args:
key: 数据库里计数器实体的key.
update_interval: 更新频率.
"""
lock_key = "counter_lock:%s" % key
count_key = "counter_value:%s" % key
if memcache.add(lock_key, None, time=update_interval):
count = int(memcache.get(count_key) or 0) + 1
def tx():
entity = db.get(key)
entity.counter += count
entity.put()
db.run_in_transaction(tx)
memcache.delete(count_key)
else:
memcache.incr(count_key, initial_value=0)
注意那个memcache.add函数,如果未到期,那么加锁失败,直接增加memcache的值;如果到期,那么加锁成功,更新memcache到datastore。这种方法可能存在这些缺陷:
- 如果计数频率太低,会导致memcache几乎没用,每次都得更新数据库。这比直接访问数据库多用了3次memcache操作。
- 如果memcache里的计数器过期,那就会丢失更新间隔内的计数值。但一般是计算频率过低导致的,而频率越低,丢失的计数值就越小。
- 需要真正的计数值时,需要同时访问datastore和memcache。
- 在更新数据库和删除memcache里的计数器时存在不同步,可能丢失计数值。解决办法是把delete函数改成decr函数,剪掉之前获取的计数值即可。不过这样就会长期占用memcache了。
0条评论 你不来一发么↓