1 命令行查看状态
很多时候我们需要去查看Memcached 的使用状态,比如Memcached
的运行时间,使用状态等等。在Windows系统中我们可以使用telnet 命令来查看Memcached
的相关运行情况。
开始—>运行àcmd 运行得到如下:
输入telnet命令: telnet 服务地址 端口
Memcached 的默认端口号是11211
输入stats 命令: 在这里屏幕是空白,看不到输入的内容,回车之后可以看到Memcached的运行相关信息。
Pid: Memcached 服务器中的进程编号
Uptime:Memcached服务器启动之后所经历的时间,单位秒
Time: 当前系统时间,单位秒
Version: Memcached 的版本号
pointer_size:服务器所在主机操作系统的指针大小,一般为32或64
curr_items:表示当前缓存中存放的所有缓存对象的数量
total_items:表示从memcached服务启动到当前时间,系统存储过的所有对象的数量,包括已经删除的对象
bytes:表示系统存储缓存对象所使用的存储空间,单位为字节
curr_connections:表示当前系统打开的连接数
total_connections:表示从memcached服务启动到当前时间,系统打开过的连接的总数
cmd_get: 查询缓存的次数,即使不成功也算一次
cmd_set: 保存数据的次数,当然这里只保存成功的次数
get_hits:表示获取数据成功的次数。
get_misses:表示获取数据失败的次数。
evictions:为了给新的数据项目释放空间,从缓存移除的缓存对象的数目。比如超过缓存大小时根据LRU算法移除的对象,以及过期的对象
bytes_read:memcached服务器从网络读取的总的字节数
bytes_written:memcached服务器发送到网络的总的字节数
limit_maxbytes:memcached服务缓存允许使用的最大字节数
threads:被请求的工作线程的总数量
缓存命中率 = get_hits / cmd_get * 100%
;
2 Memcached 存储机制
关于Memcached的存储机制,在网上搜了一下讲解基本上都是千篇一律的。
memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在之前的版本中,Memcached存储会导致很多内存碎片,从而加重了操作系统对内存管理的负担。Slab
Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,
以完全解决内存碎片问题。
借用一张图说明一下:
Slab Allocation 将分配的内存分割成各种尺寸的chunk (块),并把大小相同尺寸的chunk分为一组,就如上图一样:分割了
88b,112b,144b等尺寸。其实Slab Allocation还有重复利用内存的功能,也就是说分配的内存不会释放,而是重复利用。
当存储数据的时候,它会自动去查找最为匹配的chunk,然后将数据存储到其中。比如我存储数据的大小为110B,那么它会存储到112B的chunk中。
上面的问题来了,我存储只需要110B,但是我存储到112B的chunk中。如下图(借用):
那么在110b的存储中会浪费2B的内存空间
至于如何完全解决这个内存空间浪费的问题,还没有很好的方案,不过Memcached的
增长因子(Growth Factor)能够适当解决此问题。目前Memcached的默认增长因子 是1.25,也就是说会以原有的最大值基础上乘以1.25
来分配空间。
3 Memcached 对内存资源的有效利用
之前已经提到过了,Memcached 会重复利用已经分配的内存,也就是说不会去删除已有的数据而且释放内存空间,而是数据过期之后,用户将数据不可见。
Memcached 还是用了一种Lazy Expiration (延迟过期[姑且这样翻译])
技术,就是Memcached不会去监视服务器上的数据是否过期,而是等待get的时候检查时间戳是否过期,减少Memcached在监控数据上所用到的时间。
Memcached 不会去释放已经使用的内存空间,但是如果分配的内存空间已经满了,而Memcached
是如何去保证内存空间的重复使用呢!Memcached 是用了 Least
Recently Used(LRU) 机制来协调内存空间的使用。LRU
意思就是最少最近使用,当此处内存空间数据最长时间没有使用,而且使用次数很少,在存储新的数据的同时就会覆盖此处空间。
4 Memcached 客户端使用简单封装
本文很多都是理论上的分析,这些大多也是从网络上看来的,根据自己的理解和实际的应用做了一些总结。有时候我们使用Memcached的客户端时并不是那么的友好,这里对其做了一下简单的封装,抽象出来了一个接口:
下面这段代码对上面的接口进行了实现,里面的代码大多数人应该能够看懂,是比较简单的代码封装,如果能够了解本人上一篇的简单应用,对于这个封装的理解应该没有难度。实现代码如下:
上面的代码没有注释,因为提交不了这么长的代码,去掉了注释。代码大家可以看懂的,这里不做过多的讲解。
|