Memcachedb TTL的实现
Memcachedb没有 TTL,无法实现 expire超时,虽然有很多理由
http://osdir.com/ml/memcachedb/2009-06/msg00012.html
http://osdir.com/ml/memcachedb/2009-06/msg00010.html
但是, TTL在某些应用场景里总是需要的,比如用 cache存储认证信息 ~~~
没办法,只能自己来做了,首先是 TTL value存储的问题,由于 memcachedb直接对 memcached协议里的 expire time忽略,肯定是指望不上它了(除非改 memcachedb的代码),不过 memcached里还有个 flag,嘿嘿,就用它来存储吧。
- <flags> is an arbitrary 16-bit unsigned integer (written out in
decimal) that the server stores along with the data and sends back
when the item is retrieved. Clients may use this as a bit field to
store data-specific information; this field is opaque to the server.
Note that in memcached 1.2.1 and higher, flags may be 32-bits, instead
of 16, but you might want to restrict yourself to 16 bits for
compatibility with older versions.
而且 memcachedb使用了 int来表示 flags,这在 32位或 64位都足够存放 TTL了 J
所以最简单的 TTL方法来了:
- 封装一下 client的 get/set系列 API( add/replace/prepend/append都要包咯)
- set时把 TTL直接放到 flags里( TTL=当前时间戳 +超时时长)
- get时从 flags里取出 TTL,和当前时间戳比较,如果 TTL>当前时间戳, delete这个 key,返回空,否则返回 value
- 做个定时任务,每天夜里做一次 garbage collection(也可以定更长或更短的时间,看需要了,我的理解不需要太短的时间,因为有 的问题只是多占点空间(只有没被 get的才会,否则会被 delete掉)这个定时任务可以:
- 用 rget枚举所有 key,检查 TTL,如果 TTL>当前时间戳就 delete
rget枚举的方法也比较 tricky了,这里谈一下想法。
rget是 memcachedb 1.2.1-beta引入的,其实不是做枚举的,而是做 range query。
rget <start key> <end key> <left openness flag> <right openness flag> <max items>/r/n
- <start key> where the query starts.
- <end key> where the query ends.
- <left openness flag> indicates the openness of left side, 0 means the result includes <start key>, while 1 means not.
- <right openness flag> indicates the openness of right side, 0 means the result includes <end key>, while 1 means not.
- <max items> how many items at most return, max is 100.
rget是以字母序返回的,这也是为什么可以指定 <start key>和 <end key>的原因,能用 rget枚举的前提是知道 key的取值范围,比如如果 key的首字母是字母或数字,那可以用 0-z来指定范围(这个其实是有点问题的, <end key>指定 z的话, key为 zz的就取不出来了,更合适的是 {( ascii字符 z后面一个))
另一个解决 range的方法是所有的 key前面都以特定字符开始(比如 t),这个也可以在前面的 get/set封装里解决,这样 <start range><end range>只要指定 t-s就 ok了,对 key也没有任何要求
另一个 rget的问题是它的 <max items>最大只能支持 100个,这样一次是无法枚举出所有内容的,不过解决这个 too easy了,上伪码:
期待 memcachedb自己加上 TTL的支持,至少加上 garbage collection的 thread~~~