使用memcache实现高并发计数器

在网站中很多场景都有计数的需求,比如找回密码要求一天只能找回10次。如果并发量比较高会导致数据库频繁的更新和查询,可以使用memcached来实现计数器,代码很简单:

使用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了。

实际上如果memcache能提供一个失效事件,每次失效时自动更新到数据库,将会是个很不错的特性。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值