源码分析

前一篇博文以get命令为例子把整个处理流程简单讲述了一遍,本篇博文将以set命令详细讲述memcached的处理流程。具体的命令为“set tt 3 0 10”,并假设当然memcached服务器没有名为tt的item。 读取命令: ? ? ? ??在前一篇博文的最后,conn的状态被设置为conn_new_cmd,回到了
dexcoder 1年前发布
? ? ? ??本文以get命令为例子,探讨memcached是如何处理命令的。本文只是探讨memcached处理命令的工作流程,具体的代码细节在不影响阅读的前提下能省略的就省略、能取默认值就取默认值、内存是足够的(不需要动态申请空间就够用了)。涉及到数组、缓存区的就假设已经分配好了。
dexcoder 1年前发布
需求: ? ? ? ? 考虑这样的一个情景:在一开始,由于业务原因向memcached存储大量长度为1KB的数据,也就是说memcached服务器进程里面有很多大小为1KB的item。现在由于业务调整需要存储大量10KB的数据,并且很少使用1KB的那些数据了。由于数据越来越多,内存开始吃紧。大小为10
dexcoder 1年前发布
过期失效处理: ? ? ? ??一个item在两种情况下会过期失效:1.item的exptime时间戳到了。2.用户使用flush_all命令将全部item变成过期失效的。读者可能会说touch命令也可以使得一个item过期失效,其实这也属于前面说的第一种情况。 超时失效: ? ? ? ??对于第一种过期失效,memc
dexcoder 1年前发布
锁级别: ? ? ? ? 从前面的《扩展哈希表》知道:哈希表进行扩展时,有一个专门的线程负责将item数据从旧哈希表迁移到新哈希表(由此,也称这个线程为迁移线程)。此外,还有一些worker线程会时不时访问item(包括插入、删除和获取)。这些线程的对item所做的操作基本上都是互斥的
dexcoder 1年前发布
LRU队列: ? ? ? ??之前的《slab内存分配》博文已经写到:一个slab class里面的所有slab分配器只分配相同大小的item,不同的slab class分配不同大小的item。item结构体里面有一个slabs_clsid成员,用来指明自己是属于哪个slab class的。这里把slabs_clsid值相同的item称为是同
dexcoder 1年前发布
哈希结构: ? ? ? ??main函数会调用assoc_init函数申请并初始化哈希表。为了减少哈希表发生冲突的可能性,memcached的哈希表是比较长的,并且哈希表的长度为2的幂。全局变量hashpower用来记录2的幂次。main函数调用assoc_init函数时使用全局变量settings.hashpower_init作为参
dexcoder 1年前发布
slab简介: ? ? ? ??memcached使用了一个叫slab的内存分配方法,有关slab的介绍可以参考链接1和链接2。可以简单地把它看作内存池。memcached内存池分配的内存块大小是固定的。虽然是固定大小,但memcached的能分配的内存大小(尺寸)也是有很多种规格的。一般来说,是满足需求的
dexcoder 1年前发布
半同步/半异步: ? ? ? ??memcached使用半同步/半异步网络模型处理客户端的连接和通信。 ? ? ? ? 半同步/半异步模型的基础设施:主线程创建多个子线程(这些子线程也称为worker线程),每一个线程都维持自己的事件循环,即每个线程都有自己的epoll,并且都会调用epoll_wait函数
dexcoder 1年前发布
本文开启本系列博文的代码分析。本系列博文研究是memcached版本是1.4.21。 本文将给出memcached启动时各个参数的详细解释以及一些关键配置的默认值。以便在分析memcached源码的时候好随时查看。当然也方便使用memcached时可以随时查看各个参数的含义。《如何阅读memcached源码
dexcoder 1年前发布
安装: ? ? ? ??安装memcached之前要先安装Libevent。现在假定Libevent安装在/usr/local/libevent目录了。 ? ? ? ??因为memcached安装后不像Libevent那样,有一堆头文件和库文件。安装后的memcached不是用来编程而直接用来运行的。所以不需要在/usr/local目录下专门为memcache
dexcoder 1年前发布
和之前的《Libevent工作流程探究》一样,这里也是用一个例子来探究bufferevent的工作流程。具体的例子可以参考《Libevent使用例子,从简单到复杂》,这里就不列出了。其实要做的例子也就是bufferevent_socket_new、bufferevent_setcb、bufferevent_enable这几个函数。 ? ? ? ?
dexcoder 1年前发布
锁操作: ? ? ? ??在 前一篇博文可以看到很多函数在操作前都需要对这个evbuffer进行加锁。同event_base不同,如果evbuffer支持锁的话,要显式地调用函数evbuffer_enable_locking。 //buffer.c文件 int//参数可以是一个锁变量也可以是NULL evbuffer_enable_locking(struct ev
dexcoder 1年前发布
对于非阻塞IO的网络库来说,buffer几乎是必须的。Libevent在1.0版本之前就提供了buffer功能。现在来看一下Libevent的buffer。 buffer相关结构体: ? ? ? ??Libevent为buffer定义了下面的结构体: //evbuffer-internal.h文件 struct evbuffer_chain; struct evbuffer { str
dexcoder 1年前发布
使用evconnlistener: ? ? ? ? 基于event和event_base已经可以写一个CS模型了。但是对于服务器端来说,仍然需要用户自行调用socket、bind、listen、accept等步骤。这个过程有点繁琐,为此在2.0.2-alpha版本的Libevent推出了一些对应的封装函数。 ? ? ? ??用户只需初始化struct
dexcoder 1年前发布
?Libevent定义了一系列的可移植的兼容类型和函数。这使得在各个系统上都有一致的效果,Libevent一般都会在兼容通用类型和函数的前面加上ev或evutil前缀。 ? ? ? ??在实现上,Libevent都是使用条件编译+宏定义的方式。使用这种方式,同一个宏名字,可以使得在不同的系统上, 编
dexcoder 1年前发布
? ? ? ??Libevent提供了一些与event相关的操作函数和操作。本文就重点讲一下这方面的源代码。 ? ? ? ? 在Libevent中,无论是event还是event_base,都是使用指针而不会使用变量。实际上,如果查看Libevent不同的版本,就可以发现event和event_base这两个结构体的成员是不同的。
dexcoder 1年前发布
? ? ? ??前面的博文已经说到,如果要对多个超时event同时进行监听,就要对这些超时event进行集中管理,能够方便地(时间复杂度小)获取、加入、删除一个event。 ? ? ? ??在之前的Libevent版本,Libevent使用小根堆管理这些超时event。小根堆的插入和删除时间复杂度都是O(logN)。
dexcoder 1年前发布
基本时间操作函数: ? ? ? ??Libevent采用的时间类型是struct? timeval,这个类型在很多平台都提供了。此外,Libevent还提供了一系列的时间操作函数。比如两个struct timeval相加、相减、比较大小。有些平台直接提供了一些时间操作函数,但有些则没有,那么Libevent就自己实现
dexcoder 1年前发布
如何成为超时event: ? ? ?? ? ? ? ???Libevent允许创建一个超时event,使用evtimer_new宏。 //event.h文件 #define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg)) ? ? ? ??从宏的实现来看,它一样是用到了一般的event_new,并且不使用任何的文件描
dexcoder 1年前发布