Memcached的服务设计与启动过程——C10K系列

标签: memcached 服务设计 c10k | 发表时间:2014-08-23 10:37 | 作者:lvdccyb
出处:http://www.iteye.com
C10k要解决的问题,是10K个连接。
LINUX下,使用EPOLL可实现异步非阻塞(注:阻塞的一定是同步的,阻塞是调用方自己阻塞自己(等待事件))
非阻塞:是指调用方不会阻塞自己,如被调用方有数据就返回,无数据就返回EAGAIN,调用方根据EAGAIN决定自己的策略。因此非阻塞,和异步没有任何关联。
异步:是相对于同步的。异步是指:调用的时机和返回的时机不是同一时刻。异步说的是一个处理流程,而并不一定是具体的某个函数。

举例如下:
你在电子商城买了一本书,你已经下单;但是,这时候商城并没有立即给你发单,而是有合适时候时,主动通知你,我已经发单了。
因此,下单,和发单不是同一时刻。
一般来说,异步需要通过回调函数来实现。即先需要注册一个异步处理流程,如必须先将你的手机号告诉给商城。
当然,也有异步服务。比如用网银买火车票。火车票网站转到网银,网银付账是一个同步的过程。但是火车票网站与网银的处理是异步的。火车票网站,不知道网银交易何时完成;网银交易完成后,再发个消息给火车票网站交易完成。

---------------------------------------------------------------------------------
Memcached,版本1.4.20:基于libevent的多线程实现
采用的是一个主线程(dispatcher_thread),多个工作线程worker(LIBEVENT_THREAD),
(1)主线程dispatcher_thread负责接收外部请求事件,然后派发给工作线程处理。
(2)主线程dispatcher_thread和工作线程的通过管道传递消息。(实际上,是工作线程添加了一个与主线程关联的管道的事件 (libevent 的event))

对于TCP连接来说,主线程(dispatcher_thread)是一个监听线程,即监听外部的服务请求。
主线程(dispatcher_thread)的定义:
typedef struct {
pthread_t thread_id;

/* unique ID of this thread */
struct event_base *base;
/* libevent handle this thread uses */
} LIBEVENT_DISPATCHER_THREAD;

工作线程Worker的定义:
typedef struct {
pthread_t thread_id;

/* unique ID of this thread */
struct event_base *base;
/* libevent handle this thread uses */
struct event notify_event;  /* listen event for notify pipe */
int notify_receive_fd;
/* receiving end of notify pipe */
int notify_send_fd;

/* sending end of notify pipe */
struct conn_queue *new_conn_queue; /* queue of new connections to handle */
} LIBEVENT_THREAD;

Libevent 的main函数比较长,但与网络请求相关的是serversocket的创建和thread_init函数。

第一步:多线程服务初始化thread_init()
服务的初始化是在thread_init()完成的,主要完成主线程(dispatcher_thread),多个工作线程worker(LIBEVENT_THREAD)事件注册,管道通知等:
(1)初始化主线程dispatcher_thread的event base,event;
(2)初始化管道,将主线程dispatcher_thread与工作线程worker,通过管道关联。
for (i = 0; i notify_event, me->notify_receive_fd,
EV_READ | EV_PERSIST, thread_libevent_process, me);
event_base_set(me->base, &me->notify_event);

if (event_add(&me->notify_event, 0) == -1) {
fprintf(stderr, "Can't monitor libevent notify pipe\n");
exit(1);
}
§ thread_libevent_process:这个函数,是接收到数据的具体处理过程,其参数是线程句柄
§ 初始化工作线程自己的请求队列。
LIBEVENT_THREAD中的struct conn_queue *new_conn_queue;这个是请求队列。
(4)启动工作线程
创建Worker线程(LIBEVENT_THREAD),其函数入口是:
static void *worker_libevent(void *arg)
里面是一个event_base_loop()的消息循环。
(5)到这里,工作线程已经完成初始化和启动(即工作线程已经可以工作了)。主线程只要等待工作线程启动完毕。

第二步,serversocket创建:和所有网络服务一样:create the listening socket, bind it, and init
server_sockets(settings.port, tcp_transport,
portnumber_file)

new_socket:
获取socket的设置:fcntl(sfd, F_GETFL, 0))
将其设置为非阻塞:fcntl(sfd, F_SETFL, flags | O_NONBLOCK) 

socket设置:根据配置文件
SO_REUSEADDR,//地址重用
SO_KEEPALIVE,//是否保持连接,这是TCP层的控制
SO_LINGER,//延时断开连接。ngingx默认也启用
TCP_NODELAY,//不启用Neagle算法(本科书中的滑动窗口拥塞控制协议),一般内网访问,常设置为true
bind:
listen:
listen_conn_add = conn_new(sfd, conn_listening,
EV_READ | EV_PERSIST, 1,
transport, main_base);//main_base要和创建的server socket关联
这里的
conn_new函数:
初始化conn(一个超级复杂的结构体)
设置事件与socket 的fd,与main_base关联,设置事件响应的具体处理函数,event_handler
添加事件
到这里,才把main_base(event_base* 类型)与监听事件关联完成。

第三步:
主消息循环;整个服务启动过程结束。

备注:主线程dispatcher_thread未必是程序启动的main thread,可以是一个独立的thread。


已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [memcached 服务设计 c10k] 推荐:

Memcached的服务设计与启动过程——C10K系列

- - 行业应用 - ITeye博客
C10k要解决的问题,是10K个连接. LINUX下,使用EPOLL可实现异步非阻塞(注:阻塞的一定是同步的,阻塞是调用方自己阻塞自己(等待事件)). 非阻塞:是指调用方不会阻塞自己,如被调用方有数据就返回,无数据就返回EAGAIN,调用方根据EAGAIN决定自己的策略. 因此非阻塞,和异步没有任何关联.

从 C10K 到 C500K

- Michael - DBA Notes
这个已经过时了,现在大家已经开始说 C500K. 国外的 Urban Airship 公司的工程师在其官方网志上发文章介绍他们在产品环境中做到 50 万并发客户端,Java + Pure NIO 的实现,最近又有文章介绍针对 Linux Kernel 调优的经验:Linux Kernel Tuning for C500k.

[转载]The C10K problem翻译

- jin - 新浪开发者博客
如今的web服务器需要同时处理一万个以上的客户端了,难道不是吗. 毕竟如今的网络是个big place了. 现在的计算机也很强大了,你只需要花大概$1200就可以买一个1000MHz的处理器,2G的内存, 1000Mbit/sec的网卡的机器. 让我们来看看–20000个客户,每个为50KHz,100Kbyes和 50Kbit/sec,那么没有什么比为这两万个客户端的每个每秒从硬盘读取4千字节然后发送到网络上 去更消耗资源的了.

memcached+magent实现memcached集群

- - 编程语言 - ITeye博客
首先说明下memcached存在如下问题.   本身没有内置分布式功能,无法实现使用多台Memcache服务器来存储不同的数据,最大程度的使用相同的资源;无法同步数据,容易造成单点故障. (memagent代理实现集群).       在 Memcached中可以保存的item数据量是没有限制的,只要内存足够.

MemCached详解

- - CSDN博客推荐文章
首先,我们来了解一下MemCached与MemCache之间的区别:. Memcache是一个自由和开放源代码、高性能、分配的内存对象缓存系统. 用于加速动态web应用程序,减轻数据库负载. 它可以应对任意多个连接,使用非阻塞的网络IO. 由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这 些HashTable.

Memcached调优

- - 四火的唠叨
文章系本人原创,转载请保持完整性并注明出自 《四火的唠叨》. 项目中有一个对实时响应性比较高的服务,引入了Memcached以减少延迟和减少数据库压力. 但是期间遇到了一些问题,这里记录一些调优细节. 最开始我使用的是 Memcached Java Client,但是最后放弃了,放弃原因包括:.

memcached协议

- - 开源软件 - ITeye博客
旧版: http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt. 新版: https://github.com/memcached/memcached/blob/master/doc/protocol.txt.

Java使用memcached

- - 互联网 - ITeye博客
首先到 http://danga.com/memcached下载memcached的windows版本和java客户端jar包,目前最新版本是memcached-1.2.1-win32.zip和java_memcached-release_1.6.zip,分别解压后即可. 然后是安装运行memcached服务器,我们将memcached-1.2.1-win32.zip解压后,进入其目录,然后运行如下命令:c:>;memcached.exe -d install
c:>memcached.exe -l 127.0.0.1 -m 32 -d start.

Spring+memcached整合

- - 行业应用 - ITeye博客
1)  下载memcached服务端memcached-1.2.6-win32-bin.zip,地址:http:. 2)  下载java版客户端 java_memcached-release_2.6.1.zip. 3)  解压缩memcached-1.2.6-win32-bin.zip到指定目录,例如:D:\memcached-1.2.6-win32 ,.

转 redis vs memcached

- - 数据库 - ITeye博客
传统MySQL+ Memcached架构遇到的问题.   实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:.   1.MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间.