分佈式緩存memcached

   Memcached是一款開源、高性能、分佈式內存對象緩存系統,可應用各種需要緩存的場景,其主要目的是通過降低對數據庫的訪問來加速web應用程序。它是一個基於內存的“鍵值對”存儲,用於存儲數據庫調用、API調用或頁面引用結果的直接數據,如字符串、對象等。

wKioL1c56yLQ_znaAAI81q37zc4591.png

一、memcached既不是一個代碼加速器,也不是數據庫中間件。其具有以下特點

   ⑴內置內存存儲方式:爲了提高性能,memcached中保存的數據都存儲在memcached內置的內存存儲空間中。重啓memcached,重啓操作系統會導致全部數據消失;

   ⑵簡單key/value存儲:服務器不關心數據本身的意義及結構,只要是可序列化數據即可。存儲項由“鍵、過期時間、可選的標誌及數據”四個部分組成;

   ⑶O(1)的執行效率;

   ⑷基於libevent的事件處理:libevent是個函數庫,它將Linux的epoll、BSD類操作系統的kqueue等時間處理功能封裝成統一的接口。memcached使用這個libevent庫,能發揮高性能;

   ⑸功能的實現一半依賴於客戶端,一半基於服務器端:客戶負責發送存儲項至服務器端、從服務端獲取數據以及無法連接至服務器時採用相應的動作;服務端負責接收、存儲數據,並設置數據項的過期時長;

   ⑹各服務器間不會通信以共享信息;memcached雖然是分佈式緩存服務器,但服務器端並沒有分佈式功能,此功能主要通過客戶端實現;

   ⑺清理超期數據:默認情況下,Memcached是一個LRU緩存,同時,它按事先預訂的時長清理超期數據;但事實上,memcached不會刪除任何已緩存數據,只是在其過期之後不再爲客戶端所見;而且,memcached也不會真正按期限清理緩存,而僅是當get命令到達時檢查其時長,發現過期才清理;


二、memcached的內存管理

wKiom1c56lzAL-wSAAQwDVuCgBE969.png

    可參考http://blog.csdn.net/dato/article/details/1968663


三、安裝memcached

   1、memcached依賴於libevent實現併發處理,先要安裝後libevent包,不過此包是系統標配;

       yum -y install memcached

   2、啓動memcached服務

       service memcached start   #memcached默認監聽在TCP和UDP的11211號端口

[root@node4 ~]# rpm -q libevent
libevent-1.4.13-4.el6.x86_64
[root@node4 ~]# yum -y install memcached
...
[root@node4 ~]# rpm -ql memcached
/etc/rc.d/init.d/memcached
/etc/sysconfig/memcached   #主配置文件
/usr/bin/memcached   #主程序
/usr/bin/memcached-tool
/usr/share/doc/memcached-1.4.4
...
[root@node4 ~]# vim /etc/sysconfig/memcached 

PORT="11211"
USER="memcached"
MAXCONN="1024"   #併發連接數
CACHESIZE="64"   #用於緩存的空間大小   
OPTIONS=""
[root@node4 ~]# service memcached start
...
[root@node4 ~]# ss -tunl
Netid State      Recv-Q Send-Q               Local Address:Port                 Peer Address:Port 
 
udp   UNCONN     0      0                       :::11211                          :::*     
tcp   LISTEN     0      128                     :::11211                          :::*     
tcp   LISTEN     0      128                      *:11211                           *:*     
...

   3、memcached主程序常用選項

       -l <ip_addr>:指定進程監聽的地址

       -d: 以守護進程模式運行;

       -u <username>:以指定的用戶身份運行memcached進程;

       -m <num>:用於緩存數據的最大內存空間,單位爲MB,默認爲64MB;

       -c <num>:最大支持的併發連接數,默認爲1024;

       -p <num>: 指定監聽的TCP端口,默認爲11211;

       -P <filename>: pid文件

       -U <num>:指定監聽的UDP端口,默認爲11211,0表示關閉UDP端口;

       -t <threads>:用於處理入站請求的最大線程數,僅在memcached編譯時開啓了支持線程纔有效;

       -f <num>:設定Slab Allocator定義預先分配內存空間大小固定的塊時使用的增長因子;默認爲1.25

       -M:當內存空間不夠使用時返回錯誤信息,而不是按LRU算法利用空間;

       -n: 指定最小的slab chunk大小;單位是字節;

       -S: 啓用sasl進行用戶認證;

[root@node4 ~]# memcached -u memcached -vv
slab class   1: chunk size        96 perslab   10922
slab class   2: chunk size       120 perslab    8738
slab class   3: chunk size       152 perslab    6898
slab class   4: chunk size       192 perslab    5461
slab class   5: chunk size       240 perslab    4369
slab class   6: chunk size       304 perslab    3449
slab class   7: chunk size       384 perslab    2730
slab class   8: chunk size       480 perslab    2184
slab class   9: chunk size       600 perslab    1747
slab class  10: chunk size       752 perslab    1394
...
[root@node4 ~]# memcached-tool 127.0.0.1
  #  Item_Size  Max_age   Pages   Count   Full?  Evicted Evict_Time OOM
  1      96B     80717s       1       1      no        0        0    0
[root@node4 ~]# memcached-tool 127.0.0.1 stats
#127.0.0.1:11211   Field       Value
                    ...
            pointer_size          64
           rusage_system    1.216815
             rusage_user    1.241811
                 threads           4
                    time  1463497553
       total_connections          17
             total_items           7
                  uptime       81292
                 version       1.4.4


四、Memcached提供了爲數不多的幾個命令來完成與服務器端的交互,這些命令基於memcached的協議實現。

  1、存儲類命令:set, add, replace, append, prepend

      用法:<command> <key> <flag> <expire> <size>

          <value>

         例如:set user 0 0 8   #過期時長爲0表示永不過期

             jerry

      set:無論如何都存儲,數據不存在時存儲,數據存在時更新

      add:數據不存在時進行添加

      replace:替換

      append:將數據追加到當前緩存數據的之後

      prepend:將數據追加到當前緩存數據的之前

  2、獲取數據類命令:get, delete, incr/decr

      get key1 key2...:讀取 

      incr/decr key:對數字型的對象進行增/減操作     

  3、統計類命令:

      stats:查看memcached運行狀態

      stats items:

      stats slabs:顯示各個slab的信息,包括chunk的大小、數目、使用情況等

      stats sizes:輸出所有item的大小和個數

  4、清理命令:

      delete key:刪除

      flush_all:將當前所有緩存數據設置爲過期,但不會釋放內存

[root@node4 ~]# telnet 127.0.0.1 11211   #使用telnet命令測試memcached的使用
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
set user 0 60 5 
jerry
STORED
add gender 0 60 6
female
STORED
get user
VALUE user 0 5
jerry
END
delete gender
DELETED
stats
STAT pid 37622
STAT uptime 80761
STAT time 1463497022
STAT version 1.4.4
STAT pointer_size 64
STAT rusage_user 1.241811
STAT rusage_system 1.173821
STAT curr_connections 10
STAT total_connections 15
STAT connection_structures 11
...
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT bytes 74
STAT curr_items 1
STAT total_items 7
STAT evictions 0
END


五、PHP作爲memcached的客戶端

  1、在php-fpm服務器上安裝PHP的memcache擴展

      # wget https://pecl.php.net/get/memcache-2.2.7.tgz

      # tar xf memcache-2.2.7.tgz

      # cd memcache-2.2.7

      # /usr/local/php/bin/phpize   生成configure文件

      # ./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcache

      # make && make install

    安裝完後會有類似以下的提示:

      Installing shared extensions:   /usr/local/php/lib/php/extensions/no-debug-non-zts-20130626/          

  2、編輯/usr/local/php/lib/php.ini,在“動態模塊”相關的位置添加memcache擴展的路徑:

      extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20130626/memcache.so


  ◆補充:rpm方式安裝的php-fpm如何加載擴展模塊

      此種情況需要先安裝php-devel包,該包能提供phpize和php-config兩個二進制程序。其餘步驟與上述類似,根據實際情況做適當修改即可。

      # yum -y install php-devel

      ......

      # ./configure --with-php-config=/usr/bin/php-config --enable-memcache

      ...

      cp tmp-php.ini /etc/php.d/

      vim /etc/php.d/tmp-php.ini

        extension=/usr/lib64/php/modules/memcache.so


   示例:

wKioL1c8kO3hFyVtAAAfm3hEd2c487.png  

#此例中的php-fpm是使用rpm方式安裝的,所以若欲對其做擴展就要先安裝php-devel
[root@node1 ~]# yum -y install php-devel
...
[root@node1 ~]# rpm -ql php-devel
/etc/rpm/macros.php
/usr/bin/php-config
/usr/bin/phpize
/usr/include/php
...
[root@node1 ~]# wget https://pecl.php.net/get/memcache-2.2.7.tgz    #下載memcache擴展源碼包
...
[root@node1 ~]# tar xf memcache-2.2.7.tgz 
[root@node1 ~]# cd memcache-2.2.7
[root@node1 memcache-2.2.7]# phpize    #生成configure文件
Configuring for:
PHP Api Version:         20090626
Zend Module Api No:      20090626
Zend Extension Api No:   220090626
[root@node1 memcache-2.2.7]# ls
acinclude.m4    config9.m4    config.sub    CREDITS      Makefile.global             memcache.php        memcache_standard_hash.c  README
aclocal.m4      config.guess  configure     example.php  memcache.c                  memcache_queue.c    missing                   run-tests.php
autom4te.cache  config.h.in   configure.in  install-sh   memcache_consistent_hash.c  memcache_queue.h    mkinstalldirs
build           config.m4     config.w32    ltmain.sh    memcache.dsp                memcache_session.c  php_memcache.h
[root@node1 memcache-2.2.7]# ./configure --with-php-config=/usr/bin/php-config --enable-memcache   #編譯
...
[root@node1 memcache-2.2.7]# make && make install
...
Build complete.
Don't forget to run 'make test'.

Installing shared extensions:     /usr/lib64/php/modules/   #memcache模塊的目錄


[root@node1 memcache-2.2.7]# ls /usr/lib64/php/modules/
curl.so  fileinfo.so  json.so  memcache.so  phar.so  zip.so
[root@node1 memcache-2.2.7]# cp tmp-php.ini /etc/php.d/
[root@node1 memcache-2.2.7]# vim /etc/php.d/tmp-php.ini
在Dynamic Extensions段下添加:
extension=/usr/lib64/php/modules/memcache.so
[root@node1 memcache-2.2.7]# service php-fpm restart
...

wKioL1c6vBPxYGeJAADVzPjwXpQ195.png


  3、對memcached功能進行測試,在網站目錄中建立測試頁面test.php,添加如下內容:

     <?php

       $mem = new Memcache;

       $mem->connect("192.168.30.14", 11211) or die("Could not connect");

       $version = $mem->getVersion();

       echo "Server's version: ".$version."<br/>\n";

       $mem->set('hellokey', 'Hello World', 0, 600) or die("Failed to save data at the memcached server");

       echo "Store data in the cache (data will expire in 600 seconds)<br/>\n";

       $get_result = $mem->get('hellokey');

       echo "$get_result is from memcached server.";         

      ?>

      如果有輸出“Hello World is from memcached.”等信息,則表明memcache已經能夠正常工作。

[root@node1 ~]# vim /web/scripts/memtest.php    #創建一個測試頁

<?php
    $mem = new Memcache;
    $mem->connect("192.168.30.14", 11211) or die("Could not connect");
    $version = $mem->getVersion();
    echo "Server's version: ".$version."<br/>\n";
    $mem->set('hellokey', 'Hello World', 0, 600) or die("Failed to save data at the memcached server");
    echo "Store data in the cache (data will expire in 600 seconds)<br/>\n";
    $get_result = $mem->get('hellokey');
    echo "$get_result is from memcached server.";
?>

wKiom1c6u_SyLF4aAABklEFutCU078.png


六、php程序調用memcached服務的另一個擴展memcached

    memcache擴展是原生的(基於pecl擴展庫),而memcached擴展是基於libmemcached庫開發的,libmemcached是memcache的C接口,具有低內存,線程安全等特點;memcached擴展支持Binary Protocol,而memcache擴展不支持;總之,memcached擴展相對來說具有更高的性能。

    libmemcached還提供了數個可以遠程使用的memcached管理工具,如memcat, memping,memstat,memslap等。

    既然memcached擴展基於limemcached,因此要先編譯安裝libmemcached;libmemcached的源碼包可到https://launchpad.net/libmemcached/+download獲取,memcached擴展的源碼包可到http://pecl.php.net/上獲取;

    編譯memcached擴展

      ./configure --with-libmemcached-dir=/path/to/somedir(指定libmemcached的安裝目錄) --enable-memcached

    其它步驟與安裝memcache擴展類似,不再贅述


七、memcached的圖形管理工具

   memcached的圖形管理管理工具主要有memcachephpmemadmin-masterphpMemcachedAdmin

   phpMemcachedAdmin的壓縮包可到http://blog.elijaa.org/phpmemcachedadmin-download-version-1-2-2/獲取

[root@node1 scripts]# ls
index.php  memcachephp.zip  memtest.php
[root@node1 scripts]# unzip memcachephp.zip 
[root@node1 scripts]# ls
index.php  memcache.php  memcachephp.zip  memtest.php
[root@node1 scripts]# vim memcache.php 

<?php
...
$VERSION='$Id: memcache.php,v 1.1.2.3 2008/08/28 18:07:54 mikl Exp $';

define('ADMIN_USERNAME','magedu');      // Admin Username   #設置一個賬號和密碼
define('ADMIN_PASSWORD','123');         // Admin Password
define('DATE_FORMAT','Y/m/d H:i:s');
define('GRAPH_SIZE',200);
define('MAX_ITEM_DUMP',50);

$MEMCACHE_SERVERS[] = '192.168.30.14:11211'; // add more as an array   #指定memcached服務器地址
...

wKiom1c7R0TS_eY2AAIVLYseF30337.png


八、memcached的分佈式

    memcached本身沒有“分佈式”的功能,memcached的分佈式是由客戶端實現的。memcached的客戶端接口(API,函數庫)用hash算法根據“鍵”來決定保存數據的memcached服務器。獲取數據時把要獲取的“鍵”傳遞給函數庫,函數庫通過與數據保存時相同的算法,根據“鍵”選擇服務器。使用的算法相同,就能選中與保存時相同的服務器。這樣,將不同的鍵保存到不同的服務器上,就實現了memcached的分佈式。memcached服務器增多後,鍵就會分散,即使一臺memcached服務器發生故障無法連接,也不會影響其他的緩存。

    爲了減小增刪節點對緩存的影響和增加緩存的平衡性,應儘量使用“一致性hash”算法,關於“一致性hash”算法,可參考http://blog.csdn.net/cywosp/article/details/23397179

  1、使用“一致性hash”算法做緩存分佈示例

    ①啓動若干個memcached服務器;這裏爲演示方便,僅在一個memcached服務主機上啓動幾個實例

[root@node4 ~]# memcached -d -u memcached -m 20 -p 11211
[root@node4 ~]# memcached -d -u memcached -m 20 -p 11212
[root@node4 ~]# memcached -d -u memcached -m 20 -p 11213
[root@node4 ~]# ss -tnl
State       Recv-Q Send-Q                   Local Address:Port                       Peer Address:Port 
LISTEN      0      128                      :::11211                                 :::*     
LISTEN      0      128                      *:11211                                  *:*     
LISTEN      0      128                      :::11212                                 :::*     
LISTEN      0      128                      *:11212                                  *:*     
LISTEN      0      128                      :::11213                                 :::*     
LISTEN      0      128                      *:11213                                  *:*
...

   ②修改php的memcache擴展源碼包中的memcache.c文件中的算法設置,然後重新編譯

      "memcache.hash_strategy",         "consistent"

       MEMCACHE_G(hash_strategy)        = MMC_CONSISTENT_HASH;

    當然,可不用修改源碼重新編譯,還有另外的設置方法,可參考http://wtm-mac.iteye.com/blog/1687746

[root@node1 ~]# tar xf memcache-2.2.7.tgz 
[root@node1 ~]# cd memcache-2.2.7
[root@node1 memcache-2.2.7]# vim memcache.c
...
"memcache.hash_strategy",         "consistent"
...
MEMCACHE_G(hash_strategy)        = MMC_CONSISTENT_HASH;
# 之後的編譯安裝的步驟略

   ③創建一個測試文件

       vim /web/scripts/distribute.php

[root@node1 ~]# vim /web/scripts/distribute.php 

$mem = new Memcache;
$mem->addServer('192.168.30.14', 11211);
$mem->addServer('192.168.30.14', 11212);
$mem->addServer('192.168.30.14', 11213);

$key1 = 'mdtest1';
$value1 = '1';
$mem->add($key1, $value1);

$key2 = 'mdtest2';
$value2 = '2';
$mem->add($key2, $value2);

$key3 = 'mdtest3';
$value3 = '3';
$mem->add($key3, $value3);

$key4 = 'mdtest4';
$value4 = '4';
$mem->add($key4, $value4);

$key5 = 'mdtest5';
$value5 = '5';
$mem->add($key5, $value5);

$key6 = 'mdtest6';
$value6 = '6';
$mem->add($key6, $value6);

echo "OK";
?>

  2、利用magent搭建memcached集羣

    magent是一個緩存代理服務器,可以連接多臺後端Memcached服務器,它接受客戶端的請求,根據一定的算法做緩存分佈,而且還能對後端memcached緩存做高可用。具體的安裝配置可參考http://www.php-note.com/article/detail/800


九、Nginx整合memcached

   nginx的memcached模塊能夠實現調用memcached服務進行緩存

   配置示例:

     server {

        listen       80;

        server_name  www.magedu.com;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {

            set $memcached_key $uri?$args;   #表示將請求的URI作爲查詢的key

            memcached_pass   127.0.0.1:11211;

            default_type    text/html;

            error_page     404 @fallback;

        }

        location @fallback {

                proxy_pass http://172.16.0.1;

        }

      }

   memcached模塊中的一些指令:

     memcached_pass address;

     memcached_buffer_size size;

     memcached_connect_timeout time;

     memcached_read_timeout time;

     memcached_send_timeout time;

     這些指令與proxy模塊中的指令類似,其用法不再贅述,可查看官方文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章