Memcached 缓存系统的基础知识

时间:2022-12-26 00:16:10

摘了三篇:

一。

memcached 是什么?

memcached is a high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.
memcached是一个高性能的、分布式内存对象缓存系统,应用广泛。 通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、 提高可扩展性。
它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。还使用内置的内存块分配和哈希表算法,确保虚拟内存不会过来捣乱。

Memcached 官方网站:http://www.danga.com/memcached 

二。

1. 基本信息 

memcached是一个高性能的内存缓存对象系统,其实质为一个键值对的hashmap.其事件处理和网络通信均是基于libevent.

基本特征:

协议简单:使用基于文本行的协议

基于内存存储:数据存储在内存中

事件处理:基于libevent开发

不互相通信的分布式:多台memcached服务器之间不互相通信,由客户端实现分布式算法

Memcached 缓存系统的基础知识


                                               图1 memcached的分布式(转来的图)


1.1 内存管理机制

memcached采用名为slab allocator的内存管理机制,其基本原理是将预先规定的大小,将内存划分为特定长度的块。目的是要解决简单的malloc/free方式所造成的内存碎片。

Slab是memcached分配的基本单位,每个Slab对应多张Page(默认大小是1M),每张Page会被划分为多个chunk(每个chunk中都保存了一个item结构体、一对key和value)。

早期的版本中,每个Page一旦被分配给一个Slab,其后变一直如遇该Slab,但在较新的版本中,一个Page已经可以被重新分配给不同的Slab。

当客户端发来一条数据时,memcached根据数据的大小选择最为合适的Slab,将其存储在对应的Slab中。但是这也会带来新的问题,即内存的利用率会下降,例如,当一个100byte的数据到来,我们不得不为其分配一个128bytes的chunk,其多余的28字节就被浪费掉了。

为了尽量低的减少内存的浪费,memcached预先设定了40类Slab,通过在启动时加入-vv命令可以查看(两个v)

usr/local/memcached/bin/memcached -d -m 256 -l 127.0.0.1 -p 11212 -c 1024 -u root -vv

Memcached 缓存系统的基础知识

memcached默认的使用1.25作为增长因子,在使用memcached的过程中我们通过调整-f (成长因子、 -n(default size)等参数优化内存使用,计算公式如下(抄来的):

chunk size(class i) :  (default_size+item_size)*f^(i-1)+ CHUNK_ALIGN_BYTES

当没有可用Page时,memcached开始对Slab执行LRU算法删除冷数据,这里必须明确一点即LRU执行的对象是 Slab不是全局。


2. 安装、配置及启动

首先,安装libevent:

[html] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. wget http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz  
  2.   
  3. tar xzvf  libevent-1.4.13-stable.tar.gz  
  4.   
  5. cd libevent-1.4.13-stable  
  6.   
  7. ./configure && make && make install  

然后,安装memcached

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. wget http://memcached.org/latest  
  2. tar zxvf memcached-1.4.21.tar.gz && cd memcached-1.4.21  
  3. ./configure && make && make install  

 默认情况下程序会安装到 /usr/local/bin/memcached,接下来我们就可以启动memcached了,首先让我们来看一下启动参数,这里我们仅介绍一下常用的参数,更详细的参数列表可以通过man memcached查看:

-l              设置监听的ip地址,默认为 INADDR_ANY

-d             以守护进程模式运行memcached

-u             指定用户

-m            设置memcached可以使用的内存大小,单位为 M

-c              设置最大链接数,默认为1024

-R             设置一个客户端的最大连续请求数,默认为20

-p              设置TCP监听端口

-U              设置UDP监听端口

-P              设置memcached的Pid文件

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. /usr/local/bin/memcached -d -m 256 -l 127.0.0.1 -p 11211 -c 1024 -u root  

3. telnet方式

连接memcached:

Memcached 缓存系统的基础知识

3.1 存储命令

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. <command name> <key> <flags> <expire> <bytes>  
  2.   
  3. <value>  
<command name> set/add/replace
<key> 索引值 
<flags> 标志信息
<expire> 过期时间,0表示永不过期
<bytes> value的字节数
<value> 存储的数据块

set 命令:即可以添加新数据还可以更新已存在数据

Memcached 缓存系统的基础知识

add命令:仅在数据不存在时添加数据 

Memcached 缓存系统的基础知识   

replace命令:仅在数据存在时更新数据

Memcached 缓存系统的基础知识


3.2 清除命令

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. <command name> <key>  

delete命令: 删除已存在的数据

Memcached 缓存系统的基础知识


flush_all命令:清空数据。实际上它是时此命令之前插入的数据,在读取时无效化,同时在新数据到来后清除老数据

Memcached 缓存系统的基础知识

3.3 读取命令

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. <command name> <key>  
get命令:读取指定key的值

Memcached 缓存系统的基础知识


gets命令:读取指定key的值,末尾比get命令多一个值,限制value否改变,该值变化说明value发生了变化.

Memcached 缓存系统的基础知识


cas命令:仅当最后一个参数与gets取得结果的最后一个参数匹配时才更新(应该算是添加数据命令,但放在这里比较好解释)

Memcached 缓存系统的基础知识


3.4 更新数据命令

append命令:在现有数据之后添加字符

Memcached 缓存系统的基础知识


prepend命令:在现有数据之前添加字符

Memcached 缓存系统的基础知识


incr/decr命令:对数值型value进行增减,支持64位无符号数,最后那个参数表示变更的范围

Memcached 缓存系统的基础知识


3.5 查询状态命令

stats命令:

Memcached 缓存系统的基础知识

stats item命令:查看条目状态

Memcached 缓存系统的基础知识

stats slabs命令:查看内存情况

Memcached 缓存系统的基础知识

还有stats sizes,stats reset等等使用也比较常见.


4. libmemcached 

4.1 基本数据结构

memcached_st 结构:用于保存memcached连接对象

        memcached_return_t结构: 用于保存memcached命令执行状态

        memcached_server_st 结构:用于存储memcached服务器列表


4.2 创建和销毁一个memcached连接对象

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. memcached_st* memcached_create(memcached_st* ptr)      创建一个memcached_st对象,参数一般为NULL;  
  2.        memcached_st* memcached_clone(memcached_st* dest,memcached_st* src)    克隆一个memcached对象;  
  3.        void memcached_free(memcached_st* ptr)   释放memcached对象,断开连接时使用;  


4.3  操作memcached_st中存储的server信息

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. memcached_return_t memcached_server_add(memcached_st *mem,const char *hostname, int port); //在服务器列表尾部添加一台server  
  2. memcached_server_st* memcached_server_list_append(memcached_server_st* ptr,const char* hostname,int port,memcached_return_t * return) ; // 在memcached_server_st中添加一台server  
  3. memcached_return_t memcached_server_push(memcached_st *mem,memcached_server_st* ptr); //在服务器列表尾部添加一个server数组,与memcached_server_list_append结合使用  
  4. uint32_t memcached_server_count(memcached_st* mem); //计算当前server的个数  
  5. void memcached_servers_reset(memcached_st* mem); //清空server列表  
  6. void memcached_server_list_free(memcached_server_st* ptr); //释放memcached_server_st结构  

4.4 操作memcached数据

增减数据值:

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. memcached_return_t memcached_increment(memcached_st *ptr, const char *key, size_t key_length, uint32_t offset, uint64_t *value)//将指定key的value值加1  
  2. memcached_return_t memcached_decrement(memcached_st *ptr, const char *key, size_t key_length, uint32_t offset, uint64_t *value)//将指定key的value值减1  

删除数据

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length, time_t expiration)  

检查key值是否存在

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. memcached_return_t memcached_exist(memcached_st *ptr, char *key, size_t *key_length)  


清空数据

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration)  

获取数据

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. char * memcached_get(memcached_st *ptr, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error)//获取单个数据  
  2. memcached_return_t memcached_mget(memcached_st *ptr, const char * const *keys, const size_t *key_length, size_t number_of_keys)//获取多个数据,需要注意的是,当使用多个server时mget无法通过一次条用返回不同存储在不同server上的数据  
  3. char* memcached_fetch(memcached_st *ptr,char* keys, size_t *key_length,size_t* value_length,uint32_t* flags,memcached_return_t *error)//从上面函数的结果中提取数据  

写入数据

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//向memcached写入一条数据,存在即覆盖  
  2. memcached_return_t memcached_add(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//不存在即插入,存在返回错误  
  3. memcached_return_t memcached_replace(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//存在即覆盖,不存在返回错误  
memcached_set在非阻塞模式下只有当网络错误发生时才会返回错误


扩展字符串

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. memcached_return_t memcached_prepend(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//在原来的字符串之前添加内容  
  2. memcached_return_t memcached_append(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//在原来的字符串末尾添加内容  

上面这些接口仅用于TCP调用,libmemcached中对UDP和UNIX SOCKET也有相应的支持。

基本上,libmemcached提供了所有与命令行对应的功能接口,可以查询http://docs.libmemcached.org/

这里我们通过实例代码简要的说明一下存储和获取数据的接口

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. #include <libmemcached/memcached.h>  
  2.   
  3. int main(int argc, char* argv[]){  
  4.     memcached_st *mem;  
  5.     memcached_return_t re;  
  6.     memcached_server_st *svr;  
  7.       
  8.     //连接memcached   
  9.     mem = memcached_create(NULL);  
  10.     svr = memcached_server_list_append(NULL,"127.0.0.1",11211,&rc);  
  11.     rc = memcached_server_push(mem,srv);  
  12.     memcached_server_list_free(srv);  
  13.     //存储数据  
  14.     char* value = "zhoushuaiyin";  
  15.     rc = memcached_set(mem,"zhou",4,value,strlen(value),0,0);  
  16.     if(MEMCACHED_SUCCESS == rc){  
  17.          //anything  
  18.     }  
  19.   
  20.     //分别使用mgets+fetch和mget方式获取数据  
  21.     char *return_value = NULL;  
  22.     size_t return_value_length;  
  23.     char* keys[]={"zhou"};  
  24.     size_t keys_length[]={4};  
  25.     uint32 flags;  
  26.     rc = memcached_mget(mem,keys,keys_length,1);  
  27.     return_value = memcached_fetch(mem,return_key,&return_key_length,&return_value_length,&flags,&rc);  
  28.      if(MEMCACHED_SUCCESS == rc){  
  29.            printf("key:%s, value:%s",return_key,return_value);  
  30.      }  
  31.   
  32.       char* val = memcached_get(mem,"zhou",4, &return_value_length,&flags,&rc);if(MEMCACHED_SUCCESS == rc){  
  33.            printf("key:%s, value:%s",return_key,return_value);  
  34.      }  
  35.   
  36.      //删除数据  
  37.      rc = memcached_delete(mem,"zhou", 4 , (time_t)0);  
  38.   
  39.      memcached_free(mem);  
  40.      retrun 0;  
  41.   
  42.   
  43. }  

再给出一段memcached一致性hash的代码,包括使用memcached_get_by_key函数(by_key结尾的函数都具有相同的意义),不是很规范,但应该可以说明问题:

[cpp] view plaincopyMemcached 缓存系统的基础知识Memcached 缓存系统的基础知识
  1. #include<libmemcached/memcached.h>  
  2.   
  3. int main(int argc, char* argv[]){  
  4.     memcached_st *mem;  
  5.     memcached_return_t rc;  
  6.     memcached_server_st* servers;  
  7.   
  8.     mem = memcached_create(NULL);  
  9.     memcached_behavior_set(mem,MEMCACHED_BEHAVIOR_DISTRIBUTION,MEMCACHED_DISTRIBUTION_CONSISTENT);  
  10.     servers = memcached_server_list_append(NULL,"localhost",11211,&rc);  
  11.     servers = memcached_server_list_append(servers,"localhost",11210,&rc);  
  12.   
  13.   
  14.     rc = memcached_server_push(mem,servers);  
  15.     memcached_server_free(servers);  
  16.   
  17.     printf("the server count is %d",memcached_server_count(mem));  
  18.     const charconst keys[] = {"key1","key2","key3","key4"};  
  19.     char* values[] = {"value1","value2","value3","value4"};  
  20.   
  21.     for(int i = 0 ; i < 4; i++){  
  22.         memcached_set(mem,keys[i],strlen(keys[i]),values[i],strlen(values[i]),0,0);  
  23.   
  24.     }  
  25.   
  26.     size_t value_length[4];  
  27.     uint32_t flag;  
  28.     for(int i = 0; i < 4; i++){  
  29.         values[i] = memcached_get(mem,keys[i],strlen(keys[i]),&value_length[i],&flag,&rc);  
  30.         printf("the value is %s\n",values[i]);  
  31.     }  
  32.   
  33.     char* value = "zhou";  
  34.     size_t flag2;  
  35.   
  36.     value = memcached_get_by_key(mem,keys[1],strlen(keys[1]),keys[1],strlen(keys[1]),&flag2,&flag,&rc);  
  37.     printf("the value is %s\n",value);  
  38.     memcached_free(mem);  
  39.     return 0;  
  40.   
  41. }  
三。

A.有关memcached的C语言接口——libmemcached的介绍。

   详情参见:http://docs.libmemcached.org/index.html    1.       创建和删除memcached_st结构。

#include <libmemcached/memcached.h>

memcachd_st ;该结构可以静态创建也可以由memcached_create动态创建。

 

memcached_st* memcached_create(memcached_st *ptr)

ptr不为空时是静态创建,如果ptr为空,那么该函数返回一个memcached_st结构。

 

void memcached_free(memcached_st *ptr)

释放memcached_st结构所用的内存,删除memcached_st

 

memcached_st* memcached_clone(memcached_st *destination, memcached_st *source)

克隆一个memcached_st结构;如果source为空,那么其作用和memcached_create一样,如果destination为空,则该函数的返回值将会返回一个和source一样的memcached_st结构。

 

void memcached_servers_reset(memcached_st)

memcached_st所拥有与服务器的连接全都断开。

 

Compile and link with –lmemcached

2.    Memcached_return_t的返回值。

MEMCACHED_SUCCESS表示操作成功,其他均表示错误;其他错误的详情参考:http://docs.libmemcached.org/error_messages.html

3.       增加和减少值。

#include <libmemcached/memcached.h>

memcached_return_t memcached_increment (memcached_st *ptr, const char *key, size_t key_length, unsigned int offset, uint64_t *value)

 

memcached_return_t memcached_decrement (memcached_st *ptr, const char *key, size_t key_length, unsigned int offset, uint64_t *value)

offset是其增加或者减少的数值,改变后的值通过value指针返回。

其他增加和减少操作参见:

http://docs.libmemcached.org/memcached_auto.html

4.       从服务器获取值。

#include <libmemcached/memcached.h>

char * memcached_get(memcached_st *ptr, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error)

一次通过一个键获取一个值。

memcached_return_t memcached_mget(memcached_st *ptr, const char * const *keys, const size_t *key_length, size_t number_of_keys)

memcached_result_st * memcached_fetch_result(memcached_st *ptr, memcached_result_st *result, memcached_return_t *error)

以上两个函数同时配合使用,一次调用可以通过多个键获取多个值。先通过memcached_mget调用获取多个键的值,这些值通过循环调用memcached_fetch_result来获得每一个键所对应的值,直到该函数返回0

5.       Store, Add and Replace的操作。

memcached_return_t memcached_set (memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags);

memcached中如果存在该键,则利用新值去替换,否则将该记录写入memcached中。

 

memcached_return_t memcached_add (memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags);

如果memcached中存在该键,发生错误;否则将该记录添加进memcached中。

 

memcached_return_t memcached_replace (memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags);

如果memcached中没有该键,发生错误;否则替换value

以上三个函数中,key的长度不能超过250个字符,value是一个16个字节的值。Expiration是该记录在memcached的有效时间,即是超时时间。

6.       删除操作。

memcached_return_t memcached_delete (memcached_st *ptr, const char *key, size_t key_length, time_t expiration);

该函数将与key对应的记录放入删除队列中,并且通过expiration指定该记录从服务器删除的时间。

7.       断开客户端与服务器的连接。

void memcached_quit (memcached_st *ptr);

 

 

 

 

使用遇到的:

memcached_server_list_st memcached_server_list_append(memcached_server_list_st list, const char *hostname, unsigned int port, memcached_return_t *error)

该函数是将要连接的服务器添加到memcached_server_st数组中,返回值为NULL时表示出现错误,如果未指定port端口则使用默认的端口。

 

memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_st *list)

该函数将 memcached_server_st数组添加到memcached_st结构中。

 

void memcached_server_list_free(memcached_server_list_st list)

释放memcached_server_list_st所占据的内存。


B.一个实例。

Memcached 缓存系统的基础知识


C.libmemcached库的安装方法

下载libmemcached之后,解压,然后./configure 最后make 以及make install

注意:需要将libmemcached库的路径并不会被系统自动搜索。该库在使用时需要重新进行定位,详见动态库的重定位