Memcache摘要
Memcached完全剖析(摘要)
一.memcached的基础
- memcached 是以LiveJournal 旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件。高性能的分布式内存缓存服务器。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。
一般情况下memcache的用途
3.memcache的特征:
b) 协议简单
c) 基于libevent的事件处理
d) 内置内存存储方式
e) memcached不互相通信的分布式
4.协议简单:memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议
5.基于libevent的事件处理: libevent是个程序库,它将Linux的epoll、BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥O(1)的性能。 memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能
6.内置内存存储方式:由于数据仅存在于内存中,因此重启memcached、重启操作系统会导致全部数据消失。另外,内容容量达到指定值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。
7.memcached不互相通信的分布式:memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息;分布式完全取决于客户端的实现
8.安装,启动等,略;
9.使用MemCachedlian:连接Memcached,略
- 保存数据:
向memcached保存数据的方法有
- add
- replace
- set
它们的使用方法都相同:
选项 |
说明 |
add |
仅当存储空间中不存在键相同的数据时才保存 |
replace |
仅当存储空间中存在键相同的数据时才保存 |
set |
与add和replace不同,无论何时都保存 |
- 获取数据:获取数据可以使用get和get_multi方法;一次取得多条数据时使用get_multi。get_multi可以非同步地同时取得多个键值,其速度要比循环调用get快数十倍。
- 删除数据:使用delete方法,不过它有个独特的功能。 $memcached->delete('键', '阻塞时间(秒)')
删除第一个参数指定的键的数据。第二个参数指定一个时间值,可以禁止使用同样的键保存新数据。此功能可以用于防止缓存数据的不完整。但是要注意,set函数忽视该阻塞,照常保存数据
- 增一和减一操作:可以将memcached上特定的键值作为计数器使用,增一和减一是原子操作,但未设置初始值时,不会自动赋成0。因此,应当进行错误检查,必要时加入初始化操作。而且,服务器端也不会对超过2 32时的行为进行检查
- 最近的memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片
- Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。Slab Allocation的原理相当简单。 将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合)slab allocator还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用
二.理解memcached的内存存储
- Slab Allocation的主要术语:
a) Page: 分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
b) Chunk: 用于缓存记录的内存空间.
c) Slab Class: 特定大小的chunk的组
- Slab中缓存记录的原理: memcached根据收到的数据的大小,选择最适合数据大小的slab。 memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。
- Slab Allocator的缺点:由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。目前还没有完美的解决方案,比较有效的解决方式是:如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费。现在还不能进行任何调优,但是,我们可以调节slab class的大小的差别。接下来说明growth factor选项。
- 使用Growth Factor进行调优:memcached在启动时指定 Growth Factor因子(通过-f选项),就可以在某种程度上控制slab之间的差异。默认值为1.25。
- 将memcached引入产品,或是直接使用默认值进行部署时,最好是重新计算一下数据的预期平均长度,调整growth factor,以获得最恰当的设置。以避免浪费内存。
- 查看memcached的内部状态:使用stats命令可以获得各种各样的信息
- 查看slabs的使用状况:使用memcached的创造着Brad写的名为memcached-tool的Perl脚本,可以方便地获得slab的使用情况
三. memcached的删除机制和发展方向
1 memcached不会释放已分配的内存。记录超时后,客户端就无法再看见该记录(invisible,透明),其存储空间即可重复使用
2 memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,memcached不会在过期监视上耗费CPU时间
3 当memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录(LRU:Least Recently Used)
4 memcached启动时通过“-M”参数可以禁止LRU, 指定“-M”参数启动后,内存用尽时memcached会返回错误
5 memcached的最新发展方向:两个大的目标。一个是二进制协议的策划和实现,另一个是外部引擎的加载功能
四. memcached的分布式算法
1 memcached分布式简单原理:假设memcached服务器有node1~node3三台,应用程序要保存键名为“tokyo”“kanagawa”“chiba”“saitama”“gunma” 的数据;
2 首先向memcached中添加“tokyo”。将“tokyo”传给客户端程序库后,客户端实现的算法就会根据“键”来决定保存数据的memcached服务器。服务器选定后,即命令它保存“tokyo”及其值
3 获取时也要将要获取的键“tokyo”传递给函数库。函数库通过与数据保存时相同的算法,根据“键”选择服务器。使用的算法相同,就能选中与保存时相同的服务器,然后发送get命令。只要数据没有因为某些原因被删除,就能获得保存的值
4 Perl客户端函数库Cache::Memcached实现的分布式方法:根据服务器台数的余数进行分散。求得键的整数哈希值,再除以服务器台数,根据其余数来选择服务器。
5 当选择的服务器无法连接时,Cache::Memcached会将连接次数添加到键之后,再次计算哈希值并尝试连接。这个动作称为rehash。不希望rehash时可以在生成Cache::Memcached对象时指定“rehash =>0”选项
6 根据余数计算分散的缺点:当添加或移除服务器时,缓存重组的代价相当巨大。添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器,从而影响缓存的命中率
7 新的分布式方法可以轻而易举地添加memcached服务器了。这种分布式方法称为 Consistent Hashing:先求出memcached服务器(节点)的哈希值,并将其配置到0~232的圆(continuum)上。然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过232仍然找不到服务器,就会保存到第一台memcached服务器上。
8 添加一台memcached服务器,在Consistent Hashing中,只有在continuum上增加服务器的地点逆时针方向的第一台服务器上的键会受到影响
五. memcached的应用
1 MIX(公司名字)中对memcached的应用
2 数据库服务器,应用服务器升级后,memcached服务器几乎不占用CPU,换下来的服务器用做memcached服务器
3 每台memcached服务器仅启动一个memcached进程。分配给memcached的内存为3GB
4 memcached启动时指定的内存分配量是memcached用于保存数据的量,没有包括“slab allocator”本身占用的内存、以及为了保存数据而设置的管理空间。因此,memcached进程的实际内存分配量要比指定的容量要大,这一点应当注意