您现在的位置是:首页 > 文章详情

图文并茂超详细搭建memcache缓存服务器(nginx+php+memcache+mysql)

日期:2017-05-15点击:427

博主QQ819594300

博客地址:http://zpf666.blog.51cto.com/

有什么疑问的朋友可以联系博主,博主会帮你们解答,谢谢支持


一、MemCache简述

session

MemCache是一个自由、源码开放、高性能、分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高了网站访问的速度。 MemCaChe是一个存储键值对的HashMap,在内存中对任意的数据(比如字符串、对象等)所使用的key-value存储,数据可以来自数据库调用、API调用,或者页面渲染的结果。MemCache设计理念就是小而强大,它简单的设计促进了快速部署、易于开发并解决面对大规模的数据缓存的许多难题,而所开放的API使得MemCache能用于Java、C/C++/C#、Perl、Python、PHP、Ruby等大部分流行的程序语言。

另外,说一下为什么会有Memcache和memcached两种名称?其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名

MemCache的官方网站为http://memcached.org/

MemCache访问模型

为了加深对memcache的理解,以memcache为代表的分布式缓存,访问模型如下:

wKioL1kZCmiD8nysAAKDWwegddo172.jpg

特别澄清一个问题,MemCache虽然被称为”分布式缓存”,但是MemCache本身完全不具备分布式的功能,MemCache集群之间不会相互通信(与之形成对比的,比如JBoss Cache,某台服务器有缓存数据更新时,会通知集群中其他机器更新缓存或清除缓存数据),所谓的”分布式”,完全依赖于客户端程序的实现,就像上面这张图的流程一样。

同时基于这张图,理一下MemCache一次写缓存的流程:

1、应用程序输入需要写缓存的数据

2、API将Key输入路由算法模块,路由算法根据Key和MemCache集群服务器列表得到一台服务器编号

3、由服务器编号得到MemCache及其的ip地址和端口号

4、API调用通信模块和指定编号的服务器通信,将数据写入该服务器,完成一次分布式缓存的写操作

读缓存和写缓存一样,只要使用相同的路由算法和服务器列表,只要应用程序查询的是相同的Key,MemCache客户端总是访问相同的客户端去读取数据,只要服务器中还缓存着该数据,就能保证缓存命中。

这种MemCache集群的方式也是从分区容错性的方面考虑的,假如Node2宕机了,那么Node2上面存储的数据都不可用了,此时由于集群中Node0和Node1还存在,下一次请求Node2中存储的Key值的时候,肯定是没有命中的,这时先从数据库中拿到要缓存的数据,然后路由算法模块根据Key值在Node0和Node1中选取一个节点,把对应的数据放进去,这样下一次就又可以走缓存了,这种集群的做法很好,但是缺点是成本比较大。

一致性Hash算法

从上面的图中,可以看出一个很重要的问题,就是对服务器集群的管理,路由算法至关重要,就和负载均衡算法一样,路由算法决定着究竟该访问集群中的哪台服务器,先看一个简单的路由算法。

1、余数Hash

简单的路由算法可以使用余数Hash:用服务器数目和缓存数据KEY的hash值相除,余数为服务器列表下标编号,假如某个str对应的HashCode是52、服务器的数目是3,取余数得到1,str对应节点Node1,所以路由算法把str路由到Node1服务器上。由于HashCode随机性比较强,所以使用余数Hash路由算法就可以保证缓存数据在整个MemCache服务器集群中有比较均衡的分布。

如果不考虑服务器集群的伸缩性,那么余数Hash算法几乎可以满足绝大多数的缓存路由需求,但是当分布式缓存集群需要扩容的时候,就难办了。

就假设MemCache服务器集群由3台变为4台吧,更改服务器列表,仍然使用余数Hash,52对4的余数是0,对应Node0,但是str原来是存在Node1上的,这就导致了缓存没有命中。再举个例子,原来有HashCode为0~19的20个数据,那么:

那么不妨举个例子,原来有HashCode为0~19的20个数据,那么:

wKiom1kZCmjTqWCdAACxFjWQAJc761.jpg

现在扩容到4台,加粗标红的表示命中:

wKioL1kZCmny6EkJAADAZyEXYGk836.jpg

如果扩容到20+的台数,只有前三个HashCode对应的Key是命中的,也就是15%。当然现实情况肯定比这个复杂得多,不过足以说明,使用余数Hash的路由算法,在扩容的时候会造成大量的数据无法正确命中(其实不仅仅是无法命中,那些大量的无法命中的数据还在原缓存中在被移除前占据着内存)。在网站业务中,大部分的业务数据度操作请求上事实上是通过缓存获取的,只有少量读操作会访问数据库,因此数据库的负载能力是以有缓存为前提而设计的。当大部分被缓存了的数据因为服务器扩容而不能正确读取时,这些数据访问的压力就落在了数据库的身上,这将大大超过数据库的负载能力,严重的可能会导致数据库宕机。

这个问题有解决方案,解决步骤为:

(1)在网站访问量低谷,通常是深夜,技术团队加班,扩容、重启服务器

(2)通过模拟请求的方式逐渐预热缓存,使缓存服务器中的数据重新分布

2、一致性Hash算法

一致性Hash算法通过一个叫做一致性Hash环的数据结构实现Key到缓存服务器的Hash映射。简单地说,一致性哈希将整个哈希值空间组织成一个虚拟的圆环(这个环被称为一致性Hash环),如假设某空间哈希函数H的值空间是0~2^32-1(即哈希值是一个32位无符号×××),整个哈希空间如下:

wKiom1kZCmmSr1coAABtVvs_ySs582.jpg

下一步将各个服务器使用H进行一个哈希计算,具体可以使用服务器的IP地址或者主机名作为关键字,这样每台机器能确定其在上面的哈希环上的位置了,并且是按照顺时针排列,这里我们假设三台节点memcache经计算后位置如下:

wKioL1kZCmmxRLICAACbdcB-0Q0865.jpg

接下来使用相同算法计算出数据的哈希值h,并由此确定数据在此哈希环上的位置

假如我们有数据A、B、C、D、4个对象,经过哈希计算后位置如下:

wKiom1kZCmrglQV4AACYlJn1LaU708.jpg

根据一致性哈希算法,数据A就被绑定到了server01上,D被绑定到了server02上,B、C在server03上,是按照顺时针找最近服务节点方法

这样得到的哈希环调度方法,有很高的容错性和可扩展性:

假设server03宕机:

wKiom1kZCmrxtnkfAAChWGHTeN8420.jpg

可以看到此时C、B会受到影响,将B、C被重定位到Server01。一般的,在一致性哈希算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

考虑另外一种情况,如果我们在系统中增加一台服务器Memcached Server 04:

wKioL1kZCmujrjsmAACzzHKedEg676.jpg

此时A、D、C不受影响,只有B需要重定位到新的Server04。一般的,在一致性哈希算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

综上所述,一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

一致性哈希的缺点:在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。我们可以采用增加虚拟节点的方式解决。

更重要的是,集群中缓存服务器节点越多,增加/减少节点带来的影响越小,很好理解。换句话说,随着集群规模的增大,继续命中原有缓存数据的概率会越来越大,虽然仍然有小部分数据缓存在服务器中不能被读到,但是这个比例足够小,即使访问数据库,也不会对数据库造成致命的负载压力。

MemCache实现原理

首先要说明一点,MemCache的数据存放在内存中

1、访问数据的速度比传统的关系型数据库要快,因为Oracle、MySQL这些传统的关系型数据库为了保持数据的持久性,数据存放在硬盘中,IO操作速度慢

2、MemCache的数据存放在内存中同时意味着只要MemCache重启了,数据就会消失

3、既然MemCache的数据存放在内存中,那么势必受到机器位数的限制,32位机器最多只能使用2GB的内存空间,64位机器可以认为没有上限

然后我们来看一下MemCache的原理,MemCache最重要的是内存如何分配的,MemCache采用的内存分配方式是固定空间分配,如下图所示:

wKioL1kZCmvBSZasAAGYaCm4DAo414.jpg

这张图片里面涉及了slab_class、slab、page、chunk四个概念,它们之间的关系是:

1、MemCache将内存空间分为一组slab

2、每个slab下又有若干个page,每个page默认是1M,如果一个slab占用100M内存的话,那么这个slab下应该有100个page

3、每个page里面包含一组chunk,chunk是真正存放数据的地方,同一个slab里面的chunk的大小是固定的

4、有相同大小chunk的slab被组织在一起,称为slab_class

MemCache内存分配的方式称为allocator(分配运算),slab的数量是有限的,几个、十几个或者几十个,这个和启动参数的配置相关。

MemCache中的value存放的地方是由value的大小决定的,value总是会被存放到与chunk大小最接近的一个slab中,比如slab[1]的chunk大小为80字节、slab[2]的chunk大小为100字节、slab[3]的chunk大小为125字节(相邻slab内的chunk基本以1.25为比例进行增长,MemCache启动时可以用-f指定这个比例),那么过来一个88字节的value,这个value将被放到2号slab中。放slab的时候,首先slab要申请内存,申请内存是以page为单位的,所以在放入第一个数据的时候,无论大小为多少,都会有1M大小的page被分配给该slab。申请到page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk数组,最后从这个chunk数组中选择一个用于存储数据。

如果这个slab中没有chunk可以分配了怎么办,如果MemCache启动没有追加-M(禁止LRU,这种情况下内存不够会报Out Of Memory错误),那么MemCache会把这个slab中最近最少使用的chunk中的数据清理掉,然后放上最新的数据。

Memcache的工作流程:

wKiom1kZCmzworzSAACrA0MKnf8475.jpg

1、检查客户端的请求数据是否在memcached中,如果有,直接把请求数据返回,不再对数据库进行任何操作,路径操作为①②③⑦。

2、如果请求的数据不在memcached中,就去查数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到memcached中(memcached客户端不负责,需要程序明确实现),路径操作为①②④⑤⑦⑥。

3、每次更新数据库的同时更新memcached中的数据,保证一致性。

4、当分配给memcached内存空间用完之后,会使用LRU(Least Recently Used,最近最少使用)策略加上到期失效策略,失效数据首先被替换,然后再替换掉最近未使用的数据。

Memcached特征:

协议简单:

   它是基于文本行的协议,直接通过telnet在memcached服务器上可进行存取数据操作

注:文本行的协议:指的是信息以文本传送,一个信息单元传递完毕后要传送换行。比如对于HTTP的GET请求来说,GET/index.html HTTP/1.1是一行,接下去每个头部信息各占一行。一个空行表示整个请求结束

基于libevent事件处理:

    Libevent是一套利用C开发的程序库,它将BSD系统的kqueue,Linux系统的epoll等事件处理功能封装成一个接口,与传统的select相比,提高了性能。

内置的内存管理方式:

    所有数据都保存在内存中,存取数据比硬盘快,当内存满后,通过LRU算法自动删除不使用的缓存,但没有考虑数据的容灾问题,重启服务,所有数据会丢失。

分布式

   各个memcached服务器之间互不通信,各自独立存取数据,不共享任何信息。服务器并不具有分布式功能,分布式部署取决于memcache客户端。

Memcache的安装

分为两个过程:memcache服务器端的安装和memcached客户端的安装。

所谓服务器端的安装就是在服务器(一般都是linux系统)上安装Memcache实现数据的存储。

所谓客户端的安装就是指php(或者其他程序,Memcache还有其他不错的api接口提供)去使用服务器端的Memcache提供的数据,需要php添加扩展。

PHP的Memcache

二、centos7.2+nginx+php+memcache+mysql

环境描述:

wKiom1kZCmzxrWG_AAEPbDUo4jE485.jpg

nginx和php:

所需软件:nginx-1.10.2.tar.gz

php-5.6.27.tar.gz

ip地址:192.168.1.8

mysql:

所需软件:mysql-5.7.13.tar.gz

ip地址:192.168.1.9

memcache:

所需软件:memcached-1.4.33.tar.gz

ip地址:192.168.1.10

虚拟机环境如下:

wKiom1kZCmzj_gGjAACEwPrH14w317.jpg

下面开始正式的实验操作:

1)安装nginx

①解压缩zlib

wKioL1kZCm2xHOkgAAENnCfSbf8107.jpg

注意:不需要编译,只需要解压就行。

②解压缩pcre

wKiom1kZCm3SmuQeAAER8L0-qt8789.jpg

注意:不需要编译,只需要解压就行。

③yum安装nginx依赖包

wKioL1kZCm6xiIspAACosMXVtXE651.jpg

④下载安装nginx源码包

下载nginx的源码包:http://nginx.org/download

解压缩、编译及安装nginx源码包:

wKiom1kZCm-i8XruAAJp-v1Z5no448.jpg

图中配置、编译安装部分如下所示:

./configure--prefix=/usr/local/nginx1.10 --with-http_dav_module--with-http_stub_status_module --with-http_addition_module--with-http_sub_module --with-http_flv_module --with-http_mp4_module--with-pcre=/root/pcre-8.39 --with-zlib=/root/zlib-1.2.8 --with-http_ssl_module--with-http_gzip_static_module --user=www --group=www && make&& make install

说明:--with-pcre:用来设置pcre的源码目录。

         --with-zlib:用来设置zlib的源码目录。

         因为编译nginx需要用到这两个库的源码。

⑤做软链接

wKioL1kZCm-C4N7kAACw3t5mTmQ652.jpg

⑥nginx配置文件语法检测

wKiom1kZCnCSzo5kAADY9W3JOGQ400.jpg

⑦启动nginx

wKiom1kZCnCwv4q5AADCZf2xqA8809.jpg

⑧防火墙开启80端口例外

wKioL1kZCnCCvjCNAAEngl9noGU668.jpg

⑨在一台客户机浏览器上浏览nginx网页,测试一下nginx

wKiom1kZCnHRpdFbAAEhEMR50gA395.jpg

2)安装php

①安装libmcrypt

wKioL1kZCnHitEr6AAEBWfkQot0381.jpg

②yum安装php依赖包

wKioL1kZCnKR0peTAACXmGyYR5A532.jpg

③解压缩、编译及安装php源码包

wKiom1kZCnLTZTNtAAJTjgKlb3E936.jpg

图中配置、编译安装部分如下所示:

./configure--prefix=/usr/local/php5.6 --with-mysql=mysqlnd --with-pdo-mysql=mysqlnd--with-mysqli=mysqlnd --with-openssl --enable-fpm --enable-sockets--enable-sysvshm --enable-mbstring --with-freetype-dir --with-jpeg-dir--with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --with-mhash--with-mcrypt=/usr/local/libmcrypt --with-config-file-path=/etc--with-config-file-scan-dir=/etc/php.d --with-bz2 --enable-maintainer-zts&& make && make install

④拷贝php.ini样例文件

wKioL1kZCnSDPdU8AADMBWxYnxc226.jpg

修改/etc/php.ini文件,将short_open_tag修改为on,修改后的内容如下:

wKiom1kZCnTSZh74AAC9TSK1EFg531.jpg

wKioL1kZCnTg63O7AAA5d32Hd0Y539.jpg//支持php短标签

⑤创建php-fpm服务启动脚本并启动服务

wKiom1kZCnWhyhYwAAEX2wN5DSA737.jpg

提供php-fpm配置文件并编辑:

wKioL1kZCnaSR8RvAADmkCHvgWQ814.jpg

wKiom1kZCnbzPT_gAAA_mh4EPI8923.jpg

wKiom1kZCnbBtvTUAABO9f69WzM309.jpg

说明:如果是nginx和php分离部署,这里需要改成php真实的ip,然后php服务器还要开始9000端口例外。除此之外都和本博文一样即可。

wKioL1kZCnfRsG-7AABDWn1BDrM840.jpg

wKiom1kZCq2BgXRvAAA-joxh_Wo041.jpg

wKioL1kZCq3BcrcjAABHa1wvWVE118.jpg

wKiom1kZCq3Rfdp9AABG9gncDLc953.jpg

启动php-fpm服务:

wKioL1kZCq6xxPuNAADqNZtLKF0919.jpg

3)安装mysql

(在192.168.1.9主机上操作)

因为centos7.2默认安装了mariadb-libs,所以先要卸载掉

查看是否安装mariadb

#rpm-qa | grep mariadb

卸载mariadb

rpm-e --nodeps mariadb-libs

wKioL1kZCq7R3ftXAACy9rMRCIo795.jpg

然后具体的mysql安装请参考我的mysql5.7.13的安装,博文地址:

http://zpf666.blog.51cto.com/11248677/1908988

这里我的mysql是安装好的,我们看一下服务是否启动:

wKiom1kZCq_A1NfDAACeYiWsTKg938.jpg

防火墙开启3306端口例外:

wKiom1kZCq_Ae_LcAAEauFteYpg255.jpg

4、安装memcached服务端

(在192.168.1.10主机操作)

memcached是基于libevent的事件处理。libevent是个程序库,它将Linux的epoll、BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥I/O的性能。 memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。

①安装memcached依赖库libevent

wKioL1kZCrDS0JLsAAEPyB1Sbio340.jpg

②安装memcached

wKiom1kZCrDBqh2sAAEVwR9UXY8626.jpg

③检测memcache是否安装成功

wKioL1kZCrHQuwKTAAEB_7-AmRg027.jpg

通过以上操作就很简单的把memcached服务端编译好了。这时候就可以打开服务端进行工作了。

④配置环境变量

进入用户宿主目录,编辑.bash_profile,为系统环境变量LD_LIBRARY_PATH增加新的目录,需要增加的内容如下:

wKiom1kZCrHhl6o2AAC53gzVZ4Y369.jpg

wKioL1kZCrKwzFC7AACyY3fNhr0648.jpg

图片中具体内容如下:

MEMCACHED_HOME=/usr/local/memcached

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MEMCACHED_HOME/lib

⑤启动memcache服务

wKioL1kZCrLSlGK7AADPPMmMbRY026.jpg

注意:-m后面跟的是分配给memcache的内存,不能大于等于本主机内存。我的主机是2048M内存,我给了1024M。

启动参数说明:

-d     选项是启动一个守护进程。

-m 分配给Memcache使用的内存数量,单位是MB,默认64MB。

-l     监听的IP地址。(默认:INADDR_ANY,所有地址)

-p 设置Memcache的TCP监听的端口,最好是1024以上的端口。

-u 运行Memcache的用户,如果当前为root的话,需要使用此参数指定用户。

-c    选项是最大运行的并发连接数,默认是1024。

-P 设置保存Memcache的pid文件。

-M    内存耗尽时返回错误,而不是删除项

-f      块大小增长因子,默认是1.25

-n     最小分配空间,key+value+flags默认是48

-h     显示帮助

wKiom1kZCrPRmcQjAACrw50ePk0573.jpg

⑥防火墙开启11211端口例外

wKioL1kZCrOgk_zvAAEWxYwi0j4395.jpg

⑦刷新用户环境变量

wKiom1kZCrSRdCzJAACn8s4obgk449.jpg

刷新环境变量的时候报了一个错误,让执行那条命令,你就执行以下即可。

然后再次刷新环境变量:

wKioL1kZCrSTctvdAADwfhuegBM647.jpg

⑧编写memcached服务启停脚本

wKiom1kZCrWhsR56AADQpz0z21g897.jpg

脚本内容如下:

#!/bin/sh

#

# pidfile:/usr/local/memcached/memcached.pid

# memcached_home: /usr/local/memcached

# chkconfig: 35 21 79

# description: Start and stop memcachedService

 

# Source function library

. /etc/rc.d/init.d/functions

 

RETVAL=0

 

prog="memcached"

basedir=/usr/local/memcached

cmd=${basedir}/bin/memcached

pidfile="$basedir/${prog}.pid"

 

#interface to listen on (default:INADDR_ANY, all addresses)

ipaddr="192.168.1.10"

#listen port

port=11211

#username for memcached

username="root"

#max memory for memcached,default is 64M

max_memory=1024

#max connections for memcached

max_simul_conn=10240

start() {

echo -n $"Starting service:$prog"

$cmd -d -m $max_memory -u $username -l$ipaddr -p $port -c $max_simul_conn -P $pidfile

RETVAL=$?

echo

[ $RETVAL -eq 0 ] && touch/var/lock/subsys/$prog

}

 

stop() {

echo -n $"Stopping service:$prog  "

run_user=$(whoami)

pidlist=$(ps -ef | grep $run_user | grepmemcached | grep -v grep | awk '{print($2)}')

for pid in $pidlist

do

kill -9 $pid

if [ $? -ne 0 ]; then

return 1

fi

done

RETVAL=$?

echo

[ $RETVAL -eq 0 ] && rm -f/var/lock/subsys/$prog

}

 

# See how we were called.

case "$1" in

start)

start

;;

stop)

stop

;;

restart)

stop

start

;;

*)

echo "Usage: $0{start|stop|restart|status}"

exit 1

esac

exit $RETVAL

设置脚本可被执行:

wKioL1kZCrXTtYk3AAHtVWxcJ0E374.jpg

说明:

shell脚本中return的作用

1)终止一个函数.

2)return命令允许带一个整型参数, 这个整数将作为函数的"退出状态

码"返回给调用这个函数的脚本, 并且这个整数也被赋值给变量$?.

3)命令格式:returnvalue

  

先别急着闪,memcache服务脚本是配置好了,但是有个问题:

wKiom1kZCrWQGcmfAADhv21Qk2E976.jpg

从上图可以看出,重启不了memcache,这是因为当前memcache服务是运行着的,这个服务是开始的时候第⑤步启动的,所以咱们现在用服务脚本是重启不了的,解决办法如下:

wKioL1kZCragwLhBAAD4mPlU78s830.jpg

就是杀死正在运行的memcache服务的进程。

然后开始再重启服务:

wKiom1kZCrbR-zpdAAGNyNMCtpI168.jpg

至此就可以用服务脚本控制memcache服务了。

5、配置nginx.conf文件(在nginx&&php主机上操作)

①配置成如下的nginx.conf文件

wKiom1kZCrfgwuxKAACcA312wpY873.jpg

把原有的东西全部删除,配置成如下内容:

说明一下:我这里nginx&&php主机用的是4核,如果你的不是4核,请修改worker_cpu_affinity,如果是4核,请忽略该问题,全部复制我写好的内容即可。

user www www;

worker_processes  4;

worker_cpu_affinity 0001 0010 0100 1000;

error_log  logs/error.log;

#error_log  logs/error.log  notice;

#error_log  logs/error.log  info;

 

pid        logs/nginx.pid;

 

events {

use epoll;

   worker_connections  65535;

multi_accept on;

}

 

http {

include       mime.types;

   default_type application/octet-stream;

 

   #log_format  main  '$remote_addr - $remote_user [$time_local]"$request" '

   #                  '$status$body_bytes_sent "$http_referer" '

   #                 '"$http_user_agent" "$http_x_forwarded_for"';

 

   #access_log  logs/access.log  main;

 

sendfile        on;

tcp_nopush     on;

   keepalive_timeout  65;

tcp_nodelay on;

client_header_buffer_size 4k;

open_file_cache max=102400 inactive=20s;

   open_file_cache_valid 30s;

   open_file_cache_min_uses 1;

   client_header_timeout 15;

   client_body_timeout 15;

reset_timedout_connection on;

   send_timeout 15;

server_tokens off;

client_max_body_size 10m;

 

   fastcgi_connect_timeout     600;

   fastcgi_send_timeout 600;

   fastcgi_read_timeout 600;

fastcgi_buffer_size 64k;

   fastcgi_buffers     4 64k;

fastcgi_busy_buffers_size 128k;

fastcgi_temp_file_write_size 128k;

   fastcgi_temp_path /usr/local/nginx1.10/nginx_tmp;

fastcgi_intercept_errors on;

   fastcgi_cache_path /usr/local/nginx1.10/fastcgi_cache levels=1:2keys_zone=cache_fastcgi:128m inactive=1d max_size=10g;

 

gzip on;

   gzip_min_length  2k;

   gzip_buffers     4 32k;

   gzip_http_version 1.1;

   gzip_comp_level 6;

   gzip_types  text/plain text/csstext/javascript application/json application/javascriptapplication/x-javascript application/xml;

gzip_vary on;

gzip_proxied any;

server {

listen       80;

       server_name  www.benet.com;

 

       #charset koi8-r;

 

       #access_log logs/host.access.log  main;

 

location ~*^.+\.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ {

valid_referers none blocked  www.benet.com benet.com;

if ($invalid_referer) {

                #return 302  http://www.benet.com/img/nolink.jpg;

return 404;

break;

             }

access_log off;

       }

location / {

root  html;

index index.php index.html index.htm;

       }

location ~*\.(ico|jpe?g|gif|png|bmp|swf|flv)$ {

expires 30d;

            #log_not_found off;

access_log off;

       }

 

location ~* \.(js|css)$ {

expires 7d;

log_not_found off;

access_log off;

       }     

 

location = /(favicon.ico|roboots.txt) {

access_log off;

log_not_found off;

       }

location /status {

stub_status on;

       }

location ~ .*\.(php|php5)?$ {

root html;

            fastcgi_pass 127.0.0.1:9000;

            fastcgi_index index.php;

include fastcgi.conf;

            fastcgi_cache cache_fastcgi;

            fastcgi_cache_valid 200 302 1h;

            fastcgi_cache_valid 301 1d;

fastcgi_cache_valid any 1m;

            fastcgi_cache_min_uses 1;

fastcgi_cache_use_stale error timeoutinvalid_header http_500;

            fastcgi_cache_keyhttp://$host$request_uri;

       }

       #error_page  404              /404.html;

       # redirect server error pages to the static page /50x.html

       #

       error_page   500 502 503 504  /50x.html;

location = /50x.html {

root  html;

       }

  }

}

②重启nginx服务

wKioL1kZCrjRXqp0AAFxeAPqshg195.jpg

③编写一个php测试页

wKiom1kZCrjzbmMnAACssfO-DBA802.jpg

wKioL1kZCrjThbZ9AACOAwoUXVA426.jpg

④在客户端使用浏览器访问test1.php测试页

wKiom1kZCrmAqqszAADdfWYGaHk029.jpg

6、memcache客户端(在nginx&&php主机上操作)

说明:memcache分为服务端和客户端。服务端用来存放缓存,客户端用来操作缓存。

安装php扩展库(phpmemcache)

说明:安装PHP Memcache扩展:

可以使用php自带的pecl安装程序

#/usr/local/php5.6/bin/pecl install memcache

也可以从源码安装,他是生成php的扩展库文件memcache.so。

①安装memcache扩展库

wKioL1kZCrryrdscAAINUEZks-s281.jpg

wKioL1kZCrqwcYidAAC7eqSOCBc296.jpg

图片中内容如下:

./configure--enable-memcache --with-php-config=/usr/local/php5.6/bin/php-config &&make && make install

wKiom1kZCruD61hUAACNUqROcDc157.jpg

记住安装完毕后,最后一行你的这个路径。

/usr/local/php5.6/lib/php/extensions/no-debug-zts-20131226/

②修改php.ini

wKiom1kZCrviQkA7AAC8-OoxwSw026.jpg

添加如下一行内容:

wKioL1kZCrzTau2vAABNt9As1d0398.jpg

图片中内容如下:

extension=/usr/local/php5.6/lib/php/extensions/no-debug-zts-20131226/memcache.so

③重启php-fpm服务

wKioL1kZCxrTx0OZAAGVcAWOywA271.jpg

④测试

说明:检查php扩展是否正确安装。

主要是看查询结果中是否有memcache项。

wKiom1kZCxuzhX34AAJYLPlMbdA010.jpg

⑤在客户机浏览器上再次访问test1.php

则看到不到memcache和在session会话里面看不到memcache。

这是因为,nginx配置文件里配置了fast-cgi缓存,如果不注释点这一行,客户端访问的test1.php的数据,是fast-cgi缓存的,因为有缓存,memcache就起不到作用了。

解决办法如下:

wKioL1kZCxvhdNILAAChQ8_Bv8s497.jpg

wKiom1kZCxvQfxDDAABUPqvwClI766.jpg

wKioL1kZCxvBZvZqAAEii425iqw491.jpg

再次刷新test1.php页面,就可以看见如下的两个截图:

wKiom1kZCxzRc8tPAABa8sQkIzQ457.jpg

wKioL1kZCxywKxzAAABvSmsCweQ991.jpg

⑥编写test2.php测试页

说明:这个测试页测试的是往memcache服务器写/读数据测试

wKiom1kZCxzBGI9lAACfUZi_G_g516.jpg

具体内容如下:

<?php

$memcache = new Memcache;

$memcache->connect('192.168.1.10',11211) or die ("Could not connect");

$version = $memcache->getVersion();

echo "Server's version:".$version."<br/>";

$tmp_object = new stdClass;

$tmp_object->str_attr = 'test';

$tmp_object->int_attr = 123;

$memcache->set('key', $tmp_object,false, 10) or die ("Failed to save data at the server");

echo "Store data in the cache (datawill expire in 10 seconds)<br/>";

$get_result = $memcache->get('key');

echo "Data from thecache:<br/>";

var_dump($get_result);

?>

在客户机上访问test2.php

wKioL1kZCx2AusuqAADstILwzkE070.jpg

⑦使用memcache实现session共享

配置php.ini中的Session为memcache方式。

wKiom1kZCx6Cz4clAAC_4u41qEM623.jpg

wKiom1kZCx6RFcL0AABnpW_WV-4761.jpg

wKioL1kZCx7SQzxaAABrEOzKkkg047.jpg

说明:1394行是修改

          1424行是添加

两行的文字内容如下:

session.save_handler = memcache

session.save_path = "tcp://192.168.1.10:11211?persistent=1&weight=1&timeout=1&retry_interval=15"

ession.save_handler:设置session的储存方式为memcache 。默认以文件方式存取session数据,如果想要使用自定义的处理来存取session数据,比如memcache方式则修为session.save_handler = memcache

session.save_path:设置session储存的位置,多台memcache用逗号隔开

使用多个 memcached server 时用逗号”,”隔开,可以带额外的参数”persistent”、”weight”、”timeout”、”retry_interval”等等,

类似这样的:

"tcp://host:port?persistent=1&weight=2,tcp://host2:port2"

memcache实现session共享也可以在某个一个应用中设置:

ini_set("session.save_handler","memcache");

ini_set("session.save_path","tcp://192.168.0.9:11211");

ini_set()只对当前php页面有效,并且不会去修改php.ini文件本身,也不会影响其他php页面。

⑧测试memcache可用性

重启php-fpm:

wKioL1kZCx-TaVHIAAGcny4vtVs896.jpg

在nginx&&php

服务器上新建//usr/local/nginx1.10/html/memcache.php文件。内容如下:

wKiom1kZCx_CPVd8AACh8uEMryc198.jpg

<?php

session_start();

if (!isset($_SESSION['session_time']))

{

 $_SESSION['session_time'] = time();

}

echo "session_time:".$_SESSION['session_time']."<br/>";

echo"now_time:".time()."<br />";

echo"session_id:".session_id()."<br />";

?>

这个memcache.php的测试页面主要测试的是:

当客户机访问时,给客户机生成一个session信息,这个session就是记录在什么时间点缓存到memcache的数据。

wKioL1kZCyDSVGw5AADzhyZWOtg461.jpg

刷新一下页面,再看:

wKiom1kZCyGjn7AbAAEEGEEy8w0520.jpg

每刷一次页面,now_time的值就一直在涨,而session_time一直不会变的,因为是session会话保持嘛。

访问网址http://192.168.1.8/memcache.php可以查看session_time是否都是为memcache中的Session,同时可以在不同的服务器上修改不同的标识查看是否为不同的服务器上的。

可以直接用sessionid 去 memcached 里查询一下:

wKiom1kZCyGR0IsqAADKTNH1AT0904.jpg

wKioL1kZCyPT04sNAAXXncjLnUM006.jpg

说明:得到session_time|i:1493893966;这样的结果,说明session 正常工作。

默认memcache会监听11221端口,如果想清空服务器上memecache的缓存,一般使用的是:

wKiom1kZCyTygSIjAAJkbS1JHnU014.jpg

或者

wKioL1kZCyXg6bJfAADKT6h9QYc645.jpg

说明:使用flush_all 后并不是删除memcache上的key,而是置为过期。

memcache安全配置:

因为memcache不进行权限控制,因此需要通过iptables将memcache仅开放个web服务器。

7、测试memcache缓存数据库数据

①先在Mysql服务器上创建测试表

wKioL1kZCyXQbjynAAC4YrzKNAc722.jpg

wKiom1kZCyXglxuCAAEiSSINcMI495.jpg

wKioL1kZCybiuJ0QAAEZ2JurJk0225.jpg

wKiom1kZCyaCu7dQAADXFFVnH14227.jpg

wKioL1kZCyeCNYUMAAGp8xQpxIg086.jpg

②编写测试脚本

作用:用于测试memcache是否缓存数据成功。

先需要为这个脚本添加一个只读的数据库用户,命令格式:

wKiom1kZCyfQGqgYAADJw_At5-E631.jpg

在web服务器上创建测试脚本内容如下:

wKioL1kZCyfSG0UuAACk-firJYs465.jpg

<?php

$memcachehost = '192.168.1.10';

$memcacheport =11211;

$memcachelife = 60;

$memcache = new Memcache;

$memcache->connect($memcachehost,$memcacheport)or die ("Could not connect");

$query="select * from test1 limit 10";

$key=md5($query);

if(!$memcache->get($key))

{

                $conn=mysql_connect("192.168.1.9","user","123456");

                mysql_select_db(testdb1);

                $result=mysql_query($query);

while ($row=mysql_fetch_assoc($result))

                {

                        $arr[]=$row;

                }

                $f = 'mysql';

               $memcache->add($key,serialize($arr),0,30);

                $data = $arr ;

}

else{

       $f = 'memcache';

       $data_mem=$memcache->get($key);

       $data = unserialize($data_mem);

}

echo $f;

echo "<br>";

echo "$key";

echo "<br>";

//print_r($data);

foreach($data as $a)

{

echo "number is <b><fontcolor=#FF0000>$a[id]</font></b>";

echo "<br>";

echo "name is <b><font color=#FF0000>$a[name]</font></b>";

echo "<br>";

}

?>

③访问页面测试

wKiom1kZCyjzpnL-AAHBL6UMzg0208.jpg

说明:如果出现mysql表示memcached中没有内容,需要memcached从数据库中取得

再刷新页面,如果有memcache标志表示这次的数据是从memcached中取得的。

memcached有个缓存时间默认是1分钟,过了一分钟后,memcached需要重新从数据库中取得数据。

wKiom1kZCyjR5l8uAAHJfnEsaTA599.jpg

④查看 Memcached 缓存情况

我们需要使用 telnet 命令查看。

wKioL1kZCymgrKbMAAGtyMdttKo619.jpg

wKioL1kZCyuwbhSTAAUGccE_acY006.jpg

wKiom1kZCy2BTgPiAAPFGUgS6oE045.jpg

wKiom1kZC27hLVbGAAQJzTC84BE474.jpg

原文链接:https://blog.51cto.com/zpf666/1925729
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章