咱们工做中可能会遇到key-value数据库,若是咱们面对的不止一台memcache服务器,而是不少台。那么如今就回出现一个问题:php
当咱们访问nginx服务器的时候,咱们会判断memcache中是否有相应的值,若是没有咱们就从数据库中读取数据,可是这个时候咱们该在那一台memcache服务器读取,又应该在那一台memcache服务器存储呢?html
假设咱们有1/2/3/4/5台memcache服务器,咱们第一次访问nginx,全部memcache服务器都没有相应的存储。mysql
那么咱们就应该要从关系型数据库读取数据,并保存到memcache服务器。nginx
假设,保存到1号服务器。git
如今,咱们用和第一次访问参数同样的url进行nginx访问,那么如今要从哪个memcache服务器读取呢。nginx默认的集群算法为“取模”,也就是循环使用。github
也就是第二次的访问,应该是到2号服务器上读取,可是咱们存储的数据却在1号memcache服务器。这个时候就读不到了,因此,咱们又会在2号memcache中存储相应的值。这就不行了。算法
咱们但愿达到的效果为,相同的参数的url访问nignx和memcache的时候,咱们读取和存储的memcache是同一台。sql
这就须要用到咱们的hash一致性算法来解决了。数据库
mysql数据库为:服务器
如下是咱们的解决步骤:
一、首先,咱们须要在nginx上添加hash一致性算法模块。
下载ngx_http_consistent_hash算法插件。
下载地址:https://github.com/replay/ngx_http_consistent_hash
回到nginx安装包:cd nginx-1.14.2/
make clean
./configure --prefix=/usr/local/nginx --add-module=/usr/installsoft/ngx_http_consistent_hash-master/
咱们的hash插件,是放在/usr/installsoft/文件夹下的。
make && make install
启动nginx:/usr/local/nginx/sbin/nginx
二、编辑nginx.conf添加红色部分
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 0;
keepalive_timeout 65;
upstream imgserver {
server 111.231.226.228:81 weight=1 max_fails=2 fail_timeout=3;
server 111.231.226.228:82 weight=1 max_fails=2 fail_timeout=3;
}
upstream mcserver {
consistent_hash $request_uri;
server 111.231.226.228:11214;
server 111.231.226.228:11212;
server 111.231.226.228:11213;
}
编辑location,修改红色部分。
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
#以$rui为memcache hash一致性算法的key
set $memcached_key "$uri";
memcached_pass mcserver;
#若是没有读取到,这执行回调callback.php
error_page 404 /callback.php;
# root html;
# index index.php index.html index.htm;
}
三、将php的hash算法改成:consistent
在/usr/local/fastphp/lib/php.ini中添加下面代码。个人php是安装在/usr/local/fastphp下的,大家的以本身为准,上面的nginx同理。
memcache.hash_strategy=consistent
重启php。先杀了,在启动。
pkill -9 php-fpm
./sbin/php-fpm
四、编写咱们的额回调callback.php程序。
<?php
$uri = $_SERVER['REQUEST_URI'];
$uid = substr($uri,5,strpos($uri,'.')-5);
//设置memcache集群
$mem = new memcache();
$mem->addServer('111.231.226.228',11212);
$mem->addServer('111.231.226.228',11213);
$mem->addServer('111.231.226.228',11214);
//链接mysql数据库
$conn = mysql_connect('127.0.0.1','root','');
$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一下好让咱们知道是从memcache来的,仍是读取数据库来的。
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;
//想memcache中添加值。
$mem->add($uri,$html,0,300);
$mem->close();
}
?>
以上步骤都作完后,咱们来看效果:
访问nginx http 服务器。
第一次访问/user8.html.从下图,咱们能够看到,由于memcache中没有/html8.html的数据,因此是从mysql数据库中读取的。而且是在咱们打开的4号memcache会话框执行的(端口号11214)
咱们进行一次刷新,也就是相同的url再请求一次。有如下结果。咱们能够看到,这天数据是从memcache中取出来的,而且走的也是4号窗口(11214)。
咱们再来测试一个。获得相同的结果,可是请求的是,5号窗口(11214端口的memcache服务)
获得以上结果,表明咱们配置成功。