Tokyo Tyrant 通常简称ttserver,是一个可以保存到硬盘上的key-value程序,接口兼容memcache协议,百科介绍如下

Tokyo Tyrant 是由同一作者开发的 Tokyo Cabinet 数据库网络接口。它拥有Memcached兼容协议,也可以通过HTTP协议进行数据交换
Tokyo Cabinet 是一款 DBM 数据库,该数据库读写非常快,哈希模式写入100万条数据只需0.643秒,读取100万条数据只需0.773秒,是 Berkeley DB 等 DBM 的几倍
http://fallabs.com/tokyotyrant/

ttserver 在2009-2010年之间非常流行,原因如下

  1. 诞生于memcache之后,redis之前,市场空白,时机比较好,特别是微博这种重度交互的web产品当时正处于上升期,有强烈的KV永久存储需求,sina自己也搞了一个 Memcachedb
  2. 兼容memcache协议,学习成本低

但是ttserver 是我用过的最垃圾的开源软件,在3家公司都遇到过ttserver导致的故障

  1. 在神奇网站,用tt来存储用户密码对,某天我把tt的一个从库和一个sphinx实例部署在一起,整个服务完全挂掉(这个sphinx实例之前是和一个mysql从库部署在一块的,完全没有问题)
  2. 在某微博,用ttserver保存运营数据,某一天tt挂掉之后,1.5G的数据再也找不回来

当时不求甚解,换掉就是,最近把ttserver的代码打开读一遍,才发现果然如此 这个日本人完全不会写服务器程序

Tokyo Tyrant的网络IO模型

  1. 采用多线程模式 -- 学习的memcached
  2. 主线程socekt/bind/listen 开启服务器socket,然后生成N个worker thread

这看起来都很正常,奇葩来了

  1. 主线程和子线程共用一个event_base,子线程如果要调用epoll_ctl来修改event状态,那么先用 pthread_mutex_lock锁住,这个大概会锁100行代码,其中包含
    N个do/while
  2. 新连接和client read事件都这个epoll里面等待,server write却在每个thread中用select来等待可写时机
  3. 代码里面各种冷僻的pthread_xxx 函数满天飞,比如说用 pthread_cleanup_push 来对处理线程挂掉之后干资源释放的活,让人感慨,这样写多线程程序,只能不断的用pthread_cleanup_push来擦屁股

敝扫自珍

ttserver里面有一个socket的队列,主线程accept新连接,就放到这个队列里面--这个也是向memcached致敬
一般人大概会定义std::queue<socket_t> _qs

这个日本人用自己的数据结构叫做 TCLISTDATUM,为了把socket存到这个TCLISTDATUM结构里面,代码如下


typedef struct {                         /* type of structure for an element of a list */
  char *ptr;                             /* pointer to the region */
  int size;                              /* size of the effective region */
} TCLISTDATUM;

// array[index] is instance of TCLISTDATUM
memcpy(array[index].ptr, socket, sizeof(socket));
array[index].ptr[size] = '\0';
array[index].size = size;

Tokyo Cabinet 的代码就不去看了,必然垃圾

本文地址: http://lutaf.com/221.htm 鲁塔弗原创文章,欢迎转载,请附带原文链接