Memcache存储机制与指令汇总
1、memcache基本简介
memcached是高性能的分布式内存缓存服务器。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。
Memcache的运行图:
Memcache的特征
memcached作为高速运行的分布式缓存服务器,具有以下的特点。
1、基于C/S架构协议简单
memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议。 因此,通过telnet也能在memcached上保存数据、取得数据。
2、基于libevent的事件处理
libevent是个程序库,它将Linux的epoll、BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥O(1)的性能。memcached使用这个libevent库,因此 能在Linux、BSD、Solaris等操作系统上发挥其高性能。
3、内置内存存储方式
为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached、重启操作系统会导致全部数据消失。另外,内容容量达到指值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。memcached本身是为缓存 而设计的服务器,因此并没有过多考虑数据的永久性问题。
4、memcached不互相通信的分布式
memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互 相通信以共享信息。那么,怎样进行分布式呢?这完全取决于客户端的实现。(如下图所示)
2、理解memcache的内存存储
2.1、存储机制
Memcache采用的是Slab Allocator方式进行存储数据。这一机制可以很好的整理内存,以便重复利用,从而解决了内存碎片的问题。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。
2.2、Slab Allocator基本原理
1、按照预先规定的大小,将分配的内存以page(默认每个page为1M)为单位分为特定的块(chunk),并且把相同大小的chunk分成组(chunk的集合);
2、存储数据时,将会寻找与value大小相近的chunk区域进行存储;
3、内存一旦以page的形式分配出去,在重启前不会被回收或者重新分配,以解决内存碎片问题。(分配的内存不会释放,而是重复利用)
2.3、理解四个名词
【可参考下面的形象解析图进行理解】
Slab
用于表示存储的最大size数据,仅仅只是用于定义(通俗的讲就是表示可以存储数据大小的范围)。默认情况下,前后两个slab表示存储的size以1.25倍进行增长。例如slab1为96字节,slab2为120字节
Page
分配给Slab的内存空间,默认为1MB。分给Slab后将会根据slab的大小切割成chunk
Chunk
用于缓存记录的内存空间
Slab calss
特定大小的Chunk集合
2.4、Slab的内存分配具体过程
Memcached在启动时通过-m参数指定最大使用内存,但是这个不会一启动就占用完,而是逐步分配给各slab的。如果一个新的数据要被存放,首先选择一个合适的slab,然后查看该slab是否还有空闲的chunk,如果有则直接存放进去;如果没有则要进行申请,slab申请内存时以page为单位,无论大小为多少,都会有1M大小的page被分配给该slab(该page不会被回收或者重新分配,永远都属于该slab)。申请到page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk的数组,再从这个chunk数组中选择一个用于存储数据。若没有空闲的page的时候,则会对改slab进行LRU,而不是对整个memcache进行LRU。
形象解析图:(这图凑合凑合就好了哈,不是很专业2333)
2.5、Memcache存储具体过程
Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列slabs,每个slab只负责一定范围内的数据存储。memcached根据收到的数据的大小,选择最适合数据大小的slab。假若这个slab仍有空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中;若无则申请page(1M)【可以参考上面我画的形象图23333】
具体分析:从上面我们了解到slab的作用。Slab的增长因子默认以1.25倍进行增长。那为什么会导致有些不是1.25倍呢?答案是受小数的影响,你可以使用-f int测试个整数增长因子看看效果。【后面具体讲解】
以下图进行分析,例如slab中112字节,表示可以存储大于88字节且小于或等于112字节的value。
2.6、Slab Allocator缺点
Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。
这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节 的数据缓存到128字节的chunk中,剩余的28字节就浪费了(如下图所示)。
2.7、使用-f增长因子进行调优
增长因子就是相邻两个chunk之间的增长倍数。这个参数memcache默认是1.25,但是我们先采用整数2来测试一下,看看效果。
由图中我们可以看到chunk size的增长是2倍的。
我们再来看看-f 1.25的效果
为什么1.25倍增长因子就不能保证全部相邻的chunk size是1.25倍增长呢?
因为这些误差是为了保持字节数的对齐而故意设置的。
两图一对比,可见,因子为1.25组间差距比因子为2时小得多,更适合缓存几百字节的记录。
因此,使用memcached时,最好是重新计算一下数据的预期平均长度,调整growth factor,以获得最恰当的设置。
3、memcache删除机制
从上面我们知道,已经分配出去的内存是不会被释放回收的,记录超时后,客户端就无法看到该记录,其存储空间即可重复使用。
3.1、Lazy Expiration
memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,memcached不会在过期监视上耗费CPU时间。
3.2、LRU删除
memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况, 此时就要使用名为Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少 使用”的记录的机制。因此,当memcached的内存空间不足时(无法从slab class获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想。
不过,有些情况下LRU机制反倒会造成麻烦。memcached启动时通过“M”参数可以禁止LRU。
启动时必须注意的是,小写的“m”选项是用来指定最大内存大小的。不指定具体数值则使用默认 值64MB。
指定“M”参数启动后,内存用尽时memcached会返回错误。话说回来,memcached毕竟不是存储器,而是缓存,所以推荐使用LRU。
4、启动memcache参数
【黑体字的参数较为常用】
-p<num> |
监听的TCP端口(默认:11211) |
-U<num> |
UDP监听端口(默认:11211 0关闭) |
-d |
以守护进程方式运行 |
-u<username> |
指定用户运行 |
-m<num>. |
最大内存使用,单位MB。默认64MB |
-c<num> |
最大同时连接数,默认是1024 |
-v |
输出警告和错误消息 |
-vv |
打印客户端的请求和返回信息 |
-h |
帮助信息 |
-l<ip> |
绑定地址(默认任何ip地址都可以访问) |
-P<file> |
将PID保存在file文件 |
-i |
打印memcached和libevent版权信息 |
-M |
禁止LRU策略,内存耗尽时返回错误 |
-f<factor> |
增长因子,默认1.25 |
-n<bytes> |
初始chunk=key+suffix+value+32结构体,默认48字节 |
-L |
启用大内存页,可以降低内存浪费,改进性能 |
-l |
调整分配slab页的大小,默认1M,最小1k到128M |
-t<num> |
线程数,默认4。由于memcached采用NIO,所以更多线程没有太多作用 |
-R |
每个event连接最大并发数,默认20 |
-C |
禁用CAS命令(可以禁止版本计数,减少开销) |
-b |
Set the backlog queue limit (default: 1024) |
-B |
Binding protocol-one of ascii, binary or auto (default) |
-s<file> |
UNIX socket |
-a<mask> |
access mask for UNIX socket, in octal (default: 0700) |
5、Memcache指令汇总
指令 |
描述 |
例子 |
get key |
#返回对应的value |
get mykey |
set key 标识符 有效时间 长度 |
key不存在添加,存在更新 |
set mykey 0 60 5 |
add key标识符 有效时间 长度 |
#添加key-value值,返回stored/not_stored |
add mykey 0 60 5 |
replace key标识符 有效时间 长度 |
#替换key中的value,key存在成功返回stored,key不存在失败返回not_stored |
replace mykey 0 60 5 |
append key标识符 有效时间 长度 |
#追加key中的value值,成功返回stored,失败返回not_stored |
append mykey 0 60 5 |
prepend key标识符 有效时间 长度 |
#前置追加key中的value值,成功返回stored,失败返回not_stored |
prepend mykey 0 60 5 |
incr key num |
#给key中的value增加num。若key中不是数字,则将使用num替换value值。返回增加后的value |
Incre mykey 1 |
decr |
#同上 |
同上 |
delete key [key2…] |
删除一个或者多个key-value。成功删除返回deleted,不存在失败则返回not_found |
delete mykey |
flush_all [timeount] |
#清除所有[timeout时间内的]键值,但不会删除items,所以memcache依旧占用内存 |
flush_all 20 |
version |
#返回版本号 |
version |
verbosity |
#日志级别 |
verbosity |
quit |
#关闭连接 |
quit |
stats |
#返回Memcache通用统计信息 |
stats |
stats slabs |
#返回Memcache运行期间创建的每个slab的信息 |
stats slabs |
stats items |
#返回各个slab中item的个数,和最老的item秒数 |
stats items |
stats malloc |
#显示内存分配数据 |
stats malloc |
stats detail [on|off|dump] |
#on:打开详细操作记录、off:关闭详细操作记录、dump显示详细操作记录(每一个键的get、set、hit、del的次数) |
stats detail on stats detail off stats detail dump |
stats cachedump slab_id limit_num |
#显示slab_id中前limit_num个key |
stats cachedump 1 2 |
stats reset |
#清空统计数据 |
stats reset |
stats settings |
#查看配置设置 |
stats settings |
stats sizes |
#展示了固定chunk大小中的items的数量 |
Stats sizes |
注意:标识符:一个十六进制无符号的整数(以十进制来表示),需和数据一起存储,get的时候一起返回
ps:最近老是思考以后的方向,感觉有点迷茫,都不能好好学习了。要尽快调整好心态,切勿浮躁,欲速则不达。
参考资料:
1、Memcached原理与使用详解 作者:heiyeluren(黑夜路人)
http://blog.csdn.net/heiyeshuwu
2 、memcached 全面剖析 作者:长野雅广、前坂徹 charlee 译
3、Memcache 内存分配策略和性能(使用)状态检查 作者:jyzhou
http://www.cnblogs.com/zhoujinyi/p/5554083.html
作者:那一叶随风
声明:转载时请在文章页面明显位置给出原文链接
Memcache存储机制与指令汇总的更多相关文章
- memcache redundancy机制分析及思考
设计和开发可以掌控客户端的分布式服务端程序是件幸事,可以把很多事情交给客户端来做,而且可以做的很优雅.角色决定命运,在互联网架构中,web server必须冲锋在前,注定要在多浏览器版本以及协议兼容性 ...
- memcache 存储单个KEY,数据量过大的时候性能慢!以及简单的memcache不适合用到的场景
今天有人问到我:memcache存储大数据量,10K,100K,1M的时候,效果怎么样??我回答:不好,效果非常慢.对方问:为什么啊??我回答不上来...于是就找了点资料. memcached使用需要 ...
- Memcache存储大量数据的问题
Memcache存储大数据的问题 huangguisu Memcached存储单个item最大数据是在1MB内,假设数据超过1M,存取set和get是都是返回false,并且引起性能的问题. 我们之 ...
- Dockerfile 指令汇总及解析
原文地址:http://www.maoyupeng.com/dockerfile-command-introduction.html 什么是Dockerfile Dockerfile是由一系列 ...
- 再理解HDFS的存储机制
再理解HDFS的存储机制 1. HDFS开创性地设计出一套文件存储方式.即对文件切割后分别存放: 2. HDFS将要存储的大文件进行切割,切割后存放在既定的存储块(Block)中,并通过预先设定的优化 ...
- Java提高篇——通过分析 JDK 源代码研究 Hash 存储机制
HashMap 和 HashSet 是 Java Collection Framework 的两个重要成员,其中 HashMap 是 Map 接口的常用实现类,HashSet 是 Set 接口的常用实 ...
- Kafka文件的存储机制
Kafka文件的存储机制 同一个topic下有多个不同的partition,每个partition为一个目录,partition命名的规则是topic的名称加上一个序号,序号从0开始. 每一个part ...
- Linux常用到的指令汇总
Linux常用到的指令汇总 根据鸟哥linux私房菜上定义的:一定要先學會的指令:ls, more, cd, pwd, rpm, ifconfig, find 登入與登出(開機與關機):telnet, ...
- ios开发之数据的持久化存储机制
IOS中数据的持久化保存这块内容,类似于Android中文件的几种常见的存储方式. 对于数据的持久化存储,ios中一般提供了4种不同的机制. 1.属性列表 2.对象归档 3.数据库存储(SQLite3 ...
随机推荐
- link js重构心得
过年前后一段时间,对link库的代码进行的大量的重构,代码精简了许多,性能也得到了很大的改善,写此文记录期间所做的改进和重构,希望对看到此文的js程序员有所帮助. 1. 代码构建 最初代码使用gulp ...
- 反汇编看c++引用
继续反汇编系列,本次使用vc2008在x86体系下分析c++中的引用. 定义一个引用类型和将一个变量转换成引用类型一样吗? 引用比指针安全,真的是这样吗,对引用不理解的话比指针还危险. 为什么要用常量 ...
- Python dir()/help()
dir() dir()用来查询一个类或者对象所有属性.你可以尝试一下 print dir(list) 返回的结果: ['__add__', '__class__', '__contains__', ' ...
- GCD(关于容斥原理)
Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD( ...
- 在2017年,如何将你的小米4刷上Windows 10 mobile?
众多攻略集大成者!资深软粉亲测有效! 参考教程: http://bbs.xiaomi.cn/t-11814358 http://bbs.xiaomi.cn/t-11736827 问:刷机前,我需要做什 ...
- 安居客Android项目架构演进
入职安居客三年从工程师到Team Leader,见证了Android团队一路走来的发展历程.因此有心将这些记录下来与大家分享,也算是对自己三年来一部分工作的总结.希望对大家有所帮助,更希望能得到大家宝 ...
- 安卓的UI界面开发(初学者推荐)
一 随便扯扯 用户界面设计是程序开发的一项重要内容.在界面设计的过程中,需要考虑如何制作出UI界面,怎么样控制UI界面两大块. 任何有编程常识的人都知道:软件界面是开发者添加控件,编写控件控制逻辑, ...
- Mac入门推荐(写给Mac小白)
本人第一次接触Mac是在2016年10月中旬,那时由于对苹果系统的不熟悉,导致自己一开始的时候用的很不习惯,甚至还想换回Windows系统.总所周知,苹果系统的软件比较少,在此我向大家推荐一些个人觉得 ...
- instance “error” 了怎么办?- 每天5分钟玩转 OpenStack(159)
这是 OpenStack 实施经验分享系列的第 9 篇. OpenStack 用多了,经常会遇到这种情况:对 instance 执行某个操作如果失败了就会处于 "error" 状态 ...
- spring提供的线程池
SPRING中的线程池ThreadPoolTaskExecutor 分类: JAVA Spring2013-07-12 10:36 14896人阅读 评论(9) 收藏 举报 Spring线程池多线程 ...