Memcached源码剖析笔记
Memcache基础教程

Memcache基础教程Memcache是什么Memcache是的⼀个项⽬,最早是为 LiveJournal 服务的,⽬前全世界不少⼈使⽤这个缓存项⽬来构建⾃⼰⼤负载的⽹站,来分担数据库的压⼒。
它可以应对任意多个连接,使⽤⾮阻塞的⽹络IO。
由于它的⼯作机制是在内存中开辟⼀块空间,然后建⽴⼀个HashTable,Memcached⾃管理这些HashTable。
Memcache官⽅⽹站:/memcached,更多详细的信息可以来这⾥了解 :)为什么会有Memcache和memcached两种名称?其实Memcache是这个项⽬的名称,⽽memcached是它服务器端的主程序⽂件名,知道我的意思了把~~~~。
⼀个是项⽬名称,⼀个是主程序⽂件名,在⽹上看到了很多⼈不明⽩,于是混⽤了。
Memcache的安装分为两个过程:memcache服务器端的安装和memcached客户端的安装。
所谓服务器端的安装就是在服务器(⼀般都是linux系统)上安装Memcache实现数据的存储所谓客户端的安装就是指php(或者其他程序,Memcache还有其他不错的api接⼝提供)去使⽤服务器端的Memcache提供的函数,需要php添加扩展。
具体的配置⼤家可以参考::/257.html:/258.html:/259.html:/261.html:/306.html:/395.htmlPHP的Memcache1 < ?php2//连接3$mem = new Memcache;4$mem->connect("192.168.0.200", 12000);56//保存数据7$mem->set('key1', 'This is first value', 0, 60);8$val = $mem->get('key1');9echo "Get key1 value: " . $val ."<br />";1011//替换数据12$mem->replace('key1', 'This is replace value', 0, 60);13$val = $mem->get('key1');14echo "Get key1 value: " . $val . "<br />";1516//保存数组17$arr = array('aaa', 'bbb', 'ccc', 'ddd');18$mem->set('key2', $arr, 0, 60);19$val2 = $mem->get('key2');20echo "Get key2 value: ";21print_r($val2);22echo "<br />";2324//删除数据25$mem->delete('key1');26$val = $mem->get('key1');27echo "Get key1 value: " . $val . "<br />";2829//清除所有数据30$mem->flush();31$val2 = $mem->get('key2');32echo "Get key2 value: ";33print_r($val2);34echo "<br />";3536//关闭连接37$mem->close();38 ?>如果正常的话,浏览器将输出:Get key1 value: This is first valueGet key1 value: This is replace valueGet key2 value: Array ( [0] => aaa [1] => bbb [2] => ccc [3] => ddd )Get key1 value:Get key2 value:程序代码分析初始化⼀个Memcache的对象:$mem = new Memcache;连接到我们的Memcache服务器端,第⼀个参数是服务器的IP地址,也可以是主机名,第⼆个参数是Memcache的开放的端⼝:$mem->connect("192.168.0.200", 12000);保存⼀个数据到Memcache服务器上,第⼀个参数是数据的key,⽤来定位⼀个数据,第⼆个参数是需要保存的数据内容,这⾥是⼀个字符串,第三个参数是⼀个标记,⼀般设置为0或者MEMCACHE_COMPRESSED就⾏了,第四个参数是数据的有效期,就是说数据在这个时间内是有效的,如果过去这个时间,那么会被Memcache服务器端清除掉这个数据,单位是秒,如果设置为0,则是永远有效,我们这⾥设置了60,就是⼀分钟有效时间:$mem->set('key1', 'This is first value', 0, 60);从Memcache服务器端获取⼀条数据,它只有⼀个参数,就是需要获取数据的key,我们这⾥是上⼀步设置的key1,现在获取这个数据后输出输出:$val = $mem->get('key1');echo "Get key1 value: " . $val;现在是使⽤replace⽅法来替换掉上⾯key1的值,replace⽅法的参数跟set是⼀样的,不过第⼀个参数key1是必须是要替换数据内容的key,最后输出了:$mem->replace('key1', 'This is replace value', 0, 60);$val = $mem->get('key1');echo "Get key1 value: " . $val;同样的,Memcache也是可以保存数组的,下⾯是在Memcache上⾯保存了⼀个数组,然后获取回来并输出$arr = array('aaa','bbb','ccc', 'ddd');$mem->set('key2', $arr, 0, 60);$val2 = $mem->get('key2');print_r($val2);现在删除⼀个数据,使⽤delte接⼝,参数就是⼀个key,然后就能够把Memcache服务器这个key的数据删除,最后输出的时候没有结果$mem->delete('key1');$val = $mem->get('key1');echo "Get key1 value: " . $val . "<br>";最后我们把所有的保存在Memcache服务器上的数据都清除,会发现数据都没有了,最后输出key2的数据为空,最后关闭连接$mem->flush();$val2 = $mem->get('key2');echo "Get key2 value: ";print_r($val2);echo "<br>";Memcache的使⽤使⽤Memcache的⽹站⼀般流量都是⽐较⼤的,为了缓解数据库的压⼒,让Memcache作为⼀个缓存区域,把部分信息保存在内存中,在前端能够迅速的进⾏存取。
memcached协议解析

memcached协议解析协议memcached 的客户端使⽤TCP链接与服务器通讯。
(UDP接⼝也同样有效,参考后⽂的 “UDP协议” )⼀个运⾏中的memcached服务器监视⼀些(可设置)端⼝。
客户端连接这些端⼝,发送命令到服务器,读取回应,最后关闭连接。
结束会话不需要发送任何命令。
当不再需memcached服务时,要客户端可以在任何时候关闭连接。
需要注意的是,⿎励客户端缓存这些连接,⽽不是每次需要存取数据时都重新打开连接。
这是因为memcached 被特意设计成及时开启很多连接也能够⾼效的⼯作(数百个,上千个如果需要的话)。
缓存这些连接,可以消除建⽴连接所带来的开销(/*/相对⽽⾔,在服务器端建⽴⼀个新连接的准备⼯作所带来的开销,可以忽略不计。
)。
在memcache协议中发送的数据分两种:⽂本⾏和⾃由数据。
⽂本⾏被⽤于来⾃客户端的命令和服务器的回应。
⾃由数据⽤于客户端从服务器端存取数据时。
同样服务器会以字节流的⽅式传回⾃由数据。
/*/服务器不⽤关⼼⾃由数据的字节顺序。
⾃由数据的特征没有任何限制;但是通过前⽂提到的⽂本⾏,这项数据的接受者(服务器或客户端),便能够精确地获知所发送的数据库的长度。
⽂本⾏固定以“\r\n”(回车符紧跟⼀个换⾏符)结束。
⾃由数据也是同样会以“\r\n”结束,但是 \r(回车符)、\n(换⾏符),以及任何其他8位字符,均可出现在数据中。
因此,当客户端从服务器取回数据时,必须使⽤数据区块的长度来确定数据区块的结束位置,⽽不要依据数据区块末尾的“\r\n”,即使它们固定存在于此。
键值存储在memcached中的数据通过键值来标识。
键值是⼀个⽂本字符串,对于需要存取这项数据的客户端⽽⾔,它必须是唯⼀的。
键值当前的长度限制设定为250字符(当然,客户端通常不会⽤到这么长的键);键值中不能使⽤制表符和其他空⽩字符(例如空格,换⾏等)。
命令所有命令分为3种类型:存储命令(有3项:’set’、’add’、’repalce’)指⽰服务器储存⼀些由键值标识的数据。
memcached源码分析一-slab

memcached源码分析⼀-slabSlab作为⼀种内存管理⽅案,其作⽤主要有以下2点:a) 避免频繁的内存分配释放造成的内存碎⽚b) 减少内存分配操作产⽣的性能开销Linux内核数据结构中也有slab的设计,Linux提供了⼀套接⼝,使⽤这套接⼝可以动态创建与释放⼀个slab结构,该slab的chunk⼤⼩通过接⼝指定,创建成功后就可以从该slab中动态申请与释放chunk⼤⼩的内存⽤于存储⽬标数据,例如内核中⽤于表⽰进程的结构体task_struc 就是使⽤的slab⽅式进⾏管理。
memcached与linux内核不同,memcached中在程序启动时即初始化⼀个slabclass_t的全局数组,每⼀个slabclass_t结构的chunk⼤⼩不同,构成⼀个全局slab池。
memcached中的slab相关操作源码主要集中在源⽂件slabs.c中,下⾯对它进⾏分析。
1. 结构体slabclass_t以下是memcached中对slabclass_t的定义,typedef struct {unsigned int size; /* sizes of items */unsigned int perslab; /* how many items per slab */void *slots; /* list of item ptrs */unsigned int sl_curr; /* total free items in list */unsigned int slabs; /* how many slabs were allocated for this class */void **slab_list; /* array of slab pointers */unsigned int list_size; /* size of prev array */size_t requested; /* The number of requested bytes */} slabclass_t;slabclass_t对内存的组织可以粗略的⽤图1-1表⽰,图1-1 slabclass_t内存组织⽅式slab_list是⼀个可以动态分配的数组,数组⼤⼩以list_size表⽰,数组中已存储元素数⽬以slabs表⽰,数组中每⼀个元素都表⽰⼀个page ⼤⼩的可⽤内存(page也称为slab)。
MemCache详细解读

MemCache详细解读MemCache是什么MemCache是⼀个⾃由、源码开放、⾼性能、分布式的分布式内存对象缓存系统,⽤于动态Web应⽤以减轻数据库的负载。
它通过在内存中缓存数据和对象来减少读取数据库的次数,从⽽提⾼了⽹站访问的速度。
MemCaChe是⼀个存储键值对的HashMap,在内存中对任意的数据(⽐如字符串、对象等)所使⽤的key-value存储,数据可以来⾃数据库调⽤、API调⽤,或者页⾯渲染的结果。
MemCache设计理念就是⼩⽽强⼤,它简单的设计促进了快速部署、易于开发并解决⾯对⼤规模的数据缓存的许多难题,⽽所开放的API使得MemCache能⽤于Java、C/C++/C#、Perl、Python、PHP、Ruby等⼤部分流⾏的程序语⾔。
另外,说⼀下MemCache和MemCached的区别:1、MemCache是项⽬的名称2、MemCached是MemCache服务器端可以执⾏⽂件的名称MemCache访问模型为了加深理解,我模仿着原阿⾥技术专家李智慧⽼师《⼤型⽹站技术架构核⼼原理与案例分析》⼀书MemCache部分,⾃⼰画了⼀张图:特别澄清⼀个问题,MemCache虽然被称为"分布式缓存",但是MemCache本⾝完全不具备分布式的功能,MemCache集群之间不会相互通信(与之形成对⽐的,⽐如JBoss Cache,某台服务器有缓存数据更新时,会通知集群中其他机器更新缓存或清除缓存数据),所谓的"分布式",完全依赖于客户端程序的实现,就像上⾯这张图的流程⼀样。
同时基于这张图,理⼀下MemCache⼀次写缓存的流程:1、应⽤程序输⼊需要写缓存的数据2、API将Key输⼊路由算法模块,路由算法根据Key和MemCache集群服务器列表得到⼀台服务器编号3、由服务器编号得到MemCache及其的ip地址和端⼝号4、API调⽤通信模块和指定编号的服务器通信,将数据写⼊该服务器,完成⼀次分布式缓存的写操作读缓存和写缓存⼀样,只要使⽤相同的路由算法和服务器列表,只要应⽤程序查询的是相同的Key,MemCache客户端总是访问相同的客户端去读取数据,只要服务器中还缓存着该数据,就能保证缓存命中。
Python中的Memcached缓存

Python中的Memcached缓存Memcached是一款高性能的分布式内存对象缓存系统。
它的主要功能是将数据存储在内存中,从而提高数据访问速度。
作为一款大型网站所必不可少的缓存工具,Memcached在Python 中的应用极度广泛。
在这篇论文中,我们将深入探讨Memcached在Python中的应用,分析其优点和缺点,并提出一些最佳实践,以帮助开发人员更好地利用Memcached提升应用的性能和用户体验。
一、Memcached的优点1.高速缓存Memcached是一款基于内存的缓存系统,它可以实现非常快速的缓存访问速度。
由于数据存储在内存中,所以它的响应速度相当快,甚至可以达到微秒级别。
在大型网站前端中,常使用Memcached来缓存一些静态或不怎么变化的数据,如网站配置信息、静态页面等。
通过缓存这些数据,可以减少对数据库等后端系统的请求,从而提高网站的性能。
2.可扩展性Memcached是一款分布式缓存系统,它可以将缓存数据分散存储在多台机器的内存中,从而实现更大的存储容量和更高的并发处理能力。
在高并发的情况下,系统可以简单地通过增加或减少服务器数量来扩展缓存能力。
此外,Memcached还具有自动数据平衡和故障转移等功能,可以实现高可用性和灵活性。
3.支持多种语言Memcached支持多种语言,包括Python、Java、PHP等,可以方便地嵌入到各种应用程序中,快速提高应用程序的性能。
在Python中,Memcached是一种常见的缓存解决方案,可以通过安装对应的Python模块,轻松地集成到应用程序中。
二、Memcached的缺点1.容量限制由于Memcached是一款基于内存的缓存系统,所以它的缓存容量是有限的。
在实际应用中,需要根据业务需求和服务器硬件条件等因素综合考虑,设置合适的缓存容量,避免因容量不足而导致缓存失效。
2.数据不持久化Memcached只是一款内存缓存系统,它并不支持数据持久化。
memcached源代码分析

Part2
Part2
Memcached的线程关系
typedef struct { pthread_t thread_id; struct event_base *base; struct event notify_event; int notify_receive_fd; int notify_send_fd; CQ new_conn_queue; } LIBEVENT_THREAD; void thread_init(int nthreads, struct event_base *main_base) { threads[i].notify_receive_fd = fds[0]; threads[i].notify_send_fd = fds[1]; setup_thread(&threads[i]); for (i = 1; i < nthreads; i++) { create_worker(worker_libevent, &threads[i]); } } static void setup_thread(LIBEVENT_THREAD *me) { if (! me->base) me->base = event_init(); 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) { fprintf(stderr, "Can't monitor libevent notify pipe\n"); exit(1); } cq_init(&me->new_conn_queue); }
Memcached 源码分析--命令流程分析

Memcached 源码分析--命令流程分析一、执行命令首先是启动memcached 自带参数如下:[plain] view plain copy print?在CODE上查看代码片派生到我的代码片<span style="font-size:18px;">-p <num> 设置TCP端口号(默认设置为: 11211)-U <num> UDP监听端口(默认: 11211, 0 时关闭)-l <ip_addr> 绑定地址(默认:所有都允许,无论内外网或者本机更换IP,有安全隐患,若设置为127.0.0.1就只能本机访问)-c <num> max simultaneous connections (default: 1024)-d 以daemon方式运行-u <username> 绑定使用指定用于运行进程<username>-m <num> 允许最大内存用量,单位M (默认: 64 MB)-P <file> 将PID写入文件<file>,这样可以使得后边进行快速进程终止, 需要与-d 一起使用</span>#$: ./usr/local/bin/memcached -d -u root -l 192.168.10.156 -m 2048 -p 12121客户端通过网络方式连接:telnet 192.168.10.156 12121然后就可以操作命令、常见命令如下:[plain] view plain copy print?在CODE上查看代码片派生到我的代码片<span style="font-size:18px;">setaddreplacegetdelete</span>格式如下:[plain] view plain copy print?在CODE上查看代码片派生到我的代码片<span style="font-size:18px;">command <key> <flags> <expiration time> <bytes><value>参数说明如下:command set/add/replacekey key 用于查找缓存值flags 可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息expiration time 在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)bytes 在缓存中存储的字节点value 存储的值(始终位于第二行)</span>二、命令执行流程代码分析首先看一下工作线程中的命令数据结构:/*** The structure representing a connection into memcached.*/typedef struct conn conn;非常重要的几个参数:char * rbuf:用于存储客户端数据报文中的命令。
Memcached内存管理源码阅读

Memcached内存管理源码阅读meache能举行迅速地查找和良好的内存管理,得益于良好的hash查找和内存管理技巧.这两项功能主要由assoc.c和slab.c这两个文件来实现. 下面具体地分析一下每行代码实现slab.cdefine POWER_SMALLEST1 //slabclass数组的最小下标(slabclass 主要是来保存分配好的内存)define POWER_LARGEST 200 //slabclass数组的最大下标define POWER_BLOCK 1048576 //每一个chunk的最大值defineCHUNK_ALIGN_BYTES 8 //内存对其define DONT_PREALLOC_SLABS //不采纳事前分配内存/* powers-of-N alloion suctures *//*管理内存的主要数据结构, 搞清晰这个数据结构对囫囵内存的用法,分配,释放都很重要*/typef struct { unsigned int size; /* sizes of items */ //该结构保存的item的size大小,即最多能保存多大的数据 unsigned int perslab; /* how many items per slab */ //分配好一个slab 后,该slab可以存储多少个大小size的 vo **slots; /* list of item ptrs */ //回收回归后,内存的数组 unsigned int sl_total; /* size of previous array */ //目前总共有多少个空余的内存块 unsigned int sl_curr; /* first slot */ //目前已经用法到了多少个内存块void *end_page_ptr; /* pointer to nt free item at end of page, or 0 */ //每个slab中,可用法的地址 unsigned int end_page_free; /* number of items remaining at end of last alloced page */ //该slab中,可用法的内存块大小 unsigned int slabs; /* how many slabs were ald for this class */ //已经用法slab void **slab_list; /* array of slab pointers */ //保存每个slab的起始地址unsigned int list_size; /* size of prev array */ //总共有多少个slab unsigned int ing; /* index+1 of dying slab, or zero if none */} slabclass_t;ic slabclass_t slabclass[POWER_LARGEST + 1]; //核心的slabclass变量, 保存全部的内存static size_tmem_limit = 0; //限制memcache内存的用法的大小static size_t第1页共2页。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Memcached源码剖析笔记XguruMemcached是一个自由、源码开放、高性能、分布式内存对象缓存系统,目的在于通过减轻数据库负载来使动态Web应用程序提速。
目录1.背景 (3)2.memcached的安装 (4)3.memcached的配置 (5)4.memcached的使用 (6)4.1.存储命令 (7)4.2.读取命令 (8)4.3.删除命令 (8)4.4.高级命令 (9)4.5.其他命令 (10)5.Memcached内部工作机制 (11)5.1.Memcached基本的数据结构 (11)5.2.基本设计概念和处理流程 (12)5.3.内部Hash机制 (15)5.3.1.Hash函数及冲突解决 (15)5.3.2.HashTable主要函数 (15)5.4.slab内存处理机制 (17)5.4.1.slab主要函数 (17)5.4.2.slab机制中所采用的LRU算法 (19)5.5.控制item各种函数 (20)5.6.守护进程机制 (22)5.7.Socket处理机制 (23)15.7.1.Unix域协议 (23)5.7.2.TCP/UDP协议 (24)5.8.多线程处理机制 (25)5.9.事件处理机制 (25)6.未完善之处 (27)7.参考文献 (28)21.背景Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。
它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。
Memcached基于一个存储键/值对的hashmap。
Memcached是一个自由、源码开放、高性能、分布式内存对象缓存系统,目的在于通过减轻数据库负载来使动态Web应用程序提速。
Memcached是一个在内存中对任意的数据(比如字符串,对象等)所使用的key-value 存储。
数据可以来自数据库调用,API调用,或者页面渲染的结果。
Memcached设计理念就是小而强大,它简单的设计促进了快速部署、易于开发,并解决面对大规模的数据缓存的许多难题。
所开放的API能用于大部分流行的程序语言32.memcached的安装由于memcached采用libevent的事件处理机制,因此安装memcached之前需要先安装libevent。
Memcached: /Libevent : /~provos/libevent/在Ubuntu下可以使用sudo apt-get install libevent和sudo apt-get install memcached来安装或者使用传统wget的方式~$ wget /files/memcached-1.2.8.tar.gz.tar.gz~$ tar zxf memcached1.2.8.tar.gz~$ cd memcached1.2.8~$ ./configure~$ make目前最新的版本为1.4.4453. memcached 的配置主要使用的命令-d 以守护程序(daemon )方式运行 memcached ; -m 设置 memcached 可以使用的内存大小,单位为 M ;-l 设置监听的 IP 地址,如果是本机的话,通常可以不设置此参数; -p 设置监听的端口,默认为 11211,所以也可以不设置此参数; -u 指定用户,如果当前为 root 的话,需要使用此参数指定用户。
-f 设置增长因子(调优时使用) -v/-vv 详细显示工作时各种参数Memcached采用典型的getopt()函数获取各种配置 比如6./memcached -m 512 -p 11211 -vv该例分配给memcached 的可用内存512M ,监听11211端口,显示详细的运行信息。
4. memcached 的使用memcached 提供的API 可以在大多数的编程语言使用,在这里测试使用的是PuTTy 的telnet 方式,使用telnet 连接其11211端口。
Memcached 有4种类型的命令:● 存储命令(set/add /replace/append/prepend )指示服务器储存一些由键值标识的数据。
客户端发送一行命令,后面跟着数据区块;然后,客户端等待接收服务器回传的命令行,指示成功与否。
●读取命令(get/bget/gets )指示服务器返回与所给键值相符合的数据(一个请求中右一个或多个键值)。
客户端发送一行命令,包括所有请求的键值;服务器每找到一项内容,都会发送回客户端一行关于这项内容的信息,紧跟着是对应的数据区块;直到服务器以一行“END”回应命令结束。
●状态命令(stat)被用于查询服务器的运行状态和其他内部数据。
●其他命令,如flush_all,version,quit等。
4.1.存储命令命令格式:<command name> <key> <flags> <exptime> <bytes><data block>命令解释:存储命令区别74.2.读取命令get <key><key>可以表示一个或多个键值,由空格隔开的字串4.3.删除命令delete <key>删除键值为key的数据。
894.4. 高级命令值得一提的是,新版本的memcached 加入了gets 和cas 命令可以看到此处gets 比普通的get 多返回一个数字,这个数字可以用作检查数据是否发生改变。
当key 对应的数据改变的时候,该数会发生改变,如图中红圈所示。
cas 就是check and set 之意,只有当最后一个参数与gets所获取的参数匹配时才能存储,否则返回“EXISTS ”。
这种设计的意图是防止使用经过改变了的value/key 对。
4.5.其他命令查看状态其他更多的命令可以参看memcached的协议:/svn/memcached/trunk/server/doc/protocol.txt。
了解了其基本工作方式以后再来看源代码发现清晰很多。
10115. Memcached 内部工作机制5.1. Memcached 基本的数据结构item 为memcached 中的存储数据最小单位,其中还记录有数据和最近访问时间数据大小,桶的下一项等数据,每个不同slab 的元素内含有具有统一分配的尺寸的各个item 。
可以这样理解,每个item 是存储在其对应大小的slabclass_t 里的,同时又在hash 表中有记录。
既可以使用自己的内存分配机制来减少操作系统在处理内存碎片,添加释放等多余的操作,又可以使用hash 表的性质对其进行快速的定位。
slabclass 是由(POWER_LARGEST + 1 )个slabclass_t 结构体构成的数组,每个slabclass_t 结构体的大小是根据增长因子递增的,增长因子可以由客户端来设定,1.28版本的默认值为2,合理的调优增长因子可以避免空间的浪费。
5.2.基本设计概念和处理流程1213在这里值得注意的是,add/set/replace/cas这类存储命令在conn_read里的操作只是分配了item的空间,并没有对其进行存储工作,当conn_read结束后设置状态为conn_nread再做进一步的处理。
14155.3. 内部Hash机制5.3.1. Hash 函数及冲突解决memcached 采用的hash 函数是Bob Jenkins 先生在1996创立的一个算法,复杂度为O (6n+35),而且冲突率极低,该算法具体过程可以参阅这里。
冲突处理的方法为开链法。
memcached 中实际有两个hash 表,一个是“主hash 表”(primary_hashtable ),另外一个是“原有hash 表”(old_hashtable )。
每次操作的时候,先会检测表是否正处于扩展(expanding)状态,如果扩展还没完成时,先在原有hash 表中操作数据。
5.3.2. HashTable 主要函数 assoc_init()初始化hash 表,为主hash 表分配空间。
assoc_find()根据key 值来查找item ,如果有冲突存在,则不停往桶的下一个元素(h_next )里查找,直至找到为止,并返回其指针。
assoc_insert()在hash 表中插入item ,如果装载因子大于1.5,则扩展哈希表assoc_delete()用_hashitem_befor()找键值为key的item之前的指针,改变其指向,数据实际上是没有被释放的,在这里只是从hash表中移除。
assoc_expend()扩展hash表到2的下一次方,比如现在是hash表的大小2^16,扩展后大小则为2^17。
再进行数据迁移,扩展时候不能再分配内存时,就保持原有的表不变。
do_assoc_move_next_bucket()将下一个桶迁移到先前的我们扩充的哈希表中_hashitem_before ()(内部使用)返回该键值所对应的item的之前的指针。
165.4.slab内存处理机制slab源于Jeff Bonwick 为SunOS 操作系统首次引入的一种内存处理机制,SLAB 的设计理念是基于对象缓冲的,基本想法是避免重复大量的初始化和清理操作。
SLAB 主要可以用于频繁分配释放的内存对象。
如果是采用系统自带的malloc/free话,反复地操作会造成大量内存碎片,操作系统将会花费大量的时间去查找连续的内存块来满足malloc的请求。
memcached中内存分配机制主要理念1.先为分配相应的大块内存,再在上面进行无缝小对象填充2.懒惰检测机制,Memcached不花过多的时间在检测各个item对象是否超时,当get获取数据时,才检查item对象是否应该删除,你不访问,我就不处理。
3.懒惰删除机制,在memecached中删除一个item对象的时候,并不是从内存中释放,而是单单的进行标记处理,再将其指针放入slot回收插糟,下次分配的时候直接使用。
5.4.1.slab主要函数slabs_init()slab初始化,如果配置时采用预分配机制(prealloc)则在先在这使用malloc分配所有内存。
再根据增长因子factor给每个slabclass分配容量。
slabs_clsid()计算出哪个slabclass适合用来储存大小给定为size的item,如果返回值为0则存储的物件过大,无法进行存储。
do_slabs_alloc()在这个函数里面,由宏定义来决定采用系统自带的malloc机制还是memcached的slab机制对内存进行分配,理所当然,在大多数情况下,系统的malloc会比slab慢上一个数量级。