至於Memcache的安裝配置,我們就不講了,以前有兩篇比較好的文章如下:
windows 64位系統配置安裝Memcache緩衝 http://www.111cn.net/sys/Windows/61708.htm
Linux系統Memcache安裝配置詳解 http://www.111cn.net/sys/linux/81920.htm
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:
<?phpsession_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 libeventlrwxrwxrwx 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.lalrwxrwxrwx 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是一款開源的memcachedProxy 伺服器軟體
地址: http://code.google.com/p/memagent/
安裝magent到/usr/local/下
cd /usr/localmkdir magentcd magent/wgethttp://memagent.googlecode.com/files/magent-0.5.tar.gztar zxvf magent-0.5.tar.gz/sbin/ldconfigsed -i "s/LIBS = -levent/LIBS =-levent -lm/g" Makefilemake
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.