memcached批量删除方案探讨
来源:互联网 发布:php一句话木马制作 编辑:程序博客网 时间:2024/06/15 18:55
转自:http://it.dianping.com/memcached_item_batch_del.htm
Memcached是开源的分布式cache系统,现在很多的大型web应用程序包括facebook,youtube,wikipedia,yahoo 等等都在使用memcached来支持他们每天数亿级的页面访问。通过把cache层与他们的web架构集成,他们的应用程序在提高了性能的同时,还大大降低了数据库的负载。
如果您还对memcached还不是很了解,请先阅读:
- 利用memcached构建高性能的Web应用程序
本文中我们将集中探讨如何对memcached中存储的cache进行高效管理。在我们实际项目中,由于网站经常需要更新,而cache难免会发生与数据库不同步却仍然还有效的情况,那网站管理员就有需求对某个或某些cache进行手工清理。
比如,大众点评的每个商户页面都利用了cache,并存成键值为Shop.[ShopID]的cache对象。如果一个商户ID为1234的页面cache有问题,我们就可以通过Remove(”Shop.1234”)方法通知memcached清掉对应的cache对象。
但问题又随之而来了,有时候我们发现有一批cache都存在问题而没有及时过期。此时我们会面临一个两难的选择:
- 通过flush_all清掉所有的cache
这种做法很黄很暴力…把有问题和没问题都一起kill掉了…
- 找出这一批cache中所有的key值并逐一进行清理
这种做法看似不错,但没有好的办法实现。因为memcached是hash表结构,无法提供像sql里select from where的操作,所以你不知道这批数据到底有多少已经存进了cache
暴力法我们肯定是不能主动考虑的,否则也不用这篇文章了,呵呵。所以我们看看有没有可行的方案来实现方法2。
LogDB方案
这个方案说起来也很简单。既然memcached没有select操作,我们就用db去记录所有的Cache SET操作。只要memcached存了一个cache对象进instance,就同时往logdb上写一条记录。
等到要删除的时候,我们就通过select操作,找出所有Shop.xxxx的商户,并逐一进行remove操作。
这种办法虽然可以达到精确删除的目的,但是所消耗的代价也未免有些过高,为了清除key还要另外拉个数据库进来做辅助。而且cache的存取量是很大的,说不定数据库频繁的insert操作还会成为另一个潜在的性能瓶颈。此方案在硬件条件不是很充裕的条件下谨慎使用。
自定义keylocator方案
了解memcached的读者都知道,cache对象分配到哪个instance是由memcached客户端决定的。而memcached客户端默认的分配算法是SHA-1散列算法。所以默认情况下,商户类的cache对象(Shop.xxxx)是被散列到不同的memcached instance上的。
(X:User100,Shop202 Y:User101,Shop200 Z:User102,Shop201)
假如我们可以自定义这个分配算法,将Shop.xxx类的cache对象都同一存到某一个instance或某几个instance下,这样我们就通过清掉这些Shop.xxx专用的instance来达到批量清楚的目的。
(X:User100 Y:Shop200,Shop201,Shop202 Z:User101,User102)
这个方案看似不错,其实还是有不少衍生问题的:
- 使用率不均问题:
从上面两个例子就可以看到,前面通过散列算法存放,每个instance都放了两个对象,但是采用自定义的办法,instance Y就存了3个,X才存了1个。如果自定义的locator在实现之前不能够通盘考虑各类key的使用率的话,很容易造成instance使用不均的问题。
- 负载率不均问题:
有些热门类的key读取率很高,因为原本是散列在各个服务器上,读取负载也就自然地分解到各个服务器上。现在采用专用服务器模式的话,所有的读取操作就限制在某一台服务器上,无疑是加大了这台服务器的负担。
Key flag 方案
这个方案是眼下笔者认为最简单有效的一个办法,通过在key上做标记来实现懒清理。其实这种做法也是很合memcached的胃口的,之前的文章就介绍过,memcached server的清理策略就是懒清理。
让我们看一下实际的例子:
我们在所有的key后面都带一个版本标记,“Shop.200_1”代表商户ID为200,版本号为1的缓存。一旦有需要对所有的商户类缓存进行清理的话,我们只需要升级一下Shop类缓存的版本就可以做到。
上例中,商户类缓存版本都升级到2了,读取的key值也发生了变化。所以原来的Shop.xxx_1的缓存就永远不会再被读取到,也就等同于失效了。
这样做还有个好处就是,不需要进行批量删除的操作,而耗费大量的维护时间。那些过时版本的cache会根据LRU原则,只要cache一满,他们就会自动被剔除,不需要我们还劳神劳力地去伺候他们。
所以,在memcached这个圈子里也有个原则就是,不用的话就别去管它…它自己会消失的。
说道这个方案不足的话,我想也就是key的长度不得不进行加长来包含版本号,不过这方面会带来的性能影响是微乎其微的。
memcached的批量清理一直是个比较麻烦的问题,希望以上几种方案的探讨能给您带来一些启发。
- memcached批量删除方案探讨
- memcached批量删除方案探讨
- memcached缓存批量更新解决方案探讨
- Memcached如何实现高性能批量删除
- java memcached客户端,模糊查询/批量删除/查询所有的key
- SSO 实现方案探讨
- memcached分布式布置方案
- Memcached分布式布置方案
- 批量删除
- 批量删除
- 批量删除
- 批量删除
- 批量删除
- 批量删除
- 批量删除
- 批量删除
- 批量删除
- 批量删除
- x & (x - 1)==0
- 日期转换,获取一天最早和最晚的日期。
- GetPrivateProfileString用法和例子
- 批量下载Android源代码
- 从最近一个项目中的问题产生的新认识
- memcached批量删除方案探讨
- 正方形计数 count
- 解决局域网客户端固定IP的问题
- BNU - Choosing a camera - 数据结构 (线段树、队列)
- Ubuntu Linux下android源码下载方法
- C语言中11种赋值运算符的具体含义
- 线段树专题
- 关于Ext.data.ArrayStore的用法
- 网页设计趋势:模糊背景在网站中的经典应用案例