1、nginx与memcached整合
#安装memcached支持的事务库libevent
1
2
3
4
5
6
7
|
wget https:
//github
.com
/libevent/libevent/releases/download/release-2
.0.22-stable
/libevent-2
.0.22-stable.
tar
.gz
tar
zxf libevent-2.0.22-stable.
tar
.gz
cd
libevent-2.0.22-stable
.
/configure
--prefix=
/usr/local/libevent
make
&&
make
install
echo
$?
cd
..
|
#接下来安装memcached:
1
2
3
4
5
6
7
|
wget http:
//www
.memcached.org
/files/memcached-1
.4.35.
tar
.gz
tar
zxf memcached-1.4.35.
tar
.gz
cd
memcached-1.4.35
.
/configure
--prefix=
/usr/local/memcached
--with-libevent=
/usr/local/libevent
make
&&
make
install
echo
$?
cd
..
|
#运行memcached
[root@nginx ~]# /usr/local/memcached/bin/memcached -d -u nobody -vv
#配置nginx配置文件nginx.conf,定位user的uri交给memcached做缓存
#添加location定位:
1
2
3
4
5
|
location ~* user {
set
$memcached_key
"$uri"
;
#设置memcached的key为uri
memcached_pass 192.168.146.132:11211;
#链接memcached
error_page 404
/callback
.php;
#错误定位
}
|
#加载nginx配置
nginx -s reload
#在memcached中写入一条URI数据,测试整合是否成功
1
2
3
4
5
6
7
8
|
[root@nginx ~]
# telnet 192.168.146.132 11211
Trying 192.168.146.132...
Connected to 192.168.146.132.
Escape character is
'^]'
.
add
/user1
.html 0 0 7
iamlisi
STORED
quit
|
#访问http://192.168.146.132/user1.html如能看到iamlisi,那么nginx与memcache整合成功了!
2、整合PHP与memcahced
#安装PHP扩展模块memcache
1
2
3
4
5
6
7
8
|
wget http:
//pecl
.php.net
/get/memcache-2
.2.7.tgz
tar
zxvf memcache-2.2.7.tgz
cd
memcache-2.2.7
/usr/local/php/bin/phpize
.
/configure
--
enable
-memcache --with-php-config=
/usr/local/php/bin/php-config
--with-zlib-
dir
make
&&
make
install
echo
$?
cd
..
|
pkill php-fpm #杀死php-fpm进程
php-fpm #启动php-fpm
http://192.168.146.132/test.php能看到memcache模块就成功了
#测试PHP与memcached
1
2
3
4
|
vim
/usr/local/nginx/html/callback
.php
<?php
print_r($_SERVER);
?>php
|
#访问http://1982.168.146.132/user2.html 此uri在memcached中不存在,就会回调到callback.php处理请求,结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
Array
(
[USER] => nobody
[HOME] => /
[FCGI_ROLE] => RESPONDER
[SCRIPT_FILENAME] => /usr/local/nginx/html/callback.php
[QUERY_STRING] =>
[REQUEST_METHOD] => GET
[CONTENT_TYPE] =>
[CONTENT_LENGTH] =>
[SCRIPT_NAME] => /callback.php
[REQUEST_URI] => /user2.html
[DOCUMENT_URI] => /callback.php
[DOCUMENT_ROOT] => /usr/local/nginx/html
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_SCHEME] => http
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_SOFTWARE] => nginx/1.12.1
[REMOTE_ADDR] => 192.168.146.1
[REMOTE_PORT] => 14187
[SERVER_ADDR] => 192.168.146.132
[SERVER_PORT] => 80
[SERVER_NAME] => localhost
[REDIRECT_STATUS] => 200
[HTTP_HOST] => 192.168.146.132
[HTTP_CONNECTION] => keep-alive
[HTTP_UPGRADE_INSECURE_REQUESTS] => 1
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
[HTTP_ACCEPT_ENCODING] => gzip, deflate
[HTTP_ACCEPT_LANGUAGE] => zh-CN,zh;q=0.8
[PHP_SELF] => /callback.php
[REQUEST_TIME] => 1503552110
)
|
3、使用PHP让memcached链接MySQL查询key与value并存入memcached,
#接下来我们写个PHP程序,链接数据库,让memcached找不到的uri就回调给PHP,然后PHP去链接数据库,查找数据后给memcached:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
cat
html
/callback
.php
<?php
//print_r
($_SERVER);
//
获取UID用来做key
$uri = $_SERVER[
'REQUEST_URI'
];
//
分析出uir中的uid号
$uid = substr($uri,5,strpos($uri,
'.'
)-5);
//echo
$uid;
//
链接数据库,查询并写入memcached
$conn = mysql_connect(
'localhost'
,
'root'
,
'123.com'
);
$sql =
'use test'
;
mysql_query($sql,$conn);
$sql =
'set names utf8'
;
mysql_query($sql,$conn);
$sql =
'select * from user where uid='
.$uid;
$rs = mysql_query($sql,$conn);
echo
'from mysql query<br />'
;
$user = mysql_fetch_assoc($rs);
if
(empty($user)) {
echo
'no this user'
;
}
else
{
//
print_r($user);
$html =
'<h1>'
. $user[
'uname'
].
'</h1>'
;
echo
$html;
$mem = new memcache();
$mem->connect(
'192.168.146.132'
,11211);
$mem->add($uri,$html,0,300);
$mem->close();
}
|
#此处我们要在数据库中建立test库和user表,并写入uid和uname字段数据:
#注意:callback.php文件调用的库和表,字段要对应建立
1
2
3
4
5
6
7
8
|
mysql> create database
test
;
mysql> use
test
;
mysql> create table user(
-> uid int(11) not null,
->
uname
varchar(255) not null,
-> primary key (uid));
mysql> insert into user (uid,
uname
) values(1,
'i am memcached'
);
mysql> insert into user (uid,
uname
) values(2,
'dslajfflsaj;gljdaslgjlajfdalsjf'
);
|
#此时访问uir,首先会转发到memcached处理,memcached中没有key就会回调给callback.php处理,然后PHP链接数据库,查询uri数据,然后memcached会写入key与value,并将数据返回给客户端。
http://192.168.146.132/user1.html
#memcached显示数据动态:
1
2
3
4
5
6
7
8
9
10
11
|
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 add
/user1
.html 1 300 122
>36 STORED
<36 connection closed.
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 get
/user1
.html
>36 sending key
/user1
.html
>36 END
<36 connection closed.
|
4、配置memcached群架,nginx和PHP使用一致性哈希(ip-hash)
#当使用memcached群集时,会遇到数据写入memcached不一致,因为nginx模式使用round-robin(轮询)方式访问memcached服务器,就会造成写入和读出数据不在同一服务器的问题,为此nginx提供了ip-hash基于Ip的一致性哈希算法,它会记录访问IP,下次访问时同一ip会访问上次记录的服务器。
官方参考文档:https://www.nginx.com/resources/wiki/modules/consistent_hash/
#下载nginx hash模块并安装:
1
2
3
|
cd
/root/tools
wget https:
//github
.com
/replay/ngx_http_consistent_hash/archive/master
.zip
unzip master.zip
|
#查看nginx编译参数
1
2
3
4
5
6
|
[root@LNMP tools]
# nginx -V
nginx version: nginx
/1
.8.1
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=
/usr/local/nginx
--with-http_ssl_module --with-http_stub_status_module --with-http_ssl_module --add-module=
/root/tools/nginx-1
.8.1
/nginx-rtmp-module
|
#进入nginx源码目录,添加模块安装
1
2
3
|
[root@LNMP tools]
# cd nginx-1.8.1
[root@LNMP nginx-1.8.1]
# ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module --with-http_ssl_module --add-module=/root/tools/nginx-1.8.1/nginx-rtmp-module --add-module=/root/tools/ngx_http_consistent_hash-master/
[root@LNMP nginx-1.8.1]
#make && make install
|
#模拟memcache集群,区分端口启动三个memcached
1
2
3
|
memcached -d -u nobody -p 11211 -vv
memcached -d -u nobody -p 11212 -vv
memcached -d -u nobody -p 11213 -vv
|
#nginx配置文件http段添加upstram模块:
1
2
3
4
5
6
|
upstream mcserver {
consistent_hash $request_uri;
#指定使用哈希算法,针对memcached,请参考文档
server 192.168.146.132:11211;
server 192.168.146.132:11212;
server 192.168.146.132:11213;
}
|
#并在location中反向代理到mcserver集群:
具体参考文档:http://nginx.org/en/docs/http/ngx_http_memcached_module.html#memcached_pass
1
2
3
4
5
|
location ~*
/user
{
set
$memcached_key
"$uri"
;
#将uri配置为memcached的key
memcached_pass mcserver;
#代理到memcached集群
error_page 404 =
/callback
.php;
#memcached中找不到key将回调到此文件
}
|
#重新加载nginx配置
nginx -s reload
#修改php配置为hash查询
#具体参考文挡:http://cn2.php.net/manual/en/memcache.ini.php#ini.memcache.hash-strategy
1
2
|
vim
/usr/local/php/etc/php
.ini
memcache.hash_strategy=consistent
#添加,使用一致性哈希
|
#重新启动php-fpm
1
2
3
|
pkill -9 php-fpm
netstat
-lntup|
grep
9000
php-fpm
|
#修改回调代码,建立memcached集群链接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
cat
html
/callback
.php
<?php
//print_r
($_SERVER);
//
获取UID用来做key
$uri = $_SERVER[
'REQUEST_URI'
];
//
分析出uir中的uid号
$uid = substr($uri,5,strpos($uri,
'.'
)-5);
//
建立memcached集群链接
$mem = new memcache();
$mem->addServer(
'192.168.146.132'
,11211);
$mem->addServer(
'192.168.146.132'
,11212);
$mem->addServer(
'192.168.146.132'
,11213);
//
链接数据库,查询并写入memcached
$conn = mysql_connect(
'localhost'
,
'root'
,
'123.com'
);
$sql =
'use test'
;
mysql_query($sql,$conn);
$sql =
'set names utf8'
;
mysql_query($sql,$conn);
$sql =
'select * from user where uid='
.$uid;
$rs = mysql_query($sql,$conn);
echo
'from mysql query<br />'
;
$user = mysql_fetch_assoc($rs);
if
(empty($user)) {
echo
'no this user'
;
}
else
{
$html =
'<h1>'
. $user[
'uname'
].
'</h1>'
;
echo
$html;
$mem->add($uri,$html,0,10);
$mem->close();
}
|
#测试数据,memcached会在一个端口写入数据和查询数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 get
/user1
.html
>36 END
<36 connection closed.
<36 new auto-negotiating client connection
36: Client using the ascii protocol
<36 add
/user1
.html 0 10 87
>36 STORED
<37 new auto-negotiating client connection
37: Client using the ascii protocol
<37 get
/user1
.html
>37 END
<37 connection closed.
<40 new auto-negotiating client connection
40: Client using the ascii protocol
<40 get
/user2
.html
>40 END
<40 connection closed.
<40 new auto-negotiating client connection
40: Client using the ascii protocol
<40 add
/user2
.html 0 10 40
>40 STORED
<41 new auto-negotiating client connection
41: Client using the ascii protocol
<41 get
/user2
.html
>41 END
<41 connection closed.
|
#到此nginx+PHP+memcached+MySQL并现象memcached群架一致性哈希算法完成!
#途中遇到一个问题:在MySQL中写入中文数据,php调用后第一次显示正常,第二次存入memcached后调用就乱码了,我用Google和Firefox浏览器都是乱码,而用360和IE则没有乱码!暂时没找到原因,有知道的忘告知,万分感谢!!!
本文转自 80后小菜鸟 51CTO博客,原文链接:http://blog.51cto.com/zhangxinqi/1961992