mencached缓存服务器
Memcached是一个开源的,高性能,高并发的分布式内存缓存系统
-
服务端软件的名字形如:memcached-1.4.24.tar.gz
-
客户端软件的名字形如:memcache-2.25.tar.gz
Memcached的作用
传统场景,多数web应用都将数据保存到关系型数据库中(例如:MySQL),web服务器从中读取数据并在浏览器中显示,但是随着数据量的增大,访问的集中,关系型数据的负担就会出现加重,相应缓慢,导致网站打开延迟等问题,影响用户体验。
这时就需要memcached软件了,使用memcached主要目的是通过自身内存中缓存关系型数据的查询结果,减少数据库自身被访问的次数,以提高动态web应用的速度,提高网站架构的并发能力和可扩展性。
Memcached服务的允许原理是在事先规划好的系统内存空间中临时缓存数据库中的各类数据,以达到减少前端业务服务对数据库的直接高并发访问,从而达到提升大规模网站集群中动态服务的并发访问能力。
常见内存缓存服务软件相关对比
软件 | 类型 | 主要作用 | 缓存的数据 |
---|---|---|---|
Memcached | 纯内存 | 用于缓存网站后端的各类数据,例如数据库中的数据。 | 主要缓存用户重复请求的动态内容,例如:blog的博文,bbs的帖子以及用户session会话信息 |
Redis | 可持久化存储,既使用内存,也使用磁盘存储 | 1. 缓存后端数据的查询数据。2. 作为关系型数据库的补充 | 1. 作为缓存:主要缓存用户重复请求的动态内容,例如:blog的博文,bbs的帖子等内容。2. 作为数据库的补充:好友关注,粉丝统计,业务统计等功能可以用持久化存储 |
Suquid,nginx | 内存或内存加磁盘缓存 | 主要用于缓存web前端的服务内容 | 主要用于静态数据缓存,例如:图片,附件(压缩包),js,css,html等,此部分功能大多数企业会选择专业的CDN公司如:网宿,蓝汛等。 |
memcached在企业中的应用场景
作为数据的查询缓存
1.完整数据缓存
例如:电商的商品分类功能不会经常变动,就可以事先放到memcached里,然后再对外提供数据访问。这个过程被称之为"数据预热"。此时只需读取缓存无需读取数据库就能读到memcached缓存的所有商品分类,数据库的缓存压力就会大大降低。
如果把商品分类数据做成静态化文件,然后通过前端web缓存或使用CDN加速效果更好。
2.热点数据缓存
热点数据缓存一般是用于由用户更新的商品,例如淘宝的卖家,当卖家新增商品后,网站程序就会把商品写入后端数据库。同时把这部分数据,放入到memcached内存中,下一次访问这个商品就直接从memcached内存中取走了。
特别提示:这个过程可以通过程序实现,也可以在数据库上安装相关软件进行设置。直接由数据库把内容更新到memcached中,相当于memcached是MySQL的从库一样。
作为集群节点的session会话共享存储
即把客户端用户请求多个前端应用服务器产生的session会话信息,同一存储到一个memcached缓存中。
由于session会话数据是存储在内存中的,所以很快。
memcached特点及工作机制
Memcached作为高并发,高性能的缓存服务具有如下特点
-
协议简单:memcached的协议实现简单,采用基于文本行的协议,能通过
telnet
、nc
等命令直接操作memcached服务存取数据。 -
支持epoll/kqueue异步I/O模型,使用libevent作为事件处理通知机制。
-
Key/value键值数据类型,被缓存的数据以key/value键值形式存在的,例如:
xxx -> 36
, key=xxx, value=36 -
全内存缓存,效率高:memcahced管理内存的方式非常高效,即全部的数据都存放于memcached服务实现分配好的内存中,无持久化存储的设计,和系统的物理内存一样,当重启系统或memcached服务时,memcached内存中的数据就会丢失。如果希望重启后数据依然能保留,那么就可以采用redis这样的持久性内存缓存系统,当内存中缓存的数据容量达到服务启动时设定的内存值时,就自动使用LRU算法删除过期的缓存数据。也可以在存放数据时对存储的数据设置过期实践,这个过期后数据就自动被清除,memcached服务本身不会监控数据过期,而是访问的时候查看key的实践戳判断是否过期。
可支持分布式集群:memcached没有像MySQL那样的主从复制方式,分布式memcached集群的不同服务之间时不通讯的,每一个节点都是独立存取数据,并且数据内容也应该是不一样的,通过对web应用端的程序设计或者通过支持hash算法的负载均衡软件,可以让memcached支持大规模海量分布式缓存集群应用。
Memcached服务安装及配置
编译安装memcached服务器
# yum install libevent libevent-devel -y
# wget memcached.org/files/memcached-1.5.12.tar.gz
# tar zxf memcached-1.5.12.tar.gz
# cd memcached-1.5.12
# ./configure --prefix=/usr/local/memcached
# make && make install
# 启动
# /usr/local/memcached/bin/memcached -p 11211 -u root -m 64
yum安装libevent及连接memcached工具nc
系统安装环境
[root@memcached ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
[root@memcached ~]# uname -r
3.10.0-862.el7.x86_64
[root@memcached ~]# uname -m
x86_64
查看依赖包安装包是否安装:
[root@memcached ~]# rpm -qa libevent libevent-devel nc telnet
安装依赖包libevent:
[root@memcached ~]# yum -y install libevent libevent-devel nc telnet
安装memcached:
[root@memcached ~]# yum install memcached -y
启动memcached:
[root@memcached ~]# memcached -m 16m -p 11211 -d -u root -c 8192
查看memcached启动状态:
[root@memcached ~]# lsof -i:11211
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
memcached 1948 root 26u IPv4 27888 0t0 TCP *:memcache (LISTEN)
memcached 1948 root 27u IPv6 27889 0t0 TCP *:memcache (LISTEN)
memcached 1948 root 28u IPv4 27892 0t0 UDP *:memcache
memcached 1948 root 29u IPv6 27893 0t0 UDP *:memcache
也可启动多实例:
[root@memcached ~]# memcached -m 16m -p 11212 -d -u root -c 8192
[root@memcached ~]# lsof -i:11212
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
memcached 1993 root 26u IPv4 28729 0t0 TCP *:11212 (LISTEN)
memcached 1993 root 27u IPv6 28730 0t0 TCP *:11212 (LISTEN)
memcached 1993 root 28u IPv4 28733 0t0 UDP *:11212
memcached 1993 root 29u IPv6 28734 0t0 UDP *:11212
加入开机自启动:
[root@memcached ~]# vim /etc/rc.local
/usr/bin/memcached -m 16m -p 11211 -d -u root -c 8192
/usr/bin/memcached -m 16m -p 11212 -d -u root -c 8192
Memcached参数
安装php的memcached扩展
官网:http://pecl.php.net/package/memcached
[root@Nginx memcache-2.2.7]# wget http://pecl.php.net/get/memcache-2.2.7.tgz
[root@Nginx memcache-2.2.7]# tar zxf memcache-2.2.7.tgz
[root@Nginx memcache-2.2.7]# cd memcache-2.2.7
[root@Nginx memcache-2.2.7]# /application/php/bin/phpize
[root@Nginx memcache-2.2.7]# ./configure --enable-memcache --with-php-config=/application/php/bin/php-config
[root@Nginx memcache-2.2.7]# make
[root@Nginx memcache-2.2.7]# make install
[root@Nginx memcache-2.2.7]# ls /application/php5.5.32/lib/php/extensions/no-debug-non-zts-20121212/
memcache.so #表示成功
编辑php配置文件
[root@Nginx memcache-2.2.7]# vim /application/php/lib/php.ini
#行尾追加两行
extension_dir = "/application/php5.5.32/lib/php/extensions/no-debug-non-zts-20121212/"
extension=memcache.so
重启php
[root@Nginx memcache-2.2.7]# pkill php-fpm
[root@Nginx memcache-2.2.7]# /application/php/sbin/php-fpm
测试脚本
[root@Nginx html]# vim /usr/local/nginx/html/check_memcached.php
<?php
$memcache = new Memcache;
$memcache->connect('127.0.0.1',11211) or die ("Could not connetc Mcserver");
$memcache->set('key','value');
$get= $memcache->get('key');
echo $get;
?>
memcached数据库操作与管理
参考文档:https://my.oschina.net/AnnaWu/blog/1549193
操作命令格式:
<command name> <key> <flags> <exptime> <bytes> <data block>
MySQL数据库管理 | Memcached管理 |
---|---|
MySQL的insert语句 | Memcached的set/add命令 |
MySQL的select语句 | Memcached的get命令 |
MySQL的delete语句 | Memcached的delete命令 |
MySQL的update语句 | Memcached的replace |
其中set后跟需要更新的键值名、标记位、过期时间、字节数。如果键值名不存在,set相当于add。
[root@memcached ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
set user01 0 0 7
zhangsan
STORED
get user01 0 7
VALUE user01 0 7
zhangsan
END
delete user01
DELETED
get user01
END
quit
Connection closed by foreign host.
其中user01 0 0 7
表示键值名为user01,标记位表示自定义信息为0,过期时间为0(0:永不过期,单位为秒),字节数为7。zhangsan为键值,注意输入长度为7字节,与设定值相符合。quit表示退出
通过printf配合nc向memcached中写入数据
[root@memcached ~]# printf "set key1 0 0 6\r\nonono\r\n"|nc 127.0.0.1 11211
STORED
通过printf配合nc从memcached中读取数据
[root@memcached ~]# printf "get key1\r\n" | nc 127.0.0.1 11211
VALUE key1 0 6
nonono
END
通过printf配合nc从memcached中读删除数据
[root@memcached ~]# printf "delete key1\r\n" | nc 127.0.0.1 11211
DELETED
通过printf配合nc从memcached中替换数据
[root@memcached ~]# printf "replace key1 0 0 6\r\yesyesyes\r\n" | nc 127.0.0.1 11211
STORED
[root@memcached ~]# printf "get key1\r\n" | nc 127.0.0.1 11211
VALUE key1 0 6
yesyesyes
END
关闭memcached
如果是单实例的话,直接kill
掉,如果是多实例的话,启动的时候加入-P
指定pid文件,关闭时,关闭对应的pid文件内容。
[root@memcached ~]# memcached -m 64m -p11211 -d -u root -c 8192 -P /var/run/11211.pid
[root@memcached ~]# memcached -m 64m -p11212 -d -u root -c 8192 -P /var/run/11212.pid
[root@memcached ~]# kill `cat /var/run/11211.pid`
企业工作中如何配置memcached
在企业实际工作中,一般是开发提出需求,说要部署一个memcached数据缓存。运维人员接到这个不确定的需求,需要深入和开发人员沟通,进而确定内存要指定多大,或者和开发人员商量根据具体业务有多少数据指定内存缓存的大小。还要确定业务的重要性,进而决定是否采取负载均衡,分布式集群架构,最后确定使用多大的并发连接数等。
对于运维人员,部署memcached一般就是安装memcached服务端,把服务器动起来,做好监控,配好开机自启动,基本就ok了,客户端php程序环境一般在安装LNMP环境时都会提前安装memcached客户端插件。JAVA程序开发人员会用第三方的JAR包直接连接memcached服务。
memcached预热理念及集群节点正确重启方法
Memcached预热理念
当需要大面积重启memcache时,首先要在前端控制网站入口访问流量,然后重启memcached集群并进行数据预热,所有数据都预热完毕后,在逐步的放开前端网站入口的流量。
为了满足memcached服务数据可以持久化存储的需求,较早期,sina网基于memcached服务开发了一款nosql软件,memcacheDB,实现了在缓存的基础上增加了持久存储的特性,不过目前逐步被更优秀的redis软件取代了。
如何正确开启网站集群服务器?
如果由于机房断电或者搬迁服务器集群到新机房,那么启动集群服务器时,一定要从网站集群的后端一次往前端开启,特别是开启memcached缓存服务后要提前预热。
memcached内存管理机制原理讲解
Slab: 动态创建实际内存区,即分配给slab的内存空间,默认1MB。分配给slab之后根据的大小切分成chunk。Slab默认大小1048576byte,大于1MB的数据会忽略。
Chunk: 数据区块,固定大小,chunk初始化字节48字节。
SLAB内存管理机制的特点
-
提前分配大内存slab 1MB,在进行小对象填充chunk。
-
避免大量重复的初始化和清理,减轻内存管理器负担。
-
避免频繁malloc/free内存分配导致的碎片。
Memcache内存管理机制小节:
-
mc的早期内存管理机制为malloc(动态内存分配)。
-
malloc(动态内存分配)产生内存碎片,导致操作系统性能急剧下降。
-
slab内存分配机制产生了,就可以解决内存问题。
-
Memcached服务的内存预先分割成特定长度的内存块,成为chunk,用于缓存数据的内存空间或内存块,相当于磁盘block,只不过磁盘的每一个block都是相等的,而chunk只有同一个slab class才是相等的。
-
Slab class:特定大小(1M)的包含多个chunk的集合或组,一个memcached包含多个slab class,每个slab class包含多个相同大小的chunk
-
Slab机制也有缺点,例如,chunk的空间会浪费(通过调优因子以及大小接近的数据放入一个MC实例)
Memcached slab allocator内存管理机制缺点
Chunk存储Item浪费空间。
Slab allocatot解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题,这个问题就是由于分配的是特定长度内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了
避免浪费内存的办法是预先计算出应用存入的数据大小,或把同一业务类型的数据存入一个memcached服务器中,确保存入的数据大小相对均匀,这样就可以减少内存的浪费。
Slab尾部空间
解决办法:规划slab大小=chunk大小*
n整数倍。
使用growth Factor对slab allocator内存管理机制调优
在启动memcached时指定growth Factor因子(通过-f选项),就可以在某种程度控制每组slab之间的差异,默认值为1.25,但是在该选项出现之前这个因子曾经固定为2,称为 powers of 2策略。
Memcachedl删除机制总结
-
不主动检测item对象是否过期,而是在get时才会检查item对象是否过期以及是否应该删除。
-
当删除item对象时,一般不释放内存空间,而是做标记删除,将指针放入slot回收插槽,下次分配的时候直接使用。
-
当内存空间满的时候,才会根据LRU算法把最近最少使用的item对象删除。
-
数据存入可以设定过期时间,但是数据过期后不会被立即删除,而是在get时才会检查item对象是否过期以及是否应该删除。
-
如果不希望使用使用LRU算法清除数据,可以使用-M参数。
Memcached懒惰删除对象机制
当删除item对象时,一般不释放内存空间,而是做标记删除,将之间让如slot回收插槽,下次分配的时候直接使用。
Memcached在分配空间时,会优先使用以及过期的key/value对空间,当分配的内存空间占满时,memcached就会使用LRU算法来分配空间,删除最近最少使用的key/value对,将其空间分配给新的key/value对,在某些情况下(完整缓存),如果不想使用LRU算法,那么可以通过-M
参数来启动memcached,这样,memcached在内存耗尽时,会返还一个报错信息。-M return error on memory exhausted(rather than removing items)
memcached应用管理
通过命令管理memcached
参考:https://www.runoob.com/memcached/memcached-stats.html
运维人员一般可通过在命令行执行telnet ip port
方式登陆到memcached,然后执行一些管理的命令,除了telnet外,nc命令也是一个不错的管理memcached服务命令!有关
stats #这里显示了很多状态信息,下边详细解释每个状态项:
-
pid: memcache服务器进程ID
-
uptime:服务器已运行秒数
-
time:服务器当前Unix时间戳
-
version:memcache版本
-
pointer_size:操作系统指针大小
-
rusage_user:进程累计用户时间
-
rusage_system:进程累计系统时间
-
curr_connections:当前连接数量
-
total_connections:Memcached运行以来连接总数
-
connection_structures:Memcached分配的连接结构数量
-
cmd_get:get命令请求次数
-
cmd_set:set命令请求次数
-
cmd_flush:flush命令请求次数
-
get_hits:get命令命中次数
-
get_misses:get命令未命中次数
-
delete_misses:delete命令未命中次数
-
delete_hits:delete命令命中次数
-
incr_misses:incr命令未命中次数
-
incr_hits:incr命令命中次数
-
decr_misses:decr命令未命中次数
-
decr_hits:decr命令命中次数
-
cas_misses:cas命令未命中次数
-
cas_hits:cas命令命中次数
-
cas_badval:使用擦拭次数
-
auth_cmds:认证命令处理的次数
-
auth_errors:认证失败数目
-
bytes_read:读取总字节数
-
bytes_written:发送总字节数
-
limit_maxbytes:分配的内存总大小(字节)
-
accepting_conns:服务器是否达到过最大连接(0/1)
-
listen_disabled_num:失效的监听数
-
threads:当前线程数
-
conn_yields:连接操作主动放弃数目
-
bytes:当前存储占用的字节数
-
curr_items:当前存储的数据总数
-
total_items:启动以来存储的数据总数
-
evictions:LRU释放的对象数目
-
reclaimed:已过期的数据条目来存储新数据的数目
stats settings
参考:https://www.runoob.com/memcached/memcached-clear-data.html
flush_all
命令用于清理缓存中的所有 key=>value(键=>值)
对
memcahced服务应用优化案例
某公司实际案例:用户访问网站打开页面很慢,经运维人员排查后发现MySQL数据库负载很高,load值大概20-30,如下:
[root@memcached ~]# uptime
01:56:29 up 8:52, 2 users, load average: 20, 15, 10
登陆数据库后,使用show full processlist
查看或者在Linux命令行使用下面命令查看
mysql -uroot -p -S /data/3307/mysql.sock -e "show full processlist" |grep vi sleep
发现数据库中像like "%张三%"
这样的SQL语句特别多,导致数据库负载很好,我们知道像like "%张三%"
这样的SQL语句对于MySQL数据库来说,利用索引没有太大的优化余地。
打开该公司的网站首页查看,发现首页有一个搜索框,根据前面查看的SQL语句形式,可以推测上述like "%张三%"
应该是搜索框的语句带来的结果,这时候经过这个公司的数据库维护人员得到了正式,请问是你,你该如何优化解决当前的问题呢?
解决思路:
-
看是否可以从业务上进行整改,让用户登陆后才能进行搜索,通过这种改进来减少搜索的次数,达到减轻数据库服务的压力的目的。
-
如果有大量频繁的搜索SQL语句,很有可能是有网络爬虫在爬我们的网站,可以通过分析WEB日志或网络连接状态,封掉这样非正常的搜索请求。
-
为主库配置多个从库,然后实现读写分离,让
like '%张三%'
这样的查询语句区多个从库查,从而减轻主库的读写压力。 -
在数据库前端加memcached缓存服务器(这个效果在所有方法里是最好的)
-
在数据库里使用
like '%张三%'
实现搜索,并非民智的选择,可以通过Shpinx
等搜索服务实现用户搜索。
这个案例最终问题是,网站前端有爬虫爬站,通过分析web日志获取到爬站的ip,临时封掉后,Mysql数据负载立刻下降了很多,网站服务恢复正常。
系统性能监视的高级命令
-
内存:top free vmstat mpstat iostat sar
-
CPU:top vmstat mpstat iostat sar
-
I/O : vmstat mpstat iostat sar
-
进程:ipcs ipcrm isof starce lstrace
-
负载:uptime
memcached服务优化策略
Memcached服务安装配置简单,几乎不需要优化就可以跑得很好,在特殊的大并发高访问量的场合才需要进行一些优化。
提高memcached访问命中率
优化最关键的指标,例如每次新增数据到数据库的同时就将数据写入或者复制到memcached里一份,然后从业务逻辑上让程序优先读缓存,没有数据在查数据库。
提高内存利用率,减少内存浪费。
1. 减少chunk内存空间浪费,调优方法为根据业务数据的大小利用-n参数设定chunk的初始值,及通过-f
参数factor增长因子设置chunk的大小尽可能解决业务数据的大小。
2. 减少slab的浪费,设定slab的大小为chunk整倍数。
3. 采用一致性哈希分布式缓存集群架构,当网站后端的数据库数据量很大时,单台memcached就无法存放绝大部分的数据库内数据,导致memcached服务很低,此时可以采用一致性哈希分布式缓存集群架构,提升网站的命中率,一致性哈希可以有程序实现或者支持一致性哈希算法的负载均衡器实现。
利用memcached做集群的session共享
vim /application/php/lib/php.ini
session.save_path = "tcp://10.0.0.130:11211" #将此行注释打开,ip为memcached服务器ip
session.save_handler = memcache #files被修改为memcache
最后重启php
免责声明: 本文部分内容转自网络文章,转载此文章仅为个人收藏,分享知识,如有侵权,请联系博主进行删除。