至于Memcache的安裝配置,我們就不講了,PHP分布式中使用Memcache來同步存儲SESSION的步驟如下:
1、直接修改php.ini配置文件
- session.save_handler = memcache
- session.save_path = "tcp://127.0.0.100:11211"
2、利用目錄下的 .htaccess 文件
- php_value session.save_handler "memcache"
- php_value session.save_path "tcp://127.0.0.1:11211"
說明:這個只是針對Apache的,目前使用Nginx的比較多,也不推薦此方式。
3、項目中修改配置
- ini_set("session.save_handler", "memcache");
- ini_set("session.save_path", "tcp://127.0.0.100:11211");
上面只是一些簡單的說明,其實說點題外話,一般來說,做分布式,那肯定是有服務器權限的,所以推薦第一種。
memcache分布式實現、memcache分布式的數據同步、memcache保存session數據的實現
Memcache的分布式介紹
memcached雖然稱為“分布式”緩存服務器,但服務器端并沒有“分布式”功能。服務器端僅包括內存存儲功能,其實現非常簡單。至于memcached的分布式,則是完全由客戶端程序庫實現的。這種分布式是memcached的最大特點。
Memcached的分布式是什么意思?
這里多次使用了“分布式”這個詞,但并未做詳細解釋。現在開始簡單地介紹一下其原理,各個客戶端的實現基本相同。
下面假設memcached服務器有node1~node3三臺,應用程序要保存鍵名為“tokyo”“kanagawa”“chiba”“saitama”“gunma”的數據。
首先向memcached中添加“tokyo”。將“tokyo”傳給客戶端程序庫后,客戶端實現的算法就會根據“鍵”來決定保存數據的memcached服務器。服務器選定后,即命令它保存“tokyo”及其值。
同樣,“kanagawa”“chiba”“saitama”“gunma”都是先選擇服務器再保存。接下來獲取保存的數據。獲取時也要將要獲取的鍵“tokyo”傳遞給函數庫。函數庫通過與數據保存時相同的算法,根據“鍵”選擇服務器。使用的算法相同,就能選中與保存時相同的服務器,然后發送get命令。只要數據沒有因為某些原因被刪除,就能獲得保存的值。
這樣,將不同的鍵保存到不同的服務器上,就實現了memcached的分布式。 memcached服務器增多后,鍵就會分散,即使一臺memcached服務器發生故障無法連接,也不會影響其他的緩存,系統依然能繼續運行。
Php+memcache實現分布式:
我們PHP的PECL中的Memcache擴展能夠有效的解決Memcache的分布式問題,主要的接口就是 addServer() 函數,具體關于addServer()函數的實現可以參考該擴展源代碼。那么現在就存在第二個問題,就是說無法同步數據,可以理解為MySQL中Master/Slave的機制,就是說如果我們有多臺的Memcache服務器,使用addServer函數的話,每個服務器存儲的數據都是唯一的,也就是說每個memcached服務器上存儲的數據不是統一的,而是各自保存了不通的數據。
配置使用memcache存儲session數據
session.save_handler = memcache
session.save_path ="tcp://127.0.0.1:11211"
或者某個目錄下的 .htaccess :
- php_value session.save_handler"memcache"
- php_value session.save_path "tcp://127.0.0.1:11211"
再或者在某個一個應用中:
- ini_set("session.save_handler","memcache");
- ini_set("session.save_path","tcp://127.0.0.1:11211");
使用多個 memcached server 時用逗號","隔開,并且和Memcache::addServer() 文檔中說明的一樣,可以帶額外的參數"persistent"、"weight"、"timeout"、"retry_interval"等等,類似這樣的:"tcp://host1:port1?persistent=1&weight=2,tcp://host2:port2"。
存session:
- <?php
- session_start();
- if (!isset($_SESSION['TEST'])) {
- $_SESSION['TEST'] = time();
- }
- $_SESSION['TEST3'] = time();
- print $_SESSION['TEST'];
- print "<br><br>";
- print $_SESSION['TEST3'];
- print "<br><br>";
- print session_id();
- ?>
從memcache中取回session數據:
- <?php
- $memcache = memcache_connect('localhost',11211);
- var_dump($memcache->get('19216821213c65cedec65b0883238c278eeb573e077'));
- ?>
會有看到:
string(37)"TEST|i:1177556731;TEST3|i:1177556881;"
這樣的輸出,證明 session 正常工作,用 memcache 來存儲 session 在讀寫速度上會比 files 時快很多,而且在多個服務器需要共用 session 時會比較方便,將這些服務器都配置成使用同一組 memcached 服務器就可以,減少了額外的工作量。缺點是 session 數據都保存在 memory 中,持久化方面有所欠缺,但對 session 數據來說也不是很大的問題。
另外,WS Memcached Session Handler for PHP 提供一種用session_set_save_handler 來利用 memcached 的方法。。
Linux下的Memcache安裝
1. 如果通過下載源碼進行安裝,則需要下載最新版本http://memcached.googlecode.com/files/memcached-1.4.13.tar.gz。
如果通過apt-get方式安裝,則無需下載。
2. 進行memcache的安裝:
1).下載源碼,進行編譯安裝
Memcache用到了libevent這個庫用于Socket的處理,所以還需要安裝libevent,libevent的最新版本是https://github.com/downloads/libevent/libevent/libevent-2.0.19-stable.tar.gz,如果你的系統已經安裝了libevent,則不需要安裝。
- # cd /tmp
- # wget http://www.danga.com/memcached/dist/memcached-1.2.0.tar.gz
- # wgethttp://www.monkey.org/~provos/libevent-1.2.tar.gz
2.先安裝libevent:
- # tar zxvf libevent-1.2.tar.gz
- # cd libevent-1.2
- # ./configure --prefix=/usr
- # make
- # make install
測試libevent是否已經安裝。
- # ls -al /usr/lib | grep libevent
- lrwxrwxrwx 1 root root 21 11?? 12 17:38libevent-1.2.so.1 -> libevent-1.2.so.1.0.3
- -rwxr-xr-x 1 root root 263546 11?? 12 17:38libevent-1.2.so.1.0.3
- -rw-r--r-- 1 root root 454156 11?? 12 17:38 libevent.a
- -rwxr-xr-x 1 root root 811 11?? 12 17:38 libevent.la
- lrwxrwxrwx 1 root root 21 11?? 12 17:38 libevent.so-> libevent-1.2.so.1.0.3
安裝memcache
安裝memcached,同時需要安裝中指定libevent的安裝位置:
- # cd /tmp
- # tar zxvf memcached-1.2.0.tar.gz
- # cd memcached-1.2.0
- # ./configure --with-libevent=/usr
- # make
- # make install
如果中間出現報錯,請仔細檢查錯誤信息,按照錯誤信息來配置或者增加相應的庫或者路徑。
安裝完成后會把memcached放到 /usr/local/bin/memcached 。
測試是否成功安裝memcached:
- # ls -al /usr/local/bin/mem*
- -rwxr-xr-x 1 root root 137986 11?? 12 17:39/usr/local/bin/memcached
- -rwxr-xr-x 1 rootroot 140179 11?? 12 17:39 /usr/local/bin/memcached-debug
2)通過apt-get進行安裝:
sudo apt-get install memcached,推薦通過該方式進行安裝,比較簡單,不容易出現錯誤。
啟動memcache服務器:
memcached -d -m 50 -p 11211 -uroot
memcached常用啟動參數描述:
-d:啟動一個守護進程,
-m:分配給Memcache使用的內存數量,單位是MB,默認是64MB,
-u:運行Memcache的用戶
-l:監聽的服務器IP地址
-p:設置Memcache監聽的端口,默認是11211注:-p(p為小寫)
-c:設置最大并發連接數,默認是1024
-P:設置保存Memcache的pid文件注:-P(P為大寫)
-h 顯示幫助
安裝Memcache的PHP擴展
通過地址http://pecl.php.net/get/memcache-2.2.6.tgz下載memcache最新的穩定版本。
安裝php的memcache擴展有兩種方式:
在linux下安裝memcache擴展
可以使用php自帶的pecl安裝程序
# pecl install memcache
或apt-get安裝php的memcache擴展
sudo apt-get installphp5-memcache
也可以從源碼安裝
- # tar zxf memcache-2.2.3.tgz
- # cd memcache-2.2.3
- # /usr/local/servers/php5/bin/phpize
- #./configure --enable-memcache=/usr/local/servers/memcached--with-php-config=/usr/local/servers/php5/bin/php-config--with-apxs2=/usr/sbin/apxs
- # make && make inst
安裝完后會有類似這樣的提示:
- Installing shared extensions:/usr/local/servers/php5/lib/php/extensions/no-debug-non-zts-20060922/
把這個記住,然后修改php.ini,把
extension_dir ="./"
修改為:
extension_dir ="/usr/local/servers/php5/lib/php/extensions/"
并添加一行:
extension="no-debug-non-zts-20060922/memcache.so"
在windows下安裝memcache擴展
下載時要弄清楚自己的php版本,下載相對應的memcache擴展的版本,我用的是php5.2.6,下載地址為http://museum.php.net/php5/pecl-5.2.6-Win32.zip,解壓后找到它的php_memcache.dll文件,放在php目錄下的extension目錄下,并在php.ini 加入一行 ‘extension=php_memcache.dll’。phpinfo下,看是否安裝成功。
Php的memcache
使用實例:
- <?php
- //連接
- $mem = new Memcache;
- $mem->connect("192.168.0.200", 12000);
- //保存數據
- $mem->set('key1', 'This is first value', 0, 60);
- $val = $mem->get('key1');
- echo "Get key1 value: " . $val ."<br/>";
- //替換數據
- $mem->replace('key1', 'This is replace value', 0,60);
- $val = $mem->get('key1');
- echo "Get key1 value: " . $val ."<br />";
- //保存數組
- $arr = array('aaa', 'bbb', 'ccc', 'ddd');
- $mem->set('key2', $arr, 0, 60);
- $val2 = $mem->get('key2');
- echo "Get key2 value: ";
- print_r($val2);
- echo "<br />";
- //刪除數據
- $mem->delete('key1');
- $val = $mem->get('key1');
- echo "Get key1 value: " . $val ."<br />";
- //清除所有數據
- $mem->flush();
- $val2 = $mem->get('key2');
- echo "Get key2 value: ";
- print_r($val2);
- echo "<br />";
- //關閉連接
- $mem->close();
- ?>
Memcached集群
Magent軟件介紹
magent是一款開源的memcached代理服務器軟件
地址: http://code.google.com/p/memagent/
安裝magent到/usr/local/下
- cd /usr/local
- mkdir magent
- cd magent/
- wgethttp://memagent.googlecode.com/files/magent-0.5.tar.gz
- tar zxvf magent-0.5.tar.gz
- /sbin/ldconfig
- sed -i "s/LIBS = -levent/LIBS =-levent -lm/g" Makefile
- make
magent命令參數:
- -hthis message
- -u uid
- -g gid
- -p port, default is 11211. (0 to disable tcpsupport)
- -s ip:port, set memcached server ip and port
- -b ip:port, set backup memcached server ip andport
- -l ip, local bind ip address, default is 0.0.0.0
- -n number, set max connections, default is 4096
- -D don't go to background
- -k use ketama key allocation algorithm
- -f file, unix socket path to listen on. defaultis off
- -i number, max keep alive connections for onememcached server, default is 20
- -v verbose
啟動magent服務
- magent -u root -n 4096 -l 127.0.0.1 -p12000 -s127.0.0.1:8086 -s 127.0.0.2:8086 -b 127.0.0.1:11213
magent的hash算法
magent采用的是:Consistent Hashing原理,Consistent Hashing如下所示:首先求出memcached服務器(節點)的哈希值,并將其配置到0~232的圓(continuum)上。 然后用同樣的方法求出存儲數據的鍵的哈希值,并映射到圓上。 然后從數據映射到的位置開始順時針查找,將數據保存到找到的第一個服務器上。如果超過232仍然找不到服務器,就會保存到第一臺memcached服務器上。
從上面的狀態中添加一臺memcached服務器。余數分布式算法由于保存鍵的服務器會發生巨大變化而影響緩存的命中率,但Consistent Hashing中,只有在continuum上增加服務器的地點逆時針方向的第一臺服務器上的鍵會受到影響。
利用magent實現對memecache的分布式管理,搭建一套memcache集群服務
1、前端php對magent的訪問跟對memcache訪問相同,不需要做任何更改,對于插入的key,magent會把值散列到各個memcache服務上,只操作magent,不用關心后端處理
2、公司項目應用:南北各10臺前端,南北各部署一套magent服務,主要是考慮電信網通的跨網訪問.以北方為例,每個前端安裝memcached服務(大內存機器可以啟動多個服務),每個前端都安裝magent服務,后端掛載全部機器的 memcached服務,啟動參數:
- magent-p 12000 -s 127.0.0.1:8086 -s 127.0.0.2:8086 -s 127.0.0.3:8086.......-s127.0.0.10:8086
所有前端配置都是相同的,任何一個前端只需訪問本地端口的magent,這樣的memcache集群對應用帶來很大便利.
比如項目的基本配置信息,早期策略只能在中控機生成配置文件,同步到各個前端,沒有辦法把配置信息放到緩存中,因為各個前端的memcache是不共享 的,一臺機器緩存更新,其它機器是不更新的,用程序去控制更新,還是存在不穩定因素,而且隨著服務增多,也不便于管理,部署了magent后,就可以解決 這個問題,任何一個前端更新數據=全局更新
這種部署還可以解決的應用:session共享
Magent使用舉例
啟動兩個memcached進程,端口分別為11211和11212:
memcached -m 1 -u root -d -l 127.0.0.1 -p 11211
memcached -m 1 -u root -d -l 127.0.0.1 -p 11212
啟動兩個magent進程,端口分別為10000和11000:
magent -u root -n 51200 -l 127.0.0.1 -p 10000 -s127.0.0.1:11211 -b 127.0.0.1:11212
magent -u root -n 51200 -l 127.0.0.1 -p 11000 -s127.0.0.1:11212 -b 127.0.0.1:11211
-s 為要寫入的memcached, -b 為備份用的memcached。
說明:測試環境用magent和memached的不同端口來實現,在生產環境中可以將magent和memached作為一組放到兩臺服務器上。
也就是說通過magent能夠寫入兩個memcached。
magent使用
1、安裝libevent:
- wget http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz
- tar -xzvf libevent-1.4.13-stable.tar.gz
- cd libevent-1.4.13-stable
- ./configure --prefix=/usr/local/libevent
- make
- make install
2、安裝Memcached:
- wget http://memcached.googlecode.com/files/memcached-1.4.4.tar.gz
- tar -xzvf memcached-1.4.4.tar.gz
- cd memcached-1.4.4
- ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
- make
- make install
- ln -s /usr/local/libevent/lib/libevent-1.4.so.2 /usr/lib/
3、編譯安裝magent:
- mkdir magent
- cp magent-0.5.tar.gz magent
- cd magent
- tar -xzvf magent-0.5.tar.gz
- /sbin/ldconfig
- sed -i "s#LIBS = -levent#LIBS = -levent -lm#g" Makefile
- vi magent.c 添加
- #include <limits.h>
- make
一、使用實例:
- memcached -m 1 -u root -d -l 192.168.1.219 -p 11211
- memcached -m 1 -u root -d -l 192.168.1.219 -p 11212
- memcached -m 1 -u root -d -l 192.168.1.219 -p 11213
- magent -u root -n 51200 -l 192.168.1.219 -p 12000 -s 192.168.1.219:11211 -s 192.168.1.219:11212 -b 192.168.1.219:11213
1、分別在11211、11212、11213端口啟動3個Memcached進程,在12000端口開啟magent代理程序;
2、11211、11212端口為主Memcached,11213端口為備份Memcached;
3、連接上12000的magent,set key1和set key2,根據哈希算法,key1被寫入11212和11213端口的Memcached,key2被寫入11212和11213端口的Memcached;
4、當11211、11212端口的Memcached死掉,連接到12000端口的magent取數據,數據會從11213端口的Memcached取出。
三、整個測試流程:
- # telnet 192.168.1.219 12000
- Trying 1192.168.1.219...
- Connected to 192.168.1。219.
- Escape character is '^]'.
- stats
- memcached agent v0.4
- matrix 1 -> 192.168.1.219:11211, pool size 0
- matrix 2 -> 192.168.1.219:11212, pool size 0
- END
- set key1 0 0 5
- reesun
- STORED
- set key2 0 0 6
- reesun1
- STORED
- quit
- Connection closed by foreign host.
- # telnet 192.168.1.219 11211
- Trying 192.168.1.219...
- Connected to 192.168.1.219.
- Escape character is '^]'.
- get key1
- END
- get key2
- VALUE key2 0 6
- reesun1
- END
- quit
- Connection closed by foreign host.
- # telnet 192.168.1.219 11212
- Trying 192.168.1.219...
- Connected to 1192.168.1.219.
- Escape character is '^]'.
- get key1
- VALUE key1 0 5
- reesun
- END
- get key2
- END
- quit
- Connection closed by foreign host.
- # telnet 192.168.1.219 11213
- Trying 192.168.1.219...
- Connected to 1192.168.1.219.
- Escape character is '^]'.
- get key1
- VALUE key1 0 5
- reesun
- END
- get key2
- VALUE key2 0 6
- reesun1
- END
- quit
- Connection closed by foreign host.
新聞熱點
疑難解答