数据缓存系统-memcached介绍

一、背景

一个计算机应用系统,如果存在对数据的存取,都离不开缓存,因为好的缓存,可以极大的提高应用系统的性能。

memcached就是一个开源的缓存系统,它开始是为网站缓存而开发的,它基于key-value这一通用的数据结构,采用C++开发。

二、事件通知机制

memcached基于libevent,因此在安装时,必须先安装libevent。对libevent,笔者目前未作深入研究,现引用libevent官网上的介绍吧。

“libevent的API提供了这样一种功能:当特定事件(基于文件描述符、信号或通常的时间事件)发生超时后,调用回调函数。

目前,libevent支持/dev/poll, kqueue(2), event ports, POSIX select(2), Windows select(), poll(2)和epoll(4),它内部的事件机制与外部暴露出来功能的是相互独立的,因此可以方便升级。libevent可以用于多线程,能够在Linux, BSD, Mac OS X, Solaris, Windows等平台上编译并运行。

另外,libevent提供了一套复杂的框架,可以支持带缓冲的network IO, sockets, filters, rate-limiting, SSL, zero-copy file transmission, and IOCP。libevent支持DNS, HTTP等"协议以及一个小型化的RPC框架。"

三、存储机制

快速保存,快速取出是缓存最主要的功能,因此缓存好坏的关键是存储机制。

memcached所有的数据都保存在内存中,重启或掉电之后,数据会消失,当数据存储到达限额后,会按照LRU(Least Recently Used)算法自动删除不使用的缓存,因此不要将memcached用于需要持久化存储场合。

我们知道,频繁的分配与释放大小不同的内存,会使内存产生很多碎片,影响内存的后续分配,因此,为提高内存的使用效率,memcached采用slab的方式,分配内存时,为一个slab class分配一个较大的内存块,一个slab中,在划分若个同样大小的chunk,如下图所示。

图中,表示了4个slab,slab class1中chunk的大小是88字节,当有小于88字节的内容需要存储时,存到slab class1中,同样,当有88-112字节的内容要存储时,保存到slab class2中。这样做的好处是减少了内存碎片,当slab class不释放时,可以重复利用已分配的内存,坏处当然是内存的空间利用效率可能不高。

为提高内存的空间利用效率,在系统启动时,可以指定一个叫Growth Factor的参数,该参数将影响各slab class的内存差异,即Growth Factor=class2中chunk的空间/class1中chunk的空间=class3中chunk的空间/class2中chunk的空间=...,说白了,就是各slab class中chunk的增长速度。

四、通讯协议

比较奇怪的是,memcached不使用复杂的协议,而使用一种近乎原始的基于文本行的协议,因此即使用telnet也能对memcached进行操作。在memcached的安装包中,有一个文件"protocol.txt",该文档描述了与memcached交互的协议。

有三种命令:

1.存储命令

存储命令有6个"set", "add", "replace", "append","prepend" ,"cas",它的格式如下

<command name> <key> <flags> <exptime> <bytes> [noreply]\r\n
cas <key> <flags> <exptime> <bytes> <cas unique> [noreply]\r\n

以上命令行后,紧接着就是数据块

<data block>\r\n

数据块是可以包含非显示字符,其大小在前面的命令行中指定。

发完数据后,客户端将得到返回值(如果需要),如下:

STORED\r\n :成功

NOT_STORED\r\n:有错误

EXISTS\r\n:已存在(cas)

NOT_FOUND\r\n:未找到(cas)


2.读取命令

读取命令有2个“get" , "gets",命令如下:

get <key>*\r\n
gets <key>*\r\n

其中<key>*表示key可以多个,各key之间用空格隔开。

客户端发出此命令后,服务器端将返回如下格式的数据:

VALUE <key> <flags> <bytes> [<cas unique>]\r\n
<data block>\r\n

其中data block的长度由bytes指定,如果客户端一次读取多个值(即get命令中有多个key),以上的格式也重复多次,服务器端发送完value后,再发送

END\r\n

来表示所有数据发送完毕,读取命令结束。

3.其他命令

其他命令包括删除、自增、状态等,如下表所示。

命令格式意义
Deletion发起:
delete <key> [noreply]\r\n
返回:
DELETED\r\n
NOT_FOUND\r\n
删除
Increment/Decrement发起:
incr <key> <value> [noreply]\r\n
decr <key> <value> [noreply]\r\n
返回:
NOT_FOUND\r\n
<value>\r\n
增加或减少存储的值(该值必须是一个unsigned 64bit integer),该功能可用于提供一个唯一数。
Touch发起:
touch <key> <exptime> [noreply]\r\n
返回:
TOUCHED\r\n
NOT_FOUND\r\n
该命令用来更新数据的过期时间(不致数据因长时间未访问而过期)。
Slabs Reassign发起:
slabs reassign <source class> <dest class>\r\n
返回:
OK
BUSY [message]
BADCLASS [message]
NOSPARE [message]
NOTFULL [message]
UNSAFE [message]
SAME [message]
当一个运行的slab实例达到它的限制,用来再分配内存用的。
Slabs Automove发起:
slabs automove <0|1>
返回:
是否允许后台有一个线程移动slab
Statistics发起格式:
stats <args>\r\n
返回格式:
STAT <name> <value>\r\n...END\r\n
args可以为 settings, items, sizes, slab。
状态显示命令,返回服务器的的一些状态数据。
Other commandsversion\r\n
quit\r\n
 

五、客户端

memcached实际上是一个服务器端程序,它本身没有提供客户端接口,因此如果应用memcached,我们还需要找一个客户端程序。从上面的协议可以看出,自己开发一个客户端并不特别困难,当然,也可以利用开源的,一个比较有名的是libmemcached,关于libmemcached的使用,可以另写一篇文章了,在此略去。

六、分布式应用

memcached宣称是一个分布式系统,其实是一种伪分布式,因为各节点既不是对等关系,也不是主从关系,它们之间并没用通讯,所以不能算一个严格的分布式系统。它的分布式是由客户端来体现的,即上面介绍的两段式Hash中的第一段,如果各客户端的算法都将某个key固定映射到某台机器上,就认为该机器缓存了该key的内容,这样,各key会映射到若干机器上,memcached的分布式就是如此体现的。

如此的分布应用,马上就会出现一个问题:增加或删掉一个节点(机器)怎么办?的确,对memcached来说,它的需求是:

1.不能保证每次都能得到缓存值(第一次当然不能保证,需要从真正的数据源中取,随后的第n次也不能保证);

2.客户端的Hash算法是特殊的。

参考文章中介绍了一种hash算法,可以有效地解决Hash算法的问题。在libmemcached客户端中,提供了consistent hashing选项,来保证当节点增加或失效时,cache的命中率不致下降太多。


(本文参考了长野雅广、前坂徹写的“memcached全面剖析”)


附:

memcached的启动与检测命令

  • 启动memcached举例:/usr/local/memcached/bin/memcached -d -c 10240 -m 1024 -u root
  • 获取运行状态:echo stats | nc localhost 11211(可以查看出pid) 或使用ps -ef|grep memcached
  • 停止memcached:kill -9 pid  (-9表示强制杀死,pid 为进程的进程标识符)
  • 可用telnet来连接测试是否安装启动成功。
  • 运行stats:   查询memcached状态


主要启动选项:
-d 选项是启动一个守护进程,
-m 是分配给Memcache使用的内存数量,单位是MB,这里是1024MB,默认是64MB
-u 是运行Memcache的用户,这里是root
-l 是监听的服务器IP地址,默认应该是本机
-p 是设置Memcache监听的端口,默认是11211,最好是1024以上的端口
-c 选项是最大运行的并发连接数,默认是1024,这里设置了10240,按照你服务器的负载量来设定
-P 是设置保存Memcache的pid文件位置
-h 打印帮助信息
-v 输出警告和错误信息
-vv 打印客户端的请求和返回信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值