代码改变世界

Memcached遍历Key

2011-04-01 13:21 by Sun Yongyue, ... 阅读, ... 评论, 收藏, 编辑
     前段时间XX升级之后出了点小问题,最后定位到是缓存数据格式变动造成的。当时就想要个工具去把memcached里的key拿出来看,之后虽然没有用上,但自己还是写了个,以备后用。

    目前功能比较简单,只是遍历所有的key,稍加修改可以 1)取出指定格式(正则等)的key;2)显示value。交互可以更好一点:)

1 # -*- coding:utf-8 -*-
2  import telnetlib
3  import re
4  def send(tn, cmd):
5 tn.write(cmd + "\r\n")
6 return tn.read_until("END\r\n")
7 HOST = "localhost"
8 PORT = 31211
9 tn = telnetlib.Telnet(HOST, PORT)
10 slabs = send(tn, "stats slabs")
11 chunk_pattern = "STAT (?P<type>\d+):chunk_size \d+\r\nSTAT \d+:chunks_per_page \d+\r\nSTAT \d+:total_pages \d+\r\nSTAT \d+:total_chunks (?P<total>\d+)\r\nSTAT \d+:used_chunks \d+\r\nSTAT \d+:free_chunks \d+\r\nSTAT \d+:free_chunks_end \d+\r\n"
12 key_pattern = "ITEM (\S+) \[(\d+) b; (\d+) s\]"
13 ret = re.findall(chunk_pattern, slabs)
14 cnt = 0
15  import datetime
16  for obj in ret:
17 cmd = "stats cachedump %s %s" % (obj[0], obj[1])
18 dump = send(tn, cmd)
19 keys = re.findall(key_pattern, dump)
20 for key in keys:
21 print "%s, %s, %s" % (key[0], key[1], datetime.datetime.fromtimestamp(float(key[2])))

ps: 网上已经有很多类似实现,好吧,我out了。

2011-04-08更新:stats cachedump 输出最多为2MB,超出部分无法得到,这个时间只能显示前边部分key:(。还没看到其他命令可以获取。

    // 留意此值为回送内容的最大字节数,当回送内容达到2M时,即使没有达到用户想要的item数也会返回
    int memlimit = 2*1024*1024;
    ……
        // !!! alert:  回送内容最多为2M
        if (bufcurr + len + 6 > memlimit)  /* 6 is END\r\n\0 */
            break;
    ……

9号晚在google上搜索别人的实现,找到一个Xmemcached客户端,在1.2.2版本后支持遍历所有Key。大喜,但快速阅读相关部分代码后发现一样存在这个问题,跟作者确认过了。附上邮件中的部分内容。

原因是:stats cachedump限制了输出的最大字节数为2M,当某一slab class里的item比较多时,该命令会在输出超过2M前返回。除了key的内容以后,cachedump每条信息需要至少5+2+1+4+10+5=27个字节,贪心的情况下key长度应该为3个字节(理论值),总共30个字节,所以最大可显示的key数量不超过69904.9(理论值)个。