关于ttServer的一些整理

Tokyo Cabinet 是一款 DBM 数据库,该数据库读写非常快,哈希模式写入100万条数据只需0.643秒,读取100万条数据只需0.773秒,是 Berkeley DB 等 DBM 的几倍。利用Tokyo Tyrant构建兼容Memcached协议、支持故障转移、高并发的分布式key-value持久存储系统。key-value分布式存储系统查询速度快、存放数据量大、支持高并发,非常适合通过主键进行查询,但不能进行复杂的条件查询。

Tokyo Tyrant 是由同一作者开发的 Tokyo Cabinet 数据库网络接口。它拥有Memcached兼容协议,也可以通过HTTP协议进行数据交换。Tokyo Tyrant 加上 Tokyo Cabinet,构成了一款支持高并发的分布式持久存储系统,对任何原有Memcached客户端来讲,可以将Tokyo Tyrant看成是一个Memcached,但是,它的数据是可以持久存储的。

安装以及配置可参考:http://blog.csdn.net/ctowoo/article/details/4596674

TTserver与memcached相比,具有以下优势:

1)Tokyo Tyrant支持双机互为主辅模式,主辅库均可读写,而Memcachedb目前支持类似MySQL主辅库同步的方式实现读写分离,支持“主服务器可读写、辅助服务器只读”模式。

这里使用 $memcache->addServer 而不是 $memcache->connect 去连接 Tokyo Tyrant 服务器,是因为当 Memcache 客户端使用 addServer 服务器池时,是根据“crc32(key) % current_server_num”哈希算法将 key 哈希到不同的服务器的,PHP、C 和 python 的客户端都是如此的算法。Memcache 客户端的 addserver 具有故障转移机制,当 addserver 了2台 Memcached 服务器,而其中1台宕机了,那么 current_server_num 会由原先的2变成1。

2)日志文件体积小

Tokyo Tyrant用于主辅同步的日志文件比较小,大约是数据库文件的1.3倍,而Memcachedb的同步日志文件非常大,如果不定期清理,很容易将磁盘写满

3)超大数据量下表现出色

但是,Tokyo Tyrant 也有缺点: 在32位操作系统下,作为 Tokyo Tyrant 后端存储的 Tokyo Cabinet 数据库单个文件不能超过2G,而64位操作系统则不受这一限制。所以,如果使用 Tokyo Tyrant,推荐在64位CPU、操作系统上安装运行。

系统架构:

多线程

主线程通过网络接口侦听请求连接,然后将得到的请求放到一个全局的队列中,然后work线程从队列头取出请求进行处理并返回给用户。另外还有一个timer线程,他是用于全局做timeout检测的,这个后面再具体说。

TokyoTyrant vs. Memcached

现在对TT的处理流程有了一个大概了解,其实可以把它和memcache对比一下,他们都支持比较高的并发,他用的是linux原生的epoll.而memcache是用的libevent库,在linux下也是用的epoll。这种异步事件处理机制可以说是专为高并发而生。

不同的是memcache的实现上,每一个线程有一个自己的处理队列,而TT中是总的用一个队列,其实大家可以想像,肯定TT在处理上就会不如MC了。那是当然的,MC是存内存,所以他后面的线程们可以工作得很快,如果上面这样设计,那么如果队列同样长,就会导致经常空队列的情况,但是太长可能又会占用太多资源,而且线程间的同步调度又会需要浪费更多的时间在上面。总的来说是瓶颈不同,memcache基本不存在读写上的瓶颈,所以可以做成多队列的。这是我个人的一点理解。

启动流程

好,言归正传。我们的TT这样设计是没有问题的。上面已经论述。那么他具体的实现是如何的呢,下面我先做一个简单的介绍,以后再对各部分进行深入分析。整个运行流程的开始是在TT/ttutil.c文件的ttservstart函数开始的,他首先创建了主socket用于接受请求。接下来初始化所有线程并进入ttservdeqtasks函数入口运行。其实这时候已经开始不停地在队列的尾部处理请求了,不过现在没有请求,所以就是在空转。

然后构造epoll的描述符。下一步是将上面创建的主socket放到epoll的侦听列表中,开始进入大循环进行整个接收请求工作。

请求处理

当一个请求来到,epoll通知进行通知,如果是对主socket的连接请求,那么主线程会创建一个新的socket然后将它一起放到epoll的侦听列表中。如果这个请求是对派生socket的请求,那么这个派生的socket会被包装起来,放进我们上面那个队列中,这个过程是通过tclistpush完成的。其实这已经是一个完整的流程了,子线程的处理是同步的在创建线程的时候进行的。现在我们回头来说一下。当我们的队列有了数据,也就是有了具体的请求之后。我们的从线程们就可以读过来处理,当然,一个线程一次拿走一个进行处理。这个过程在代码中是怎么样的呢?我们知道从线程的入口是ttservdeqtasks。在这个函数中,也有一个大的循环,这个循环什么作用?当然就是不停地去队列尾上问,有没有任务。没有就再进行循环,有的话就调用tclistshift2函数将这个任务取出来。然后进行处理。

数据结构

大体流程就是上面这样的,重要的数据结构有:

  • TTREQ:其实就是代表每一个线程,多了一些附加数据。
  • TTSERV:我们这个网络服务器就是一个他的实例,包含了一些参数的设置,比如host,port之流。
  • TTSOCK:在具体的线程处理请求中,针对的是一个socket,这个socket就是这个类型。

    +++程序流程+++

    下面再说一下整个程序流程。
  1. 先从ttserver.c的main函数开始,接收命令行参数做好了配置就进入同一个文件中的proc函数。进行了一些初始化的工作。
  2. 然后进入ttutil.c文件的ttservstart开始真正的启动过程,在这个函数中创建socket,启动线程,epoll侦听等等,如上面说的。

参考内容引自:http://www.162cm.com/p/tokyotyrant.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值