天天看点

nginx+PHP+memcached+MySQL+ip-hash做memcached集群

1、nginx与memcached整合

#安装memcached支持的事务库libevent

<code>wget https:</code><code>//github</code><code>.com</code><code>/libevent/libevent/releases/download/release-2</code><code>.0.22-stable</code><code>/libevent-2</code><code>.0.22-stable.</code><code>tar</code><code>.gz</code>

<code>tar</code> <code>zxf libevent-2.0.22-stable.</code><code>tar</code><code>.gz </code>

<code>cd</code> <code>libevent-2.0.22-stable</code>

<code>.</code><code>/configure</code> <code>--prefix=</code><code>/usr/local/libevent</code>

<code>make</code> <code>&amp;&amp; </code><code>make</code> <code>install</code>

<code>echo</code> <code>$?</code>

<code>cd</code> <code>..</code>

#接下来安装memcached:

<code>wget http:</code><code>//www</code><code>.memcached.org</code><code>/files/memcached-1</code><code>.4.35.</code><code>tar</code><code>.gz</code>

<code>tar</code> <code>zxf memcached-1.4.35.</code><code>tar</code><code>.gz</code>

<code>cd</code> <code>memcached-1.4.35</code>

<code>.</code><code>/configure</code> <code>--prefix=</code><code>/usr/local/memcached</code> <code>--with-libevent=</code><code>/usr/local/libevent</code>

#运行memcached

[root@nginx ~]# /usr/local/memcached/bin/memcached -d -u nobody -vv

#配置nginx配置文件nginx.conf,定位user的uri交给memcached做缓存

#添加location定位:

<code>location ~* user {</code>

<code>                </code><code>set</code> <code>$memcached_key </code><code>"$uri"</code><code>; </code><code>#设置memcached的key为uri</code>

<code>                </code><code>memcached_pass 192.168.146.132:11211; </code><code>#链接memcached</code>

<code>                </code><code>error_page 404 </code><code>/callback</code><code>.php; </code><code>#错误定位</code>

<code>        </code><code>}</code>

#加载nginx配置

nginx -s reload

#在memcached中写入一条URI数据,测试整合是否成功

<code>[root@nginx ~]</code><code># telnet 192.168.146.132 11211</code>

<code>Trying 192.168.146.132...</code>

<code>Connected to 192.168.146.132.</code>

<code>Escape character is </code><code>'^]'</code><code>.</code>

<code>add </code><code>/user1</code><code>.html 0 0 7</code>

<code>iamlisi </code>

<code>STORED</code>

<code>quit</code>

#访问http://192.168.146.132/user1.html如能看到iamlisi,那么nginx与memcache整合成功了!

2、整合PHP与memcahced

#安装PHP扩展模块memcache

<code>wget http:</code><code>//pecl</code><code>.php.net</code><code>/get/memcache-2</code><code>.2.7.tgz</code>

<code>tar</code> <code>zxvf memcache-2.2.7.tgz</code>

<code>cd</code> <code>memcache-2.2.7</code>

<code>/usr/local/php/bin/phpize</code> 

<code>.</code><code>/configure</code> <code>--</code><code>enable</code><code>-memcache --with-php-config=</code><code>/usr/local/php/bin/php-config</code> <code>--with-zlib-</code><code>dir</code>

pkill php-fpm   #杀死php-fpm进程

php-fpm   #启动php-fpm

http://192.168.146.132/test.php能看到memcache模块就成功了

#测试PHP与memcached

<code>vim </code><code>/usr/local/nginx/html/callback</code><code>.php</code>

<code>&lt;?php</code>

<code>print_r($_SERVER);</code>

<code>?&gt;php</code>

#访问http://1982.168.146.132/user2.html 此uri在memcached中不存在,就会回调到callback.php处理请求,结果如下:

<code>Array</code>

<code>(</code>

<code>    </code><code>[USER] =&gt; nobody</code>

<code>    </code><code>[HOME] =&gt; /</code>

<code>    </code><code>[FCGI_ROLE] =&gt; RESPONDER</code>

<code>    </code><code>[SCRIPT_FILENAME] =&gt; /usr/local/nginx/html/callback.php</code>

<code>    </code><code>[QUERY_STRING] =&gt; </code>

<code>    </code><code>[REQUEST_METHOD] =&gt; GET</code>

<code>    </code><code>[CONTENT_TYPE] =&gt; </code>

<code>    </code><code>[CONTENT_LENGTH] =&gt; </code>

<code>    </code><code>[SCRIPT_NAME] =&gt; /callback.php</code>

<code>    </code><code>[REQUEST_URI] =&gt; /user2.html</code>

<code>    </code><code>[DOCUMENT_URI] =&gt; /callback.php</code>

<code>    </code><code>[DOCUMENT_ROOT] =&gt; /usr/local/nginx/html</code>

<code>    </code><code>[SERVER_PROTOCOL] =&gt; HTTP/1.1</code>

<code>    </code><code>[REQUEST_SCHEME] =&gt; http</code>

<code>    </code><code>[GATEWAY_INTERFACE] =&gt; CGI/1.1</code>

<code>    </code><code>[SERVER_SOFTWARE] =&gt; nginx/1.12.1</code>

<code>    </code><code>[REMOTE_ADDR] =&gt; 192.168.146.1</code>

<code>    </code><code>[REMOTE_PORT] =&gt; 14187</code>

<code>    </code><code>[SERVER_ADDR] =&gt; 192.168.146.132</code>

<code>    </code><code>[SERVER_PORT] =&gt; 80</code>

<code>    </code><code>[SERVER_NAME] =&gt; localhost</code>

<code>    </code><code>[REDIRECT_STATUS] =&gt; 200</code>

<code>    </code><code>[HTTP_HOST] =&gt; 192.168.146.132</code>

<code>    </code><code>[HTTP_CONNECTION] =&gt; keep-alive</code>

<code>    </code><code>[HTTP_UPGRADE_INSECURE_REQUESTS] =&gt; 1</code>

<code>    </code><code>[HTTP_USER_AGENT] =&gt; Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36</code>

<code>    </code><code>[HTTP_ACCEPT] =&gt; text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8</code>

<code>    </code><code>[HTTP_ACCEPT_ENCODING] =&gt; gzip, deflate</code>

<code>    </code><code>[HTTP_ACCEPT_LANGUAGE] =&gt; zh-CN,zh;q=0.8</code>

<code>    </code><code>[PHP_SELF] =&gt; /callback.php</code>

<code>    </code><code>[REQUEST_TIME] =&gt; 1503552110</code>

<code>)</code>

3、使用PHP让memcached链接MySQL查询key与value并存入memcached,

#接下来我们写个PHP程序,链接数据库,让memcached找不到的uri就回调给PHP,然后PHP去链接数据库,查找数据后给memcached:

<code>cat</code> <code>html</code><code>/callback</code><code>.php</code>

<code>//print_r</code><code>($_SERVER);</code>

<code>//</code><code>获取UID用来做key</code>

<code>$uri = $_SERVER[</code><code>'REQUEST_URI'</code><code>];</code>

<code>//</code><code>分析出uir中的uid号</code>

<code>$uid = substr($uri,5,strpos($uri,</code><code>'.'</code><code>)-5);</code>

<code>//echo</code> <code>$uid;</code>

<code>//</code><code>链接数据库,查询并写入memcached</code>

<code>$conn = mysql_connect(</code><code>'localhost'</code><code>,</code><code>'root'</code><code>,</code><code>'123.com'</code><code>);</code>

<code>$sql = </code><code>'use test'</code><code>;</code>

<code>mysql_query($sql,$conn);</code>

<code>$sql = </code><code>'set names utf8'</code><code>;</code>

<code>$sql = </code><code>'select * from user where uid='</code><code>.$uid;</code>

<code>$rs = mysql_query($sql,$conn);</code>

<code>echo</code> <code>'from mysql query&lt;br /&gt;'</code><code>;</code>

<code>$user = mysql_fetch_assoc($rs);</code>

<code>if</code> <code>(empty($user)) {</code>

<code>    </code><code>echo</code> <code>'no this user'</code><code>;</code>

<code>} </code><code>else</code> <code>{</code>

<code>//</code>    <code>print_r($user);</code>

<code>    </code><code>$html = </code><code>'&lt;h1&gt;'</code><code>. $user[</code><code>'uname'</code><code>].</code><code>'&lt;/h1&gt;'</code><code>;</code>

<code>    </code><code>echo</code> <code>$html;</code>

<code>    </code><code>$mem = new memcache();</code>

<code>    </code><code>$mem-&gt;connect(</code><code>'192.168.146.132'</code><code>,11211);</code>

<code>    </code><code>$mem-&gt;add($uri,$html,0,300);</code>

<code>    </code><code>$mem-&gt;close();</code>

<code>}</code>

#此处我们要在数据库中建立test库和user表,并写入uid和uname字段数据:

#注意:callback.php文件调用的库和表,字段要对应建立

<code>mysql&gt; create database </code><code>test</code><code>;</code>

<code>mysql&gt; use </code><code>test</code><code>;</code>

<code>mysql&gt; create table user(</code>

<code>    </code><code>-&gt; uid int(11) not null,</code>

<code>    </code><code>-&gt; </code><code>uname</code> <code>varchar(255) not null,</code>

<code>    </code><code>-&gt; primary key (uid));</code>

<code>mysql&gt; insert into user (uid,</code><code>uname</code><code>) values(1,</code><code>'i am memcached'</code><code>);</code>

<code>mysql&gt; insert into user (uid,</code><code>uname</code><code>) values(2,</code><code>'dslajfflsaj;gljdaslgjlajfdalsjf'</code><code>);</code>

#此时访问uir,首先会转发到memcached处理,memcached中没有key就会回调给callback.php处理,然后PHP链接数据库,查询uri数据,然后memcached会写入key与value,并将数据返回给客户端。

http://192.168.146.132/user1.html

#memcached显示数据动态:

<code>&lt;36 new auto-negotiating client connection</code>

<code>36: Client using the ascii protocol</code>

<code>&lt;36 add </code><code>/user1</code><code>.html 1 300 122</code>

<code>&gt;36 STORED</code>

<code>&lt;36 connection closed.</code>

<code>&lt;36 get </code><code>/user1</code><code>.html</code>

<code>&gt;36 sending key </code><code>/user1</code><code>.html</code>

<code>&gt;36 END</code>

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模块并安装:

<code>cd</code> <code>/root/tools</code>

<code>wget https:</code><code>//github</code><code>.com</code><code>/replay/ngx_http_consistent_hash/archive/master</code><code>.zip</code>

<code>unzip master.zip</code>

#查看nginx编译参数

<code>[root@LNMP tools]</code><code># nginx -V</code>

<code>nginx version: nginx</code><code>/1</code><code>.8.1</code>

<code>built by gcc 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) </code>

<code>built with OpenSSL 1.0.1e-fips 11 Feb 2013</code>

<code>TLS SNI support enabled</code>

<code>configure arguments: --user=nginx --group=nginx --prefix=</code><code>/usr/local/nginx</code> <code>--with-http_ssl_module --with-http_stub_status_module --with-http_ssl_module --add-module=</code><code>/root/tools/nginx-1</code><code>.8.1</code><code>/nginx-rtmp-module</code>

#进入nginx源码目录,添加模块安装

<code>[root@LNMP tools]</code><code># cd nginx-1.8.1</code>

<code>[root@LNMP nginx-1.8.1]</code><code># ./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/</code>

<code>[root@LNMP nginx-1.8.1]</code><code>#make &amp;&amp; make install</code>

#模拟memcache集群,区分端口启动三个memcached

<code>memcached -d -u nobody -p 11211 -vv</code>

<code>memcached -d -u nobody -p 11212 -vv</code>

<code>memcached -d -u nobody -p 11213 -vv</code>

#nginx配置文件http段添加upstram模块:

<code>upstream mcserver {</code>

<code>        </code><code>consistent_hash $request_uri;  </code><code>#指定使用哈希算法,针对memcached,请参考文档</code>

<code>        </code><code>server 192.168.146.132:11211;</code>

<code>        </code><code>server 192.168.146.132:11212;</code>

<code>        </code><code>server 192.168.146.132:11213;</code>

#并在location中反向代理到mcserver集群:

具体参考文档:http://nginx.org/en/docs/http/ngx_http_memcached_module.html#memcached_pass

<code>location ~* </code><code>/user</code> <code>{</code>

<code>                </code><code>set</code> <code>$memcached_key </code><code>"$uri"</code><code>;  </code><code>#将uri配置为memcached的key</code>

<code>                </code><code>memcached_pass mcserver;    </code><code>#代理到memcached集群</code>

<code>                </code><code>error_page 404 = </code><code>/callback</code><code>.php;  </code><code>#memcached中找不到key将回调到此文件</code>

#重新加载nginx配置

#修改php配置为hash查询

#具体参考文挡:http://cn2.php.net/manual/en/memcache.ini.php#ini.memcache.hash-strategy

<code>vim </code><code>/usr/local/php/etc/php</code><code>.ini</code>

<code>memcache.hash_strategy=consistent  </code><code>#添加,使用一致性哈希</code>

#重新启动php-fpm

<code>pkill -9 php-fpm</code>

<code>netstat</code> <code>-lntup|</code><code>grep</code> <code>9000</code>

<code>php-fpm</code>

#修改回调代码,建立memcached集群链接

<code>//</code><code>建立memcached集群链接</code>

<code>$mem = new memcache();</code>

<code>$mem-&gt;addServer(</code><code>'192.168.146.132'</code><code>,11211);</code>

<code>$mem-&gt;addServer(</code><code>'192.168.146.132'</code><code>,11212);</code>

<code>$mem-&gt;addServer(</code><code>'192.168.146.132'</code><code>,11213);</code>

<code>    </code><code>$mem-&gt;add($uri,$html,0,10);</code>

#测试数据,memcached会在一个端口写入数据和查询数据:

<code>&lt;36 add </code><code>/user1</code><code>.html 0 10 87</code>

<code>&lt;37 new auto-negotiating client connection</code>

<code>37: Client using the ascii protocol</code>

<code>&lt;37 get </code><code>/user1</code><code>.html</code>

<code>&gt;37 END</code>

<code>&lt;37 connection closed.</code>

<code>&lt;40 new auto-negotiating client connection</code>

<code>40: Client using the ascii protocol</code>

<code>&lt;40 get </code><code>/user2</code><code>.html</code>

<code>&gt;40 END</code>

<code>&lt;40 connection closed.</code>

<code>&lt;40 add </code><code>/user2</code><code>.html 0 10 40</code>

<code>&gt;40 STORED</code>

<code>&lt;41 new auto-negotiating client connection</code>

<code>41: Client using the ascii protocol</code>

<code>&lt;41 get </code><code>/user2</code><code>.html</code>

<code>&gt;41 END</code>

<code>&lt;41 connection closed.</code>

#到此nginx+PHP+memcached+MySQL并现象memcached群架一致性哈希算法完成!

#途中遇到一个问题:在MySQL中写入中文数据,php调用后第一次显示正常,第二次存入memcached后调用就乱码了,我用Google和Firefox浏览器都是乱码,而用360和IE则没有乱码!暂时没找到原因,有知道的忘告知,万分感谢!!!

本文转自 80后小菜鸟 51CTO博客,原文链接:http://blog.51cto.com/zhangxinqi/1961992