Nginx连接Memcached

来源:互联网 发布:预约学车软件 编辑:程序博客网 时间:2024/05/17 08:58

前言

之前这篇文章PHP与Memcached实战说的是php怎么连memcached,文中主要写的是php连接memcached的api。

Nginx连接Memcached

架构图

这里写图片描述

首先请求Nginx,Nginx去连接Memcached,从中读取数据,如果不存在,就使用PHP连接MySQL,在数据库中读取数据,然后将数据在复制到Memcached一份。

Memcached key

memcached是k/v存储,nginx请求memecached时用什么做key?一般用 uriarg 做key, 如 /user.html?id=1,这里我只使用uri做key

单个memcached服务器配置

server{    listen 80;    server_name test.com;    location / {        set $memcached_key $uri;#设置mc的key        memcached_pass 127.0.0.1:11211;#设置mc的端口        error_page 404 /callback.php;#错误提示功能    }    #nginx连接php的配置    location ~ \.php$ {        root           html;        fastcgi_pass   127.0.0.1:9000;        fastcgi_index  index.php;        fastcgi_param  SCRIPT_FILENAME  $DOCUMENT_ROOT$fastcgi_script_name;        include        fastcgi_params;    }   }

首先设置memcached存储的key为uri,然后设置mc服务器的端口,还设置了一个404返回的界面,当没有请求到页面时,我们就调用这个callback.php文件,在callback.php文件中我们要连接数据库,然后查找到数据,将数据复制到memcached一份。

callback.php文件:

<?php//获取请求的地址$uri = $_SERVER['REQUEST_URI'];//获取uid$uid = substr($uri,5,strpos($uri,'.')-5);//连数据库$dsn = 'mysql:host=localhost;dbname=test';$pdo = new PDO($dsn,'root','1234');$sql = 'select * from user where id = '.$uid;$st = $pdo->prepare($sql);$st->execute();$user = $st->fetchAll(PDO::FETCH_ASSOC);if(!empty($user)){    echo 'from mysql';    print_r($user);    //连接mc    $mem = new Memcache();    $mem->connect('127.0.0.1',11211);    $mem->add($uri,$user,false,300);    $mem->close();}else{    echo 'no user';}

当我们这样请求的时候:

test.com/user1.htmltest.com/user22.htmltest.com/user100.html

如果memcached中有数据,就不走callback文件,如果没有数据,我们就走callback文件,然后截取到对应的userid,拿着id去查询数据库,然后将查询到的数据复制到memcached一份。

memcached集群

 #memcached服务器池 upstream memcached_pool{        consistent_hash $request_uri; #一致性hash算法        server 127.0.0.1:11211;        server 127.0.0.1:11212;        server 127.0.0.1:11213; }server{   listen 80;   server_name test.com;   location / {       set $memcached_key $uri;       memcached_pass memcached_pool;       error_page 404 /callback.php;   }   location ~ \.php$ {       root           html;       fastcgi_pass   127.0.0.1:9000;       fastcgi_index  index.php;       fastcgi_param  SCRIPT_FILENAME  $DOCUMENT_ROOT$fastcgi_script_name;       include        fastcgi_params;   }}

这里我们不仅做了集群,还设置了Nginx连接memcached的算法为一致性哈希算法,至于什么是一致性哈希算法,可以去看我的文章:一致性哈希算法,为什么要设置一致性哈希算法。这样可以保证uri相同的情况下,我们发出的请求连接的memcached都是一台服务器,如果不写一致性哈希算法,那么Nginx将默认使用轮询算法,这样就不科学了。假设我们已经将内容写入了第一台服务器,但是第二次请求竟然落到了第二台服务器上,这样的话,又要写一遍数据。好不科学。

callback.php文件

<?php//获取请求的地址$uri = $_SERVER['REQUEST_URI'];//获取uid$uid = substr($uri,5,strpos($uri,'.')-5);//连数据库$dsn = 'mysql:host=localhost;dbname=test';$pdo = new PDO($dsn,'root','1234');$sql = 'select * from user where id = '.$uid;$st = $pdo->prepare($sql);$st->execute();$user = $st->fetchAll(PDO::FETCH_ASSOC);if(!empty($user)){    echo 'from mysql';    print_r($user);    //连接mc    $mem = new Memcache();    $mem->addServer('127.0.0.1',11211);    $mem->addServer('127.0.0.1',11212);    $mem->addServer('127.0.0.1',11213);    $mem->add($uri,$user,false,300);    $mem->close();}else{    echo 'no user';}

php连接memcached使用一致性hash算法

在php.ini中添加这样的一段:

memcache.hash_strategy=consistent

有的同学可能会问,为什么php也要使用一致性hash算法?假设nginx使用了一致性hash算法,用户请求的是:/user1.html页面,假设落到的是1号服务器,没有读到数据,去请求php,php去连接memcached,结果连得是第2台服务器,然后将数据写入了第2台服务器,我们发出的请求明明落在1号服务器,但是却写到了第2台服务器,这样就造成了数据的不一致。所以,我们要让Nginx和php都采用一致性hash算法。

nginx编译一致性hash扩展

1、下载ngx_http_consistent_hash扩展模块

cd /usr/local/srcwget https://github.com/replay/ngx_http_consistent_hash/archive/master.zip

2、将文件解压后复制到下/usr/local/src下

3、编译

./configure --prefix=/usr/local/nginx --add-module=/usr/local/src/ngx_http_consistent_hash-master/make && make install

结论

使用集群的时候,只要我们使用将nginx和php连接memcached的连接算法改为一致性hash算法,就可以实现读取和写入memcached的时候都是一台服务器了。

原创粉丝点击