memcached是一个分布式,开源的数据存储引擎。php
memcached是一款高性能的分布式内存缓存服务器,经过减小查询次数来抵消沉重缓慢的数据集或API调用、提升应用响应速度、提升可扩展性。ios
在高并发的场景下, 大量的读/写请求涌向数据库, 此时磁盘IO将成为瓶颈, 从而致使太高的响应延迟, 所以缓存应运而生.git
Memcached的工做方式是将关键词和他们对应的值(最大能达到1MB)保存在一个关联矩阵中(好比哈希表),延展和分布在大量的虚拟服务器中。github
固然不管是单机缓存仍是分布式缓存都有其适用场景和优缺点, 最多见的有redis和memcached. 本文主要是介绍memcached.redis
硬盘 --> 内存 --> 三级缓存 --> 二级缓存 --> 一级缓存算法
首先访问较快的存储介质, 若是命中且未生效则返回内容. 若是命中或失效则访问较慢的存储介质将内容返回同时更新缓存.docker
特色 | 描述 |
---|---|
协议简单 | 它是基于文本行的协议,直接经过telnet在memcached服务器上可进行存取数据操做 |
基于libevent事件处理 | 异步I/O, 基于事件的单进程和单线程, 使用libevent做为事件处理机制; |
内置内存存储方式, 非持久性存储 | 全部数据都保存在内存中,存取数据比硬盘快,当内存满后,经过LRU算法自动删除不使用的缓存,但没有考虑数据的容灾问题,重启服务,全部数据会丢失。 |
分布式 | 各个memcached服务器之间互不通讯,各自独立存取数据,不共享任何信息。服务器并不具备分布式功能,分布式部署取决于memcache客户端。 |
# 安装依赖包
apt-get install libevent-dev
#安装Memcached
wget http://memcached.org/latest
tar -zxvf memcached-1.x.x.tar.gz
cd memcached-1.x.x
./configure && make && make test && sudo make install
#启动memcached
memcached -p 11211 -d -u root -P /tmp/memcached.pid
复制代码
-P是表示使用TCP,默认端口为11211 -d表示后台启动一个守护进程(daemon) -u表示指定root用户启动,默认不能用root用户启动 -P表示进程的pid存放地点,此处“p”为大写“P” -l,后面跟IP地址,手工指定监听IP地址,默认全部IP都在监听 -m后面跟分配内存大小,以MB为单位,默认为64M -c最大运行并发链接数,默认为1024 -f 块大小增加因子,默认是1.25 -M 内存耗尽时返回错误,而不是删除项,即不用LRU算法 在64位系统中,会报libevent-1.4.so.2文件没法找到,解决办法是把32位目录里的同名文件连接至64位目录中,即像windows那样创建快捷方式。 Shell > /usr/local/lib/libevent-1.4.so.2 /usr/lib64/libevent-1.4.so.2 启动后若是发现没有端口在监听,是由于命动命令时带pid参数的“p”是大写“P”,你可能写成小写了。数据库
// 运行一个内存限制为1024MB的容器:
sudo docker run -name csphere-memcached -m 1024m -d -p 11211:11211 memcached:alpine
复制代码
能够查看Memcached:latest
使用的 Dockerfile, 来获取 memcached在debian下的安装方法windows
分类 | 方法 | 描述 |
---|---|---|
存 | set | 添加一个新条目到memcached或是用新的数据替换替换掉已存在的条目 |
存 | add | 当KEY不存在的状况下,它向memcached存数据,不然,返回NOT_STORED响应 |
存 | replace | 当KEY存在的状况下,它才会向memcached存数据,不然返回NOT_STORED响应 |
存 | cas | 改变一个存在的KEY值 ,但它还带了检查的功能 |
存 | append | 在这个值后面插入新值 |
存 | prepend | 在这个值前面插入新值 |
取 | get | 取单个值 ,从缓存中返回数据时,将在第一行获得KEY的名字,flag的值和返回的value长度,真正的数据在第二行,最后返回END,如KEY不存在,第一行就直接返回END |
取 | get_multi | 一次性取多个值 |
删 | delete |
# 清空memcache数据
telnet 10.27.5.71 11211
flush_all
quit //退出telnet
复制代码
yum -y install libmemcached.x86_64 libmemcached-devel.x86_64
cd /usr/src
git clone https://github.com/php-memcached-dev/php-memcached.git
cd php-memcached/
git checkout php7
/alidata/server/php/bin/phpize
./configure --with-php-config=/alidata/server/php/bin/php-config
make
make install
复制代码
能够经过命令行直接管理与监控也可经过nagios等监控软件进行监控 命令行:缓存
// 若是在启动时指定了IP及端口号,这里要做相应改动,链接成功后命令
telnet 127.0.0.1 11211
复制代码
命令 | 描述 |
---|---|
stats | 统计memcached的各类信息 |
stats reset | 从新统计数据 |
stats slabs | 显示slabs信息,能够详细看到数据的分段存储状况 |
stats items | 显示slab中的item数目 |
stats cachedump 1 0 | 列出slabs第一段里存的KEY值 |
set/get | 保存/获取数据 |
STAT evictions 0 | 表示要腾出新空间给新的item而移动的合法item数目 |
Memcached利用slab allocation机制来分配和管理内存,它按照预先规定的大小,将分配的内存分割成特定长度的内存块,再把尺寸相同的内存块分红组,数据在存放时,根据键值 大小去匹配slab大小,找就近的slab存放,因此存在空间浪费现象。
传统的内存管理方式是,使用完经过malloc分配的内存后经过free来回收内存,这种方式容易产生内存碎片并下降操做系统对内存的管理效率。
Memcached的内存管理制效率高,并且不会形成内存碎片,可是它最大的缺点就是会致使空间浪费。由于每一个 Chunk都分配了特定长度的内存空间,因此变长数据没法充分利用这些空间。如图二所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了。
如何避免内存浪费
Memcached的缓存策略是**LRU(最近最少使用)**加上到期失效策略。当你在memcached内存储数据项时,你有可能会指定它在缓存的失效时间,默认为永久。当memcached服务器用完分配的内时,失效的数据被首先替换,而后也是最近未使用的数据。在LRU中,memcached使用的是一种Lazy Expiration策略,本身不会监控存入的key/vlue对是否过时,而是在获取key值时查看记录的时间戳,检查key/value对空间是否过时,这样可减轻服务器的负载。
当空间占满时
memcached不相互通讯,那么memcached是如何实现分布式的呢?
memcached的分布式实现主要依赖客户端的实现.
当数据到达客户端, 客户端实现的算法会根据”键”来决定保存的memcached服务器. 服务器选定后, 命令他保存数据. 取的时候也同样, 客户端根据”键”选择服务器, 使用保存时候的相同算法就能保存选中和存的时候相同的服务器.
也就是说,存取数据分二步走,第一步,选择服务器,第二步存取数据。
使用什么算法选择服务器呢?
client 使用Hash算法来完成数据分散存储.
复制代码
当向memcached集群存入/取出key/value时,memcached客户端程序根据必定的算法计算存入哪台服务器,而后再把key/value值存到此服务器中。也就是说,存取数据分二步走,第一步,选择服务器,第二步存取数据。
经常使用的算法有两种: 余数计算分散法 和 一致性Hash算法.
CRC($key)%N
复制代码
客户端首先根据key来计算CPC, 而后结果对服务器取模获得memcached服务器节点
将server的hash值分配至0~2^32的圆环上, 用一样的方法求出存储数值键的hash值并映射到圆上. 而后从数据映射到的位置开始顺时针查找, 将数据存放至找到的第一台服务器上. 若是超过0~2^32还找不到, 则将数据存放至第一台服务器.
若是新添/删除一台server, 在一致性hash算法下会有什么影响?
如图, 新添/删除server时, 只在圆上增长服务器的逆时针方向的第一台服务器上的键会受到影响。
优化一致性hash算法
优化后: 在物理机不多的状况下, 只要虚拟节点足够多, 也能使的key分布相对均匀. 提高了算法的平衡性.
单调性是指若是已经有一些内容经过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应可以保证原有已分配的内容能够被映射到新的缓冲中去,而不会被映射到旧的缓冲集合中的其余缓冲区。
复制代码
平衡性是指哈希的结果可以尽量分布到全部的缓冲中去,这样可使得全部的缓冲空间都获得利用。
复制代码
hash 算法并非保证绝对的平衡
对比点 | memcached | redis |
---|---|---|
数据结构 | 单一(存储数据的类型都是String字符串类型) | 丰富(String、List、Set、Sortedset、Hash) |
内存使用率 | 使用简单的key-value存储,Memcached的内存利用率更高 | Redis采用hash结构来作key-value存储,因为其组合式的压缩,其内存利用率会高于Memcached |
持久化 | 不能够 | 能够(能够把数据随时存储在磁盘上) |
数据同步 | 不能够 | 能够 |
多核 | 可使用多核(多线程) | 单核 |
数据大小 | 单个key(变量)存放的数据有1M的限制 | 单个key(变量)存放的数据有1GB的限制 |
计算能力 | 无 | 自己有必定的计算功能 |
memcached和redis对过时数据的处理
Redis是懒处理,对有有效期的数据会作有效期的标识,在指定时间会对有过时时间的数据作处理。随机取出一部分数据,检查是否有过时数据,若是过时数据超过25/100,则反复此过程
它使用libevent,能够应付任意数量打开的链接(使用epoll,而非poll),使用非阻塞网络IO,分布式散列对象到不一样的服务器,查询复杂度是O(1)。
缓存命中率 = get_hits/cmd_get * 100%
一致性Hash
a. 在软件工程的项目实战中, 常常会遇到时间/空间的权衡, 缓存是权衡中被研究出的一种典型的技术, 而memcached又是此类技术中的佼佼者.
b. 在高并发环境下,大量的读、写请求涌向数据库,此时磁盘IO将成为瓶颈,从而致使太高的响应延迟,所以缓存应运而生。
c. 本文在理解缓存基本概念的状况下介绍了memcached的分布式算法实现原理