Memcached 是一個高性能的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。它經過在內存中緩存數據和對象來減小讀取數據庫的次數,從而提升動態、數據庫驅動網站的速度。Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,可是客戶端能夠用任何語言來編寫,並經過memcached協議與守護進程通訊。python
Memcached安裝和基本使用
Memcached安裝:算法
1
2
3
4
5
6
7
8
|
wget http:
/
/
memcached.org
/
latest
tar
-
zxvf memcached
-
1.x
.x.tar.gz
cd memcached
-
1.x
.x
.
/
configure && make && make test && sudo make install
PS:依賴libevent
yum install libevent
-
devel
apt
-
get install libevent
-
dev
|
啓動Memcached數據庫
1
2
3
4
5
6
7
8
9
10
|
memcached
-
d
-
m
10
-
u root
-
l
10.211
.
55.4
-
p
12000
-
c
256
-
P
/
tmp
/
memcached.pid
參數說明:
-
d 是啓動一個守護進程
-
m 是分配給Memcache使用的內存數量,單位是MB
-
u 是運行Memcache的用戶
-
l 是監聽的服務器IP地址
-
p 是設置Memcache監聽的端口,最好是
1024
以上的端口
-
c 選項是最大運行的併發鏈接數,默認是
1024
,按照你服務器的負載量來設定
-
P 是設置保存Memcache的pid文件
|
Memcached命令緩存
1
2
3
|
存儲命令:
set
/
add
/
replace
/
append
/
prepend
/
cas
獲取命令: get
/
gets
其餘命令: delete
/
stats..
|
Python操做Memcached
安裝API服務器
1
2
|
python操做Memcached使用Python
-
memcached模塊
下載安裝:https:
/
/
pypi.python.org
/
pypi
/
python
-
memcached
|
一、第一次操做併發
1
2
3
4
5
6
|
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
)
mc.
set
(
"foo"
,
"bar"
)
ret
=
mc.get(
'foo'
)
print
ret
|
Ps:debug = True 表示運行出現錯誤時,現實錯誤信息,上線後移除該參數。app
二、天生支持集羣分佈式
python-memcached模塊原生支持集羣操做,其原理是在內存維護一個主機列表,且集羣中主機的權重值和主機在列表中重複出現的次數成正比memcached
1
2
3
4
5
6
7
|
主機 權重
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"
, ]
|
若是用戶根據若是要在內存中建立一個鍵值對(如:k1 = "v1"),那麼要執行一下步驟:post
- 根據算法將 k1 轉換成一個數字
- 將數字和主機列表長度求餘數,獲得一個值 N( 0 <= N < 列表長度 )
- 在主機列表中根據 第2步獲得的值爲索引獲取主機,例如:host_list[N]
- 鏈接 將第3步中獲取的主機,將 k1 = "v1" 放置在該服務器的內存中
代碼實現以下:
1
2
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'
)
|
三、add
添加一條鍵值對,若是已經存在的 key,重複執行add操做異常
1
2
3
4
5
6
7
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
)
mc.add(
'k1'
,
'v1'
)
# mc.add('k1', 'v2') # 報錯,對已經存在的key重複添加,失敗!!!
|
四、replace
replace 修改某個key的值,若是key不存在,則異常
1
2
3
4
5
6
7
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
)
# 若是memcache中存在kkkk,則替換成功,不然一場
mc.replace(
'kkkk'
,
'999'
)
|
五、set 和 set_multi
set 設置一個鍵值對,若是key不存在,則建立,若是key存在,則修改
set_multi 設置多個鍵值對,若是key不存在,則建立,若是key存在,則修改
1
2
3
4
5
6
7
8
9
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
)
mc.
set
(
'key0'
,
'wupeiqi'
)
mc.set_multi({
'key1'
:
'val1'
,
'key2'
:
'val2'
})
|
六、delete 和 delete_multi
delete 在Memcached中刪除指定的一個鍵值對
delete_multi 在Memcached中刪除指定的多個鍵值對
1
2
3
4
5
6
7
8
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
)
mc.delete(
'key0'
)
mc.delete_multi([
'key1'
,
'key2'
])
|
七、get 和 get_multi
get 獲取一個鍵值對
get_multi 獲取多一個鍵值對
1
2
3
4
5
6
7
8
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
)
val
=
mc.get(
'key0'
)
item_dict
=
mc.get_multi([
"key1"
,
"key2"
,
"key3"
])
|
八、append 和 prepend
append 修改指定key的值,在該值 後面 追加內容
prepend 修改指定key的值,在該值 前面 插入內容
1
2
3
4
5
6
7
8
9
10
11
12
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
)
# k1 = "v1"
mc.append(
'k1'
,
'after'
)
# k1 = "v1after"
mc.prepend(
'k1'
,
'before'
)
# k1 = "beforev1after"
|
九、decr 和 incr
incr 自增,將Memcached中的某一個值增長 N ( N默認爲1 )
decr 自減,將Memcached中的某一個值減小 N ( N默認爲1 )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
)
mc.
set
(
'k1'
,
'777'
)
mc.incr(
'k1'
)
# k1 = 778
mc.incr(
'k1'
,
10
)
# k1 = 788
mc.decr(
'k1'
)
# k1 = 787
mc.decr(
'k1'
,
10
)
# k1 = 777
|
十、gets 和 cas
如商城商品剩餘個數,假設改值保存在memcache中,product_count = 900
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 便可,如:
1
2
3
4
5
6
7
8
9
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import
memcache
mc
=
memcache.Client([
'10.211.55.4:12000'
], debug
=
True
, cache_cas
=
True
)
v
=
mc.gets(
'product_count'
)
# ...
# 若是有人在gets以後和cas以前修改了product_count,那麼,下面的設置將會執行失敗,剖出異常,從而避免非正常數據的產生
mc.cas(
'product_count'
,
"899"
)
|
Ps:本質上每次執行gets時,會從memcache中獲取一個自增的數字,經過cas去修改gets的值時,會攜帶以前獲取的自增值和memcache中的自增值進行比較,若是相等,則能夠提交,若是不想等,那表示在gets和cas執行之間,又有其餘人執行了gets(獲取了緩衝的指定值), 如此一來有可能出現非正常數據,則不容許修改。