memcache详解

一、缓存服务器相关概念
二、memcache简介
三、memcache配置实现
四、memcache整合

一、缓存服务器相关概念

专用缓存服务器:squid,varnish,memcached,redis
第三方模块的缓存:nginx,http

squid:太古老,不推荐
varnish用来做网站和小文件的缓存,相当给力的,做图片cache之类的合适,varnish没有专门的存储引擎,但是不能cache到本地硬盘上的。
Varnish可以使用正则表达式快速、批量地清除部分缓存,varnish的内存管理完全交给内核,当缓存内容超过内存阈值时,内核会自动将一部分缓存存入swap中让出内存。以挪威一家报社的经验,1台varnish可以抵6台squid的性能。
nginx:nginx本来是反向代理/web服务器,用了插件可以做做这个副业,但是本身不支持的性能比较多。

CDN选型:

1)单点问题

防止单点问题,但是如果只是简单做负载均衡,单台CDN server上需要存储全部数据,存储利用率太低了。
squid支持几个实例并联,实际使用的人不多;
varnish 只能用单实例;
nginx+memcache 天然的分布式存储;
采用squid/varnish 也有解决办法: 需要在它们前面部署一个支持url hash的负载均衡设备(硬件,软件均可,比如说haproxy)

2)内存存储的代价

CDN把缓存放在内存当中,提升性能。但是当服务遭遇故障重启之后,全部数据都会丢失需要重建,这个时候会给后端应用服务器带来很大的短时压力服务需要较长的时间才能完全恢复.
而实际运行当中,由于各种原因,CDN服务重启的概率相当高.

3)动态请求

动态网页使用CDN,无论squid还是varnish都不能直接用,都需定制代码。这样面临的问题是命中率高低和维护成本的问题

4)purge效率

purge就是CDN删除缓存项的接口,国内的UGC网站,因为严厉的内容检查制度和泛滥的垃圾广告,删帖子删图片特别频繁,某些网站可能高达40%(发100个贴,有40个帖子可能被删除或者修改),所以对purge的效率有要求。
squid和varnish的purge效率都达不到国内这种强度要求,nginx+memcache purge性能要好很多。
在国内,遇到突发事件后,要是不及时删除指定的链接或内容,后果可能会很严重(小到个人被炒,大到公司被关都有可能)

5)推荐

中小型网站直接买CDN服务就好,现在CDN已经进行按需付费的云计算模式了,性价比是可以准确计算的;
外地部署单点,推荐用squid;
准备在公司内部实施私有云战略,推荐nginx+memcache;
不太建议使用varnish。

二、memcache简介

1、数据结构模型:

结构化数据:关系型数据库;//多表查询是一个非常慢的过程,占用大量的内存,甚至磁盘空间 //关系型数据库在个应用场景中都成为了瓶颈
半结构化数据:xml,json,...(NoSQL)
非结构化数据:文件系统,
所有的缓存都是kv数据:
k:查询语句或者访问的资源的 url
v:所对应的文件对应的md5码,可以分级存储
//查询时间是恒定的,O(1),速度很快
k/V存储:
memcached:存储于内存中,部署相对简单
redis: 存储于内存中,周期性将数据同步于disk上

2、memcached:

Livejournal旗下的Danga Interactive
c++里分配内存有两种方式,预先分配和动态分配,显然,预先分配内存会使程序比较快,但是它的缺点是不能有效利用内存,而动态分配可以有效利用内存,但是会使程序运行效率下降,memcached的内存分配就是基于以上原理,显然为了获得更快的速度,有时候我们不得不以空间换时间。
memcache的内存存储:
Memcache使用了Slab Allocator的内存分配机制:按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。
Memcache的存储涉及到slab,page,chunk三个概念
1.Chunk为固定大小的内存空间,默认为48Byte。
2.page对应实际的物理空间,1个page为1M。
3.同样大小的chunk又称为slab。
Slab Allocator的缺点:特定长度的内存,因此无法有效利用分配的内存。例如,将100 字节的数据缓存到128 字节的chunk 中,剩余的就浪费了
Grow Factor:增长因子 //控制slab之间的差异
memcached 在启动时指定Growth Factor 因子(通过f 选项),就可以在某种程度上控制slab 之间的差异。默认值为1.25。但是,在该选项出现之前,这个因子曾经固定为2,称为“powers of 2”策略。
memcache启动verbose查看:

    slab class 1: chunk size 128 perslab 8192
    slab class 2: chunk size 256 perslab 4096
    slab class 3: chunk size 512 perslab 2048
    ... n为(n-1)*2

特性:
1.k/V缓存:可以缓存所有的可序列化数据
//数据能够打散存储,还能够还原的数据
存储项:key,value,flag,expire time;
2.功能的实现一半依赖于服务端,一半依赖于客户端
3.分布式缓存:可能一个数据分段后分别存储在多个s上
//各缓存s互不通信
4.O(1)的执行效率,
5.清理过期数据,LRU(内存不足时开启):最近最少使用 //Memcached 不会释放已经分配的内存,记录过期之后,客户端无法再看到这一条记录,其存储空间就可以利用。
缓存项过期 //memcahe自身不会检测是否过期,而是在get 时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,memcached不会在过期监视上耗费CPU 时间
缓存空间用尽
memcached -M //禁用LRU

3、序列化数据:

含义:将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。
序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。
反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。
特点:如果某个类能够被序列化,其子类也可以被序列化。
用途:
一:对象序列化可以实现分布式对象。
二:对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。
可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。
利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
目的:序列化的目的是为了便于传输,要点在于能够保存对象的状态信息,进行传输

4、缓存系统的种类

代理式缓存:例如nginx做proxy,假如本地缓存没有,nginx会代client去向RS请求
旁路式缓存:假如本地缓存没有命中,client需要自己去找存储端取,
//一半在memecache中一半在client端
//client决定是否查找缓存,以及查找哪个缓存,查找完后,是否缓存下来
如何保证在缓存系统中,(确定是否有缓存)一次命中//有就返回,没有就直接说没有

5、memcache的分布式

memcached 不互相通信的分布式
memcached 尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached 不会互相通信以共享信息。那么,怎样进行分布式呢?这完全取决于客户端的实现。

6、基于缓存查询算法实现:

1)取模法,(余数)
把key进行hash,对s的数量取模,(只要key没有变,他的hash码就没有变)
缓存数据的时候,取模后,存储在对应的s上[例如S3],查询的时候,同样对key取模,到对应s上去查看
缺陷:主机故障,少了一台,所有原有key都失效了,因为s数量已经发生改变,缓存对应数据取模也发生了改变 //现在的大站点,高度依赖于缓存系统,一个故障,全部玩完

2)一致性hash算法
对s的ip进行hash,然后对2^32取模,数值范围{0-[2^32-1]}
对key做hash然后2^32取模, //顺时针距离他最近的节点做缓存节点
0——[2^32-1] //组成一个环,
查找:对key做hash,取模,然后顺时针找距离他最近的
//即使有一台缓存s挂了,不影响其他s的缓存
极端情况:hash码偏斜
对A,B,C做hash的结果如下,A会承载了多半的负担
图1:
memcache详解

三、memcache配置实现

[root@localhost ~]# rpm -ql memcached

/etc/sysconfig/memcached  //修改该配置文件,定义
/usr/bin/memcached
/usr/bin/memcached-tool
/usr/lib/systemd/system/memcached.service

连配置文件都没有,启动的时候直接定义选项即可
systemctl start memcached //tcp,dup 11211

1、memcache常见命令

telnet 127.0.0.1 11211
命令:

    统计类:stats 
        stats items
        stats slabs
        stats sizes
STAT limit_maxbytes 134217728      #  分配给memcache的内存大小(字节)
STAT bytes 609350    # 当前服务器存储items占用的字节数
STAT curr_items 4668    # 服务器当前存储的items数量
STAT evictions 0     # 分配给memcache的空间用满后需要删除旧的items数,踢出。
STAT reclaimed 27160  #回收再利用,已过期的数据条目来存储新数据。
    存储类:set,add,replace,append,prepend
        pepend:前插入
        append:后插入
    获取数据类:get,delete,incr/decr
    清空:flush_all //清空所有记录
        //memcached惰性清理,缓存过期了,标识为0,并不真的清理,只有在满了的时候清理

set mykey 0 60 11 //标志 换存时长  字长
hello world
stats items
get mykey

append mykey 0 300 4 //添加4个字符
prepend mykey 0 300 4   

quit //退出
ctrl +u 可以使用

set mykey 0 300 1
0 //存储数值为0
get mykey
incr mykey 3 //增加3
get mykey 
decr myeky 3 //减3

2、memcached命令简介

memcached:

    -l 监听的地址
    -d 以守护进程模式运行
    -u 运行身份
    -m 内存使用大小,默认64m
    -c max并发连接数,默认1024
    -p 监听的tcp端口,默认11211
    -U udp,监听的udp端口,默认11211
    -M 缓存空间耗尽时,向请求者返回错误信息,而不是基于LRU算法清理
    -f [factor] growth factor,增长因子
        不断的增加删除可能会导致内存碎片
        解决内存碎片的策略:memcached:
            例如对内存进行分片,1k的n个,2k的n个,4k的n个
                根据缓存项的大小进行存放,减少了碎片,但是会造成内存浪费
                一个萝卜一个坑,有的萝卜大有的萝卜小,小萝卜占用大坑,就浪费了
            factor就是增长的因子,  
                每一级比他的上一级大多少,增长倍数
            例如最少:40,下一个就是40*1.25 //默认增长因子是1.25
    -n 最小chunk大小字节  
    -t threads线程数,默认4
[root@localhost ~]# memcached -u memcached -f 2 -vv
slab class   1: chunk size        96 perslab   10922    //大约1M,96*10922/1024=1023KB==1M
slab class   2: chunk size       192 perslab    5461        //每一个slab class上有5461个192Bytes大小的chrunk
slab class   3: chunk size       384 perslab    2730
slab class   4: chunk size       768 perslab    1365
slab class   5: chunk size      1536 perslab     682
slab class   6: chunk size      3072 perslab     341
slab class   7: chunk size      6144 perslab     170
slab class   8: chunk size     12288 perslab      85
slab class   9: chunk size     24576 perslab      42
slab class  10: chunk size     49152 perslab      21
slab class  11: chunk size     98304 perslab      10
slab class  12: chunk size    196608 perslab       5
slab class  13: chunk size    393216 perslab       2
slab class  14: chunk size   1048576 perslab       1  //最大为1048576,再大不给于缓存,还没有用完64M,大约使用了14M

每一个大小{96,192...}称为一个slab class
例如类别96的缓存项有10922个
类别为192的缓存项共有5461个

linux内存管理是基于页面进行管理的
n个4k组成了64M内存空间
每个页4K大小,每个4k应该属于一个slab类别,
slab类别中有多个叶匡组成,每个页框中再次划分
例如96字节:的共有10922个,等
内存:【slab | slab |slab | .... ... . ... 】
slab: 【slab class 96|slab class 96 | ....】
chunk:块,
slab:大块
page:分配给slab的内存空间,默认是1M,分配给slab之后根据slab的大小分成chunk
chunk:用于缓存记录的内存空间
slab class:特定大小的chunk 组
slab calss和chunk都是抽象的概念,只有page才是真实的

3、stats输出

名称 类型 含义
pid 2604 服务器进程ID
uptime 1061 服务器运行时间,单位秒
time 1543837789 服务器当前的UNIX时间
version 1.4.15 服务器的版本号
rusage_user 0.058755 该进程累计的用户时间(秒:微妙)
rusage_system 0.110598 该进程累计的系统时间(秒:微妙)
curr_items 0 服务器当前存储的内容数量
total_items 0 服务器启动以来存储过的内容总数
bytes 0 服务器当前存储内容所占用的字节数
curr_connections 10 连接数
total_connections 26 服务器运行以来接受的连接总数
connection_structures 11 服务器分配的连接结构的数量
cmd_get 1 取回请求总数
cmd_set 0 存储请求总数
get_hits 1 请求成功的总次数
get_misses 1 请求失败的总次数
bytes_read 341 服务器从网络读取到的总字节数
bytes_written 7452 服务器向网络发送的总字节数
limit_maxbytes 67108864 服务器在存储时被允许使用的字节总数
memcache详解

4、其他

memcached默认没有认证机制,但可以借助于SASL进行认证;
php连接memcached的模块:
memcache:php-percl-memcache
memcached:php-percl-memcached

yum -y install libmemcached //memcached的c接口
/usr/bin/memaslap
memcapable,memcat,memcp,memdump,memerror,memexist,memflush
memparse,memping,memrm,memslap,memstat,memtouch

提供众多的memcached工具包
memstat --servers=127.0.0.1 //显示状态信息

四、memcache整合

1、安装PHP的memcache扩展

# tar xf memcache-2.2.5.tgz
# cd memcache-2.2.5
/usr/local/php/bin/phpize
# ./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcache
# make && make install

上述安装完后会有类似以下的提示:
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/
编辑/usr/local/php/lib/php.ini,在“动态模块”相关的位置添加如下一行来载入memcache扩展:
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/memcache.so

而后对memcached功能进行 测试,在网站目录中建立测试页面test.php,添加如下内容:

<?php
    $mem = new Memcache;
    $mem->connect("127.0.0.1", 11211)  or die("Could not connect");

    $version = $mem->getVersion();
    echo "Server's version: ".$version."<br/>\n";

    $mem->set('hellokey', 'Hello World', 0, 600) or die("Failed to save data at the memcached server");
    echo "Store data in the cache (data will expire in 600 seconds)<br/>\n";

    $get_result = $mem->get('hellokey');
    echo "$get_result is from memcached server.";         
?>

如果有输出“Hello World is from memcached.”等信息,则表明memcache已经能够正常工作。

2、使用libmemcached的客户端工具:

访问memcached的传统方法是使用基于perl语言开发的Cache::memcached模块,这个模块在大多数perl代码中都能良好的工作,但也有着众所周知的性能方面的问题。libMemcached则是基于C语言开发的开源的C/C++代码访问memcached的库文件,同时,它还提供了数个可以远程使用的memcached管理工具,如memcat, memping,memstat,memslap等。
1) 编译安装libmemcached

# tar xf libmemcached-1.0.2.tar.gz 
# cd libmemcached-1.0.2
# ./configure 
# make && make install
# ldconfig

2) 客户端工具

# memcat --servers=127.0.0.1:11211 mykey
# memping 
# memslap
# memstat

3、Nginx整合memcached:

server {
    listen       80;
    server_name  www.magedu.com;
    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location / {
            set $memcached_key $uri;
            memcached_pass     127.0.0.1:11211;
            default_type       text/html;
            error_page         404 @fallback;
    }

    location @fallback {
            proxy_pass http://172.16.0.1;
    }
}

参考站点:
http://memcached.org/
https://github.com/memcached/memcached/wiki
https://www.cnblogs.com/kevingrace/p/6188123.html
https://www.cnblogs.com/usa007lhy/p/5503728.html

转载于:https://blog.51cto.com/hmtk520/2325602

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值