memcached介绍与使用

Memcached是什么?

   Memcached是一个免费、开源、高性能的分布式内存对象缓存系统。通常用来增强web服务器的性能(通过缓存减轻数据库负担)。当然也可以用途其它系统的缓存。

   Memcached是一个内存key-value存储,主要用来存储从数据库、API调用、页面渲染获取的小对象(字符串、其它对象)。

   Memcached简单却强大。为了方便快速部署,易用而设计简单。它能解决大多数系统中的大数据量的缓存问题。它提供了大多数流行编程语言的API接口。

    最新版源代码下载地址:http://www.memcached.org/files/memcached-1.5.11.tar.gz

    使用Memcached的系统:

设计原则

   Memcached不关心你的数据是什么格式、什么大小。所有存入项都包含一个key、一个超时时间、可选flag、真正的二进制数据。不管你的数据是什么结构,你必须序列化为二进制以后进行存储。部分命令(incr/decr)必须依赖数据的类型,但也只是简单的约束。

    一个完整的Memcached系统一半逻辑是实现在客户端的,另一半在服务器。客户端必须自己选择到哪一个服务器去读写对象。并且当出现连接故障时,客户端要自己进行处理。服务器部分只管存储对象,并且在合适的时机回收再利用内存资源。

    每个Memcached服务器都是一个单独的进程,它们本身并不组成集群。利用多台服务器组成集群的逻辑是由客户端处理的。介绍中所说的分布式,其实是由客户端来进行协调实现的。

    所有命令的实现都被实现得尽可能地快,并且合理地使用锁。这样能够让多用户的访问场景有较快的速度。在配置差的机器上一个命令通常在1ms内响应。高配置的服务器每秒可以写入百万量级的对象。

    Memcached本质上是一个使用LRU策略的缓存系统。另外对象可以指定失效时间。这两种策略能够满足多数需求。失效时间能够避免返回陈旧的老对象,LRU策略能够回收老对象而保证新对象的使用。

    回收对象并不会导致服务器暂停,回收过程使用的是懒加收策略。具体可以查看文档 LRU documentation

性能指标

   在高配置的机器上,Memcached每秒可以轻松地处理超过20万条请求。如果加高配置,可以达到很多倍的性能提升。

网络协议

    Memcached支持TCP、UDP协议。建议不要开启UDP协议,避免被用作放大攻击。

    协议格式上支持文本和带结构的协议两种:

    Memcached文本协议

    Memcached二进制协议

主要命令

add、set、replace是三个主要的存储命令

<command name> <key> <flags> <exptime> <bytes>"r"n

<data block>"r"n

delete是删除命令

delete <key> <time>"r"n

telnet简单示例

$ telnet localhost 11211
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
add a 0 0 5        // 增加对象 key flag expiretime datalen
hello              // 数据
STORED
get a              // 获取数据
VALUE a 0 5        // 返回 key flag datalen 
hello              // data
END
replace a 0 0 5    // 更新对象 key flag expiretime datalen 
world
STORED   
delete a           // 删除数据
DELETED
stats
STAT pid 8861
(etc)

python示例

#!/usr/bin/env python

import memcache

mc = memcache.Client(['127.0.0.1:12000'],debug=0)

mc.set("some_key", "Some value")
value = mc.get("some_key")

mc.set("another_key", 3)
mc.delete("another_key")

mc.set("key", "1")   # note that the key used for incr/decr must be a string.
mc.incr("key")
mc.decr("key")

内存管理

存储方式

        为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached、重启操作系统会导致全部数据消失。另外,缓存的内容容量达到指定值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。memcached本身是为缓存而设计的服务,因此并没有过多考虑数据的永久性问题。

内存结构

        memcached仅支持基础的key-value键值对类型数据存储。在memcached内存结构中有两个非常重要的概念:slab和chunk。 
slab是一个内存块,它是memcached一次申请内存的最小单位。在启动memcached的时候一般会使用参数-m指定其可用内存,但是并不是在启动的那一刻所有的内存就全部分配出去了,只有在需要的时候才会去申请,而且每次申请一定是一个slab。Slab的大小固定为1M(1048576 Byte),一个slab由若干个大小相等的chunk组成。每个chunk中都保存了一个item结构体、一对key和value。

        虽然在同一个slab中chunk的大小相等的,但是在不同的slab中chunk的大小并不一定相等,在memcached中按照chunk的大小不同,可以把slab分为很多种类(class),默认情况下memcached把slab分为40类(class1~class40),在class 1中,chunk的大小为80字节,由于一个slab的大小是固定的1048576字节(1M),因此在class1中最多可以有13107个chunk(也就是这个slab能存最多13107个小于80字节的key-value数据)。 

Memcached内存结构图
Memcached内存结构图

        memcached内存管理采取预分配、分组管理的方式,分组管理就是我们上面提到的slab class,按照chunk的大小slab被分为很多种类。内存预分配过程是怎样的呢?向memcached添加一个item时候,memcached首先会根据item的大小,来选择最合适的slab class:例如item的大小为190字节,默认情况下class 4的chunk大小为160字节显然不合适,class 5的chunk大小为200字节,大于190字节,因此该item将放在class 5中(显然这里会有10字节的浪费是不可避免的),计算好所要放入的chunk之后,memcached会去检查该类大小的chunk还有没有空闲的,如果没有,将会申请1M(1个slab)的空间并划分为该种类chunk。例如我们第一次向memcached中放入一个190字节的item时,memcached会产生一个slab class 2(也叫一个page),并会用去一个chunk,剩余5241个chunk供下次有适合大小item时使用,当我们用完这所有的5242个chunk之后,下次再有一个在160~200字节之间的item添加进来时,memcached会再次产生一个class 5的slab(这样就存在了2个pages)。

注意事项

  • chunk是在page里面划分的,而page固定为1m,所以chunk最大不能超过1m。
  • chunk实际占用内存要加48B,因为chunk数据结构本身需要占用48B。
  • 如果用户数据大于1m,则memcached会将其切割,放到多个chunk内。
  • 已分配出去的page不能回收。
  • 对于key-value信息,最好不要超过1m的大小;同时信息长度最好相对是比较均衡稳定的,这样能够保障最大限度的使用内存;同时,memcached采用的LRU清理策略,合理甚至过期时间,提高命中率。

猜你喜欢

转载自blog.csdn.net/yuanfengyun/article/details/83213554