• Nginx连接Memcached


    前言

    之前这篇文章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.html
    test.com/user22.html
    test.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/src
    wget 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的时候都是一台服务器了。

  • 相关阅读:
    fiddler使用
    Laravel数据库操作
    mysql 小知识点备忘(一)
    移动端和服务器端通信
    js函数和代码片段
    tomcat9目录结构解析
    数据库三范式的理解
    win10修改hosts文件
    Java十六进制字符串与二进制数组互转、&0xff的作用
    15、SpringBoot实现Excel的导入导出
  • 原文地址:https://www.cnblogs.com/cnsec/p/13406990.html
Copyright © 2020-2023  润新知