Home > $Programming, server & system > 导出Memcached中的全部数据

导出Memcached中的全部数据

Update(Mar 18th, 2011) 最近,我们针对数十个Memcached集群(数据从几G到几十G)进行了数据转换工作,虽是不得已而为之,但是整个过程还算顺利。编写导出脚本需注意的是cachedump得到的很多key其实已经过期了,这部分过期的key要通过get()操作,将之从Memcached中清除,使之不再出现在下次的cachedump中。
================================================================

因为特别的原因,需要从Memcached中导出所有的数据。因为Memcached对数据的遍历是明确不支持的,所以必须想歪门邪道的方法。

现在网络上主要有两种思路,一种是通过Memcached提供的stats cachedump命令导出,例如下面这些网址:

以上文章都利用这个命令导出了部分数据。但事实上,cachedump的输出会限制在 2*1024*1024=2M 字节的长度内(Memecahed source: items.c, func: do_item_cachedump),其导出的格式如下所示:

ITEM key990017 [1 b; 1270394155 s]
ITEM key990016 [1 b; 1270394155 s]
ITEM key990015 [1 b; 1270394155 s]
ITEM key990014 [1 b; 1270394155 s]

即使不计算key的长度,每一条数据至少要占掉近三十个字节,2M最多到几万项数据。对于Item数量很大的情况下,这种方法并不能导出全部数据。

下面的地址佐证了这些观点。

第二种思路来自 Twitter infrastructure team 的 Evan Weaverpeeping into memcached , 利用 linux 的 ptrace 系统调用导出memcached进程中数据,分析这些数据得到memcached的所有Key。

但是这种方式有其限制的,一方面,编译Memcached时必须编译入调试信息 (参见link); 另一方面,在分析时对内存消耗太大。我们对一个只使用了64M内存、含有76万左右数据项的Memcached进程进行分析,在完成23万左右数据项时,分析进程占用内存的达到1040M,导致虚拟机内存用满,关闭了该进程。

因为我们现在运行的memcached是不带编译符号的,所以放弃了第二种方式。 第一种方式,则只能考虑怎么将slabs中的数据分批导出来。 Memcached 支持一个可选的 slabs reassign 命令,可以将一个slab内的数据项移动到其他slab。但这个命令必须在编译 memcached 时加入该特性。

最后,还是利用了第一种方法,每一次导出一批数据以后就从memcached中删除这一批数据,直到全部导出为止。 虽然这种办法很土,但是还是能够应付一次性数据迁移。 当然这是不得以而为之,明智的做法还是在一开始就不要将需要持久化的数据持久化到其他服务中,而不是只存放于memcached中。

Related posts:

  1. Flex中的对象比较(相等性)
  2. 解决Java序列化的版本冲突
  1. 渔戈
    September 16th, 2010 at 18:52 | #1

    坪溪你好!

    Memcached 支持一个可选的 slabs reassign 命令,可以将一个slab内的数据项移动到其他slab。但这个命令必须在编译 memcached 时加入该特性。

    请问这个特性是怎样加入的呢?
    烦请不吝赐教啊

    • Zhaoren
      September 16th, 2010 at 22:23 | #2

      编译选项ALLOW_SLABS_REASSIGN已经正式在1.4.2版本中删除。不再推荐使用。参考Memcached的开发人员dormando 的评论

      即使是此前的版本,似乎也不能顺利编译。你可以参考这里

  2. 渔戈
    September 17th, 2010 at 10:17 | #3

    Zhaoren :
    编译选项ALLOW_SLABS_REASSIGN已经正式在1.4.2版本中删除。不再推荐使用。参考Memcached的开发人员dormando 的评论
    即使是此前的版本,似乎也不能顺利编译。你可以参考这里

    坪溪,你好 在memcached.h中添加ALLOW_SLABS_REASSIGN预定义 确实不能顺利编译,经过修改slabs.c可以编译成功,但是使用slabs reassign 仍然不能移动
    # Item_Size Max_age 1MB_pages Count Full?
    1 88 B 699 s 2 23830 yes
    3 144 B 0 s 2 0 no
    4 184 B 1541 s 1 5698 yes

    这是我的测试数据,在mc启动时分配5M内存,然后手动生成了一些数据,set到mc中,现在不论我是执行
    slabs reassign 3 1 还是slabs reassign 3 4 都提醒CANT

    请问你使用reassign命令时有没有遇到类似的问题呢?

  3. Zhaoren
    September 17th, 2010 at 11:22 | #4

    没有发生过错误。你编译的啥版本?

  1. No trackbacks yet.