Memcached是一個高性能的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。它通過在內存中緩存數據和對象減少讀取數據庫的次數,從而提高動態、數據庫驅動網站的速度。Memcached基於一個存儲鍵/值的hash map。其守護進程(daemon)是用C語言寫的,但是客戶端可以用任何語言來編寫,並通過memcached協議與守護進程通信。
安裝
cd /usr/local/src
wget http://memcached.org/latest
tar -zxvf memcached-1.x.x.tar.gz
cd memcached-1.x.x
./configure && make && make test && make install
啓動
memcached -d -m 10 -u root -l 127.0.0.1 -p 12000 -c 256 -P /export/servers/memcache/logs/memcache.pid
-p 指定端口號(默認11211)
-m 指定最大使用內存大小(默認64MB)
-t 線程數(默認4)
-l 連接的IP地址, 默認是本機
-d 以後臺守護進程的方式啓動
-c 最大同時連接數,默認是1024
-P 制定memecache的pid文件
-h 打印幫助信息
ps -ef檢查memcache是否啓動,檢查端口號
Python操作memcache集羣
python-memcachd模塊原生支持集羣操作,其原理是在內存維護一個主機列表,且集羣中主機的權重值和主機在列表中重複出現的次數成正比。
主機 權重
1.1.1.1 1
1.1.1.2 2
1.1.1.3 1
那麼在內存中主機列表爲:host_list=['1.1.1.1','1.1.1.2','1.1.1.2','1.1.1.3',]
例子:
mc = memcache.Client([('1.1.1.1:12000', 1), ('1.1.1.2:12000', 2), ('1.1.1.3:12000', 1)], debug=True)
mc.set('k1', 'v1')
如果用戶要在內存中創建一個鍵值對(如:k1 = “v1”),那麼要執行以下步驟:
根據算法將k1轉換成一個數字;
將數字和主機列表長度求餘數,得到一個值N(0 <= N < 列表長度);
在主機列表中根據第2步得到的值爲索引獲取主機,例如:host_list[N];
連接將第3步中獲取的主機,將k1 = 'v1'放置在該服務器的內存中。
上面例子我們通過調用memcache模塊來實現對memcached進行存取數據,debug=True表示運行中出現錯誤時,顯示錯誤信息,上線後移除該參數。
常用操作
add方法
添加一條鍵值對,如果已經存在的key,重複執行add操作會報異常。
例子:
import memcache
mc = memcache.Client(['192.168.1.1:11211'], debug=True)
#mc.set("foo", "bar")
#ret = mc.get("foo")
mc.add('k1','v1')
mc.add('k1','v1')
#print(ret)
replace方法
replace修改某個key的值,如果key不存在,則異常。
例子:
import memcache
mc = memcache.Client(['192.168.1.1:11211'], debug=True)
#mc.set("foo", "bar")
#ret = mc.get("foo")
mc.add('k1','v1')
#mc.add('k1','v1')
#print(ret)
mc.replace("k1", "666")
print(mc.get("k1"))
輸出:
666
set和set_multi方法
set:設置一個鍵值對,如果key不存在,則創建,如果key存在,則修改;
set_multi:設置多個鍵值對,如果key不存在,則創建,如果key存在,則修改。
例子:
import memcache
mc = memcache.Client(['192.168.1.1:11211'], debug=True)
mc.set("k10", "v10")
mc.set_multi({"k11": "v11", "k12": "v12"})
set方法和add方法的區別
set = add + replace
add 方法:add方法用於向memcache服務器添加一個要緩存的數據。如果memcache服務器中已經存在要存儲的key,此時add方法調用失敗。
set 方法:set方法用於設置一個指定key的緩存內容,set方法是add方法和replace方法的集合體。如果要設置的key不存在時,則set方法與add方法的效果一致;如果要設置的key已經存在時,則set方法與replace方法效果一樣。
replace方法: replace方法用於替換一個指定key的緩存內容,如果key不存在則返回false
delete和delete_multi方法
delete:在Memcached中刪除指定的一個鍵值對;
delete_multi:在Memcached中刪除指定的多個鍵值對。
例子:
import memcache
mc = memcache.Client(['192.168.1.1:11211'], debug=True)
#mc.set("k10", "v10")
#mc.set_multi({"k11": "v11", "k12": "v12"})
mc.delete("k10")
mc.delete_multi(["k11", "k12"])
get和get_multi方法
get : 獲取一個鍵值對;
get_multi:獲取多個鍵值對。
例子:
import memcache
mc = memcache.Client(['192.168.48.128:11211'], debug=True)
mc.set("k10", "v10")
mc.set_multi({"k11": "v11", "k12": "v12"})
#mc.delete("k10")
#mc.delete_multi(["k11", "k12"])
val = mc.get('k1')
print(val)
item_dict = mc.get_multi(['k11', 'k12'])
print(item_dict)
append和prepend方法
append:修改指定key的值,在該值後面追加內容;
prepend:修改指定key的值,在該值前面插入內容。
例子:
import memcache
mc = memcache.Client(['192.168.10.128:12000'], debug=True)
mc.append('k1','after')
val1 = mc.get('k1')
print(val1)
mc.prepend('k1','brefore')
val2 = mc.get('k1')
print(val2)
輸出:
v1afterafter
breforev1afterafter
incr:自增,將Memcached中的某一個值增加N(N默認爲1);
decr:自減,將Memcached中的某一個值減少N(N默認爲1)。
例子:
import memcache
mc = memcache.Client(['192.168.10.128:12000'], debug=True)
#默認自增1,第二個參數爲增加的n
mc.set('k1','777')
#mc.incr('k1')
mc.incr('k1',10)
val1 = mc.get('k1')
print(val1)
mc.decr('k1',20)
val2 = mc.get('k1')
print(val2)
輸出:
787 #自增後的結果
767 #自減後的結果
gets和cas:
如商城商品剩餘個數,假設改值保存在memcache中,product_count =9000
A用戶刷新頁面從memcache中讀取到product_count = 900
B用戶刷新頁面從memcache中讀取到product_count = 900
如果A、B用戶均購買商品:
A用戶修改商品剩餘個數 product_count = 899
B用戶修改商品剩餘個數product_count = 899
如此一來緩存內的數據便不再正確,兩個用戶購買商品後,商品剩餘還是899,如果使用python的set和get來操作以上過程,那麼程序就會如上述所示情況,數據不準確。
如果想要避免此情況的發生,只要使用gets和cas即可
例子:
import memcache
mc = memcache.Client(['192.168.10.128:12000'], debug=True)
v = mc.gets('product_count')
print(v)
#如果有人在gets之後和cas之前修改了product_count,那麼下面的設置將會執行失敗,拋出異常,從而避免非正常數據的產出
v1 = mc.cas('product_count',"899")
print(v1)
輸出:
899
True
本質上每次執行gets時,會從memcache中獲取一個自增的數字,通過cas去修改gets的值時,會攜帶之前獲取的自增值和memcache中的自增值進行比較,如果相等,則可以提交,如果不相等,那表示在gets和cas執行之間,又有其他人執行了gets(獲取了緩衝的指定值),如此一來有可能出現非正常數據,則不允許修改。