天天看點

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