您好,登錄后才能下訂單哦!
講師的博客:https://www.cnblogs.com/wupeiqi/p/5132791.html
如果是要在django里使用Memcache緩存,那么下面都不用看了,直接看django里是怎么用的就好了。
這篇里緩存的章節:https://blog.51cto.com/steed/2104127
Memcached是一個高性能的分布式內存對象緩存系統,用于動態Web應用以減輕數據庫負載。它通過在內存中緩存數據和對象來減少讀取數據庫的次數,從而提高動態、數據庫驅動網站的速度。Memcached基于一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,但是客戶端可以用任何語言來編寫,并通過memcached協議與守護進程通信。
貌似Redis要比Memcached好。不過這兩個都不錯,也都有人在用。仔細比較的話也確實是各有優劣的,比如Redis只使用單核,而Memcached可以使用多核。
具體看這篇吧:https://www.oschina.net/news/26691/memcached-timeout
Memcached官網:http://memcached.org/
關于安裝,可以看這里:https://github.com/memcached/memcached/wiki/Install
可以直接用yum安裝:
$ yum install libevent-devel
可能還要安裝這個,但是上面的yum安裝時并不在依賴關系里:
$ yum install libevent-devel
上面這個我還沒有安裝。
啟動運行
$ memcached -d -m 10 -u root -l 10.211.55.4 -p 12000 -c 256 -P /tmp/memcached.pid
啟動選項:
<num>
: TCP監聽端口(default: 11211)<num>
: UDP監聽端口(default: 11211, 0 is off)<file>
: UNIX套接字路徑偵聽<mask>
: UNIX套接字的訪問掩碼,八進制(默認值:0700)<addr>
: 偵聽接口地址默認為所有地址,可以指定主機加端口可以使用逗號分隔多個地址<username>
: 指定運行用戶<num>
: 最大內存(默認為64 MB)<num>
: 最大同時連接數默認為1024<file>
: 指定PID文件,只與-d選擇一起使用<factor>
: 塊大小生長因子,默認值為1.25<bytes>
: 為鍵值標志的最小空間,默認為48<char>
: 使用<char>
作為密鑰前綴和IDS之間的分隔符<num>
: 使用的線程數,默認為4<num>
: 設置積壓隊列限制默認值1024上面如果用后臺啟動了之后無法關閉,可以先找到守護進程的PID,然后kill掉:
$ ps -aux
$ kill -9 PID
開放防火墻:
$ firewall-cmd --permanent --add-port=11211/tcp
$ firewall-cmd --reload
直接使用pip安裝:
pip install python-memcached
第一次使用:
import memcache
mc = memcache.Client(['192.168.3.108:11211'], debug=True)
mc.set('k1', 'v1')
ret = mc.get('k1')
print(ret)
這里有個參數,debug=True表示運行出現錯誤時,顯示錯誤信息,上線后移除該參數。
運行上面的代碼前先確認啟動了服務端的Memcached,用如下的命令開啟吧:
$ memcache -u root -vv
此時,在運行上面的代碼,就可以進行設置值和取值的操作了。
python-memcached模塊原生支持集群操作。這里單講上面的生成memcache.Client實例的這條命令。
實例化的時候傳入的第一個參數,是一個列表。既然是列表,就可以傳入多個,這樣是實現了集群的操作:
mc = memcache.Client(['192.168.3.108:11211', '192.168.3.109:11211', '192.168.3.110:11211'])
另外,列表中的元素可以是一個元組,元組的第一個元素就是上面的IP地址和端口,第二個元素是數字表示權重:
mc = memcache.Client([('192.168.3.108:11211', 1), ('192.168.3.109:11211', 3), ('192.168.3.110:11211', 4)])
根據算法將用戶要存的key轉換成一個數字,將數字和主機列表的長度求值,如此就知道該連接哪一臺主機了。加了權重值,就是增加這個主機在主機列表里出現的次數。
這里操作的命令比較簡單,所以簡單了解一下有哪些命令可以操作就好了。
add
添加一條鍵值對,如果是已經存在的key,會返回False:
res = mc.add('k2', 'v2')
print(res) # 設置成功,返回True
res = mc.add('k2', 'value2')
print(res) # 設置失敗,返回False
這里重復add同一個key,應該是會產生異常的,不過應該是被底層捕獲的,不會導致程序崩潰。如果開啟了debug,那么會把異常打印出來。
replace
修改某個key的值,如果key不存在,則異常:
mc.replace('k1', 'value1')
這里的異常和上面add的情況是一樣的。set操作就相當于是 add + replace 。
set 和 set_multi
set : 設置一個鍵值對,如果key不存在,則創建,如果key存在,則修改
set_multi : 設置多個鍵值對,此時要傳入一個字典
res = mc.set('k1', 'v1')
print(res) # 設置成功,會返回True
mc.set_multi({'k11': 'v11', 'k12': 'v12', 'k13': 'v13'})
set的時候可以直接傳數字,應該是會自動幫我們傳成字符串保存的:
mc.set('n1', 100)
print(mc.get('n1'))
get 和 get_multi
get : 獲取一個鍵值對
get_multi : 獲取多個鍵值對,傳入一個列表,返回字典
items = mc.get_multi(['k11', 'k12', 'k13'])
print(items)
delete 和 delete_multi
delete : 刪除指定的一個鍵值對,可以刪除不存在的鍵值對
delete_multi : 刪除指定的多個鍵值對,如果key不存在,會異常
mc.delete('k1')
mc.delete_multi(['k11', 'k12', 'k13'])
append 和 prepend
append : 修改指定key的值,在該字符串后面追加內容
prepend : 修改指定key的值,在該字符串前面插入內容
在Memcached里只有一個數據格式,就是字符串,所以這里是對字符串的操作:
mc.set('s1', 'TEST')
print(mc.get('s1'))
mc.append('s1', ' after')
print(mc.get('s1'))
mc.prepend('s1', 'before ')
print(mc.get('s1'))
decr 和 incr
incr : 自增,將某個值增加N,默認加1
decr : 自減,將某個值減少N,默認減1
這里能操作的只能是能是數字形式的字符串,否則程序會拋出異常。這個異常應該是客戶端計算是產生的,直接會導致程序崩潰:
mc.set('n1', '123')
print(mc.get('n1'))
mc.incr('n1')
print(mc.get('n1'))
mc.incr('n1', 100)
print(mc.get('n1'))
設置超時時間
上面的設置值的操作:set、 set_multi、add、replace,都是可以設置超時時間的。通過time參數,單位是秒:
mc.set('k1', 'v1', time=2)
time.sleep(1)
print(mc.get('k1')) # 返回設置的值,v1
time.sleep(1)
print(mc.get('k1')) # 超時,返回None
gets 和 cas
這里提供的方法,是為了解決同時修改某個數據的時候,導致數據一致性問題。
比如A取出了某個值假設是1000,B也取出了這個值1000。A和B都要把數據減1然后回寫回去。此時A和B都會嘗試把999寫回去。這樣最終這個數字就不對了。應該是A和B都把數字減少了1,此時最終的數值應該是998。
用這里的gets和cas操作,就可以發生上面的問題。要讓這兩個命令有效果,需要在創建客戶端實例的時候再加一個參數cache_cas=True:
mc = memcache.Client(['192.168.3.108:11211'], debug=True, cache_cas=True)
下面是演示這種沖突情況的代碼:
# s2a.py
import memcache
mc = memcache.Client(['192.168.3.108:11211'], debug=True, cache_cas=True) # 注意參數
mc.set('count', 1000) # 設置一個默認值
n = mc.gets('count')
input("%s>>>" % n) # 獲取到值之后,先暫停
res = mc.cas('count', n-1) # 把計算后的新的值寫回
print(res, mc.get('count'))
# s2b.py
import memcache
mc = memcache.Client(['192.168.3.108:11211'], debug=True, cache_cas=True)
n = mc.gets('count')
input("%s>>>" % n)
res = mc.cas('count', n-1)
print(res, mc.get('count'))
先運行s2a.py,然后再運行s2b.py。此時2個程序都會在獲取到值之后暫停。隨便讓一個程序繼續,寫回最新的數據。當第二個程序寫回的時候就會發生錯誤,返回False。此時你就知道這里的操作失敗了。知道失敗了,就再重新執行一個gets和cas的操作應該就可以了。失敗返回如下:
1000>>>
MemCached: while expecting 'STORED', got unexpected response 'EXISTS'
False 999
這里應該是一個樂觀鎖的實現。總之就是cas之后檢查返回值判斷是否成功。如果不成功,表示之前執行的時候有沖突,那么再執行一次。
另外其實數字的加減,是不需要這樣做的。對于數字,使用decr 和 incr就不會發生上面的那種沖突的情況。不過如果是字符串操作,比如在前后添加內容,就無法避免了。另外或許處理數字還有其他更復雜的情況,只是還沒遇到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。