memcached简单分析

多线程的memcached很简单,一个监听主线程,N个工作线程(event worker),实际上每一个线程都是一个单独的libevent实例,都有自己的event_base。

 a.主线程负责监听、接收、CQ_ITEM的分发

 b.工作线程负责已注册连接的读写事件处理。

网上找了一个图如下,源地址不明:


1.子线程初始化:

bool MyService::thread_init(int thread_num,struct event_base *main_base)
{
	threads = (LIBEVENT_THREAD *)malloc(sizeof(LIBEVENT_THREAD) * thread_num);
	if(!threads)
	{
		return false;
	}
	memset(threads,0,sizeof(LIBEVENT_THREAD)*thread_num);

	dispatcher_thread.base = main_base;      //main thread event_base
	dispatcher_thread.thread_id = pthread_self();

	for(int i = 0; i < thread_num; i++)
	{
                int fds[2];
                if(pipe(fds))
                { 
        	   printf("pipe error"); 
		   exit(1); 
                }
                threads[i].notify_receive_fd = fds[0];
		threads[i].notify_send_fd = fds[1];
		setup_thread(&threads[i]);
	}

	for(int i = 0; i < thread_num; i++)
	{
                pthread_t th;
                int ret = pthread_create(&th,NULL,ThreadWorkers,&threads[i]);
                assert(ret == 0);
	}
	return true;
}
 a.创建pipe,用于主线程接收到新的连接后通知工作线程,注册pipe可读事件

 b.创建工作线程,启动工作线程event_base_dispatch(me->base);

注册pipe事件如下:

void MyService::setup_thread( LIBEVENT_THREAD *me )
{
	if(!me->base)
	{
		me->base = event_base_new();
	}

	//Listen for notifications from other threads 
        event_set(&me->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) 
        {
           printf("Can't monitor libevent notify pipe\n");
           exit(1);
        }
	me->new_conn_queue = new CConnQueueLock();  //工作线程连接队列
}

2.主线程分发新的连接:

void MyService::dispatch_conn_new( evutil_socket_t sfd )
{
	CQ_ITEM *item = free_item_list.cqi_new();
	if(item == NULL)
	{
		return;
	}

	int tid = (last_thread+1)%THREAD_NUM;
	LIBEVENT_THREAD *thread = threads + tid;
	last_thread = tid;
	item->sfd = sfd;
	
	thread->new_conn_queue->cq_push(item);

        char buf[1] = {'c'};
        if(write(thread->notify_send_fd,buf,1) != 1)
        {
	    printf("write pipe error");
 	}
}
 a.从free_item_list new一个CQ_ITEM,push到工作线程的连接队列中。

 b.通过向该线程管道中写入一个'c'字符通知工作线程有新的连接到达。

3.工作线程触发pipe可读事件,调用thread_libevent_process函数:

void MyService::thread_libevent_process(int fd,short which,void *arg)
{
    LIBEVENT_THREAD *me = (LIBEVENT_THREAD*)arg;
    CQ_ITEM *item = NULL;
    char buf[1];

    if (read(fd, buf, 1) != 1)
    { 
	printf("read from pipe error"); 
    }
      
    if(buf[0] == 'c')
       item = me->new_conn_queue->cq_pop();

    if (NULL != item) 
    {
     	bufferevent *bev =  bufferevent_socket_new(me->base,item->sfd,BEV_OPT_CLOSE_ON_FREE);    

	bufferevent_setcb(bev, socket_read_cb, NULL, socket_event_cb, NULL);    
	int ret = bufferevent_enable(bev, EV_READ | EV_PERSIST);   
	assert(ret != -1);
    }
}
 a.工作线程从连接队列pop出CQ_ITEM

 b.注册到自己的event_base上。

4.free_item_list创建CQ_ITEM

CQ_ITEM * CFreeListLock::cqi_new()
{
#define ITEMS_PER_ALLOC 64

	CQ_ITEM *item = NULL;
	if(cqi_freelist)
	{
		item = cqi_freelist;
		cqi_freelist = item->next;
	}

	if(NULL == item)
	{
		item = (CQ_ITEM *)malloc(sizeof(CQ_ITEM) * ITEMS_PER_ALLOC);
		if(item == NULL)
			return NULL;
		//组成单链表 cqi_freelist为header
		for(int i = 2; i < ITEMS_PER_ALLOC; i++)
		{
			item[i-1].next = &item[i];
		}

		_lock.Enter();
		item[ITEMS_PER_ALLOC-1].next = cqi_freelist;
		cqi_freelist = &item[1];
		_lock.Leave();
	}
	return item;
}
可以看出,CQ_ITEM被用完后,会一次分配 ITEMS_PER_ALLOC个,而不是每次都new。

memcached版本为1.4.24,以上代码只是摘取后修改简化的。



1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值