memcache是一套分布式的高速缓存系统,由LiveJournal的Brad Fitzpatrick开发,但目前被许多网站使用以提升网站的访问速度,尤其对于一些大型的、需要频繁访问数据库的网站访问速度提升效果十分显著
MemCache的工作流程如下:
-
先检查客户端的请求数据是否在memcached中,如有,直接把请求数据返回,不再对数据库进行任何操作;如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中(memcached客户端不负责,需要程序明确实现);每次更新数据库的同时更新memcached中的数据,保证一致性;当分配给memcached内存空间用完之后,会使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据。
-
Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。
-
Memcache是danga的一个项目,最早是LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。
-
Memcached是以守护程序(监听)方式运行于一个或多个服务器中,随时会接收客户端的连接和操作。
-
memcached是一种无阻塞的socket通信方式服务,基于libevent库,由于无阻塞通信,对内存读写速度非常之快。
- memcached分服务器端和客户端,可以配置多个服务器端和客户端,应用于分布式的服务非常广泛。
- memcached作为小规模的数据分布式平台是十分有效果的。 -
memcached是键值一一对应,key默认最大不能超过128个字 节,value默认大小是1M,也就是一个slabs,如果要存2M的值(连续的),不能用两个slabs,因为两个slabs不是连续的,无法在内存中 存储,故需要修改slabs的大小,多个key和value进行存储时,即使这个slabs没有利用完,那么也不会存放别的数据。
-
memcached已经可以支持C/C++、Perl、PHP、Python、Ruby、Java、C#、Postgres、Chicken Scheme、Lua、MySQL和Protocol等语言客户端。
应用
- 使用Memcache的网站一般流量都是比较大的,为了缓解数据库的压力,让Memcache作为一个缓存区域,把部分信息保存在内存中,在前端能够迅速的进行存取。那么一般的焦点就是集中在如何分担数据库压力和进行分布式,毕竟单台Memcache的内存容量的有限的。
- [分布式应用]
Memcache本来支持分布式,我们客户端稍加改造,更好的支持。我们的key可以适当进行有规律的封装,比如以user为主的网站来说,每个用户都有UserID,那么可以按照固定的ID来进行提取和存取,比如1开头的用户保存在第一台Memcache服务器上,以2开头的用户的数据保存在第二台Memcache服务器上,存取数据都先按照User ID来进行相应的转换和存取。
但是这个有缺点,就是需要对User ID进行判断,如果业务不一致,或者其他类型的应用,可能不是那么合适,那么可以根据自己的实际业务来进行考虑,或者去想更合适的方法。
-[ 减少数据库压力]
这个算是比较重要的,所有的数据基本上都是保存在数据库当中的,每次频繁的存取数据库,导致数据库性能急剧下降,无法同时服务更多的用户,比如MySQL,特别频繁的锁表,那么让Memcache来分担数据库的压力吧。我们需要一种改动比较小,并且能够不会大规模改变前端的方式来进行改变目前的架构。
一个用PHP编写的可视化的MemCached管理系统
MemAdmin是一款可视化的Memcached管理与监控工具,使用PHP开发,体积小,操作简单。 - 主要功能:
服务器参数监控:STATS、SETTINGS、ITEMS、SLABS、SIZES实时刷新;
服务器性能监控:GET、DELETE、INCR、DECR、CAS等常用操作命中率实时监控;
支持数据遍历,方便对存储内容进行监视;
支持条件查询,筛选出满足条件的KEY或VALUE;
数组、JSON等序列化字符反序列显示;
兼容memcache协议的其他服务,如Tokyo Tyrant (遍历功能除外);
支持服务器连接池,多服务器管理切换方便简洁。
####php增加memcache 模块####
在编译php中增加memcache模块,当客户访问的资源需要使用php对其进行解析的时候:php先检查客户端的请求数据是否在memcached中,如有,直接把请求数据返回,不再进行解析处理;如果请求的数据不在memcached中,就去解析请求数据,把解析的结果数据返回给客户端,同时把数据缓存一份到memcached中,下次再有相同的请求时候,直接从memcached中直接返回请求结果。
没有缓存的流程:
每一次的客户请求:客户---->web(nginx)---->php---->解析出结果---->nginx---->客户
当访问同一个页面的时候,也是上述流程重复多次,每一次都要进行解析。浪费资源
添加memcache:在php配置文件中添加mencache模块。
当对特定的页面(特定指的是,该页面中必须说明让php将自己的解析结果存放在缓存中)进行重复请求的时候,只有第一次需要php对请求页面进行解析,因为在第一次解析的时候,会将该页面的解析结果存放在memcache缓存中,下次有同样的请求过来的时候,php直接从缓存中调取结果,返回给前端页面。
第一次访问一个资源:客户---->web(nginx)---->php---->解析出结果---->nginx---->客户
再次访问一个资源:客户---->web(nginx)---->php---->缓存中直接调取---->nginx---->客户
环境配置:
memcache目录中本来没有configure文件,所以没法编译。phpize是用来扩展php扩展模块的,通过phpize可以建立php的外挂模块,比如你想在原来编译好的php中加入memcached或者ImageMagick等扩展模块,可以使用phpize。或者说,phpize的作用可以这样理解:侦测环境(phpize工具是在php安装目录下,基于这点phpize对应了当时的php环境,所以是要根据该php的配置情况生成对应的configure文件),建立一个configure文件。必须在一个目录下去运行phpize。那么phpize就知道你的的环境是哪个目录,并且configure文件建立在该目录下,会生成configure文件
[root@server1 ~]# vim ~/.bash_profile
PATH=$PATH:$HOME/bin:/usr/local/lnmp/mysql/bin:/usr/local/lnmp/php/bin
[root@server1 ~]# source ~/.bash_profile
[root@server1 lnmp]# tar zxf memcache-2.2.5.tgz
[root@server1 lnmp]# cd memcache-2.2.5
[root@server1 memcache-2.2.5]# phpize
Configuring for:
PHP Api Version: 20131106
Zend Module Api No: 20131226
Zend Extension Api No: 220131226
Cannot find autoconf. Please check your autoconf installation and the
$PHP_AUTOCONF environment variable. Then, rerun this script.
[root@server1 memcache-2.2.5]# yum install -y autoconf
[root@server1 memcache-2.2.5]# ./configure
[root@server1 memcache-2.2.5]# make && make install
修改php主配置文件,增加memcache模块
[root@server1 memcache-2.2.5]# vim /usr/local/lnmp/php/etc/php.ini
873 extension=memcache.so
[root@server1 memcache-2.2.5]# /etc/init.d/php-fpm reload ## 重新加载php
Reload service php-fpm done
[root@server1 memcache-2.2.5]# php -m | grep memcache # 可以查看是否加载成功
memcache
[root@server1 memcache-2.2.5]# php -m | grep mysql
mysql
mysqli
mysqlnd
pdo_mysql
安装memcached查看memcached的配置文件
[root@server1 memcache-2.2.5]#yum install -y memcached ##安装memcached
[root@server1 memcache-2.2.5]# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="" (如果写为OPTIONS="-l 127.0.0.1" 即为只监听本机的11211端口)
[root@server1 memcache-2.2.5]# systemctl start memcached #启动memcached
telnet测试
[root@server1 memcache-2.2.5]# yum install -y telnet
[root@server1 memcache-2.2.5]# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
set name 0 0 6
westos
STORED
get name
VALUE name 0 6
westos
END
stats(查看状态)
set name 0 0 6 (0编号 0缓存时间(此处0代表不限制时间) 6限制字符数) key:name;编号:0;缓存时间:0(永久)valuce值:6位
westosawd
CLIENT_ERROR bad data chunk
ERROR
westos
STORED
get name
VALUE name 0 6
westos
END
delete name
DELETED
set name 0 5 6 ##设置缓存5s,过5s再获取name,为空
westos
STORED
get name
END
quit #退出
拷贝php页面到nginx默认发布目录
memcache.php监控页面;example.php测memcache命中率
[root@server1 memcache-2.2.5]# cp memcache.php example.php /usr/local/lnmp/nginx/html/
[root@server1 memcache-2.2.5]# cd /usr/local/lnmp/nginx/html/
[root@server1 html]# vim memcache.php
define('ADMIN_USERNAME','memcache'); ## Admin Username(自定义)
define('ADMIN_PASSWORD','westos'); ## Admin Password(自定义)
$MEMCACHE_SERVERS[] = '172.25.46.1:11211'; // add more as an array
#$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array
只留一个主机,memcache没有转发或负载均衡机制,只能一个一个添加(因为本实验只有一个主机,其实可以添加多个)
测试:
访问http://172.25.46.1/memcache.php
输入用户名密码,可以查看memcache命中率,使用http://172.25.46.1/example.php不停刷新来测试
在物理机上分别对两个页面进行压测
[root@foundation46 ~]# ab -c 10 -n 5000 http://172.25.46.1/index.php #很慢,因为没有缓存,而且failed比较多 10个并发,5000个请求
[root@foundation46 ~]# ab -c 10 -n 5000 http://172.25.46.1/example.php#很快,因为访问缓存,而且没有failed的观察时间和命中率
可以看出添加了memcache的网络页面压力测试下所需时间较短,原始页面所需时间较长,由于其没有缓存。并且缓存命中率较高。
#####nginx增加memcache模块(缓存前移)######
OpenResty:
OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web平台,由中国人章亦春发起,提供了很多高质量的第三方模块。
OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。360,UPYUN,阿里云,新浪,腾讯网,去哪儿网,酷狗音乐等都是 OpenResty 的深度用户。OpenResty 的目标是让你的 Web 服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL,PostgreSQL,~Memcaches 以及 ~Redis 等都进行一致的高性能响应。
所以对于一些高性能的服务来说,可以直接使用 OpenResty 访问 Mysql或Redis等,而不需要通过第三方语言(PHP、Python、Ruby)等来访问数据库再返回,这大大提高了应用的性能。参考openresty中文官网 http://openresty.org/cn/
原nginx不支持memcache
缓存前移:将memcache模块加载在nginxweb服务器,客户请求过来的时候,nginx先从memcached中寻找数据,如果由直接返回数据给客户;如果没有的话,在去都端进行请求调取数据,在将该数据返回给客户的时候,保存一份在memcached中,下次处理相同的请求的时候,会直接从memcache中调取数据。
2 、编译安装OpenResty
下载OpenResty源码包进行解压编译安装,可以从官网进行下载。
1)给nginx添加memc和sr cache模块,让nginx直接访问memcache来提高速度
先关闭原来的nginx,因为下面安装的openresty-1.13.6.1.tar.gz也是nginx
[root@server1 nginx]# nginx -s stop
源码编译安装openresty-1.13.6.1.tar.gz(不需要加参数,使用默认)
[root@server1 lnmp]# tar zxf openresty-1.13.6.1.tar.gz
[root@server1 lnmp]# cd openresty-1.13.6.1
[root@server1 openresty-1.13.6.1]# ./configure --prefix=/usr/local/openresty
[root@server1 openresty-1.13.6.1]# gmake && gmake install
拷贝之前example.php和index.php到默认发布目录/usr/local/openresty/nginx/html
准备测试
[root@server1 openresty-1.13.6.1]# cd /usr/local/openresty/nginx/html
[root@server1 html]# cp /usr/local/lnmp/nginx/html/index.php .
[root@server1 html]# cp /usr/local/lnmp/nginx/html/example.php .
修改nginx配置文件:vim /usr/local/openresty/nginx/conf/nginx.conf
17 http {
18 include mime.types;
19 default_type application/octet-stream;
20 upstream memcache { ##添加20-23行内容
21 server localhost:11211;
22 keepalive 512;
23 }
68 location /memc {
69 internal; # 只接收内部访问,不接受外部http访问。比较安全
70 memc_connect_timeout 100ms;
71 memc_send_timeout 100ms; ##后端服务器数据回传时间
72 memc_read_timeout 100ms; ##连接成功后,后端服务器响应时间
73 set $memc_key $query_string;
74 set $memc_exptime 300;
75 memc_pass memcache;
76 }
78 location ~ \.php$ {
79 set $key $uri$args;
##http的GET方法表示get、PUT方法表示set
80 srcache_fetch GET /memc $key;(这两个配置的作用是:请求php页面时,先会去memcache中找,如果没有,正常访问;
81 srcache_store PUT /memc $key; 访问结束后将结果存到memcache,下次访问时直接从缓存中)
82 root html;
83 fastcgi_pass 127.0.0.1:9000;
84 fastcgi_index index.php;
85 #fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
86 include fastcgi.conf;
87
[root@server1 conf]# /usr/local/openresty/nginx/sbin/nginx ##重启nginx
测试:
[root@foundation46 ~]# ab -c 10 -n 5000 http://172.25.46.1/example.php
[root@foundation46 ~]# ab -c 10 -n 5000 http://172.25.46.1/index.php