正確理解memcached,才能更好的使用

基于memcached官方wiki,寫了幾篇 memcached 內(nèi)部機(jī)制的文章,比如內(nèi)存分配、LRU的工作原理。接下來(lái)從應(yīng)用的角度說(shuō)說(shuō)memcached,只有從正確的角度理解,才能更好的應(yīng)用,否則就會(huì)出現(xiàn)很多誤解,比如有時(shí)候比較memcached和redis是毫無(wú)意義的。

1:內(nèi)存、內(nèi)存、內(nèi)存

memcached是完全基于內(nèi)存操作的,是一個(gè)緩存系統(tǒng),從本質(zhì)它不是一個(gè)數(shù)據(jù)庫(kù)系統(tǒng),也不支持持久化。

既然是內(nèi)存,在使用之前問自己,memcached緩存的數(shù)據(jù)如果丟失,會(huì)影響你的業(yè)務(wù)嗎?

2:分布式系統(tǒng)

memcached本身是一個(gè)非常輕量級(jí)的服務(wù),不支持主輔同步,也沒有集群的概念。但為了可擴(kuò)展性,memcached 服務(wù)器端和 memcached 客戶端結(jié)合起來(lái)可以構(gòu)成一個(gè)分布式系統(tǒng)。

在memcached分布式系統(tǒng)中,各個(gè) memcached 節(jié)點(diǎn)之間無(wú)須通信,所以擴(kuò)展性非常好。

3:不支持復(fù)雜的操作

和 redis 不一樣的是,memcached 沒有復(fù)雜的數(shù)據(jù)結(jié)構(gòu)(比如隊(duì)列、集合),它只能存儲(chǔ)字符串類型,也不關(guān)心具體存儲(chǔ)什么,這是它的一個(gè)優(yōu)勢(shì):簡(jiǎn)單。但很多人用的時(shí)候可能就不爽了,說(shuō)它比 redis 弱爆了,其實(shí)雙方的應(yīng)用場(chǎng)景不一樣。

當(dāng)然也可以基于基本命令模擬一些數(shù)據(jù)結(jié)構(gòu),這是允許的,但這和memcached無(wú)關(guān)。

4:原子操作

memcached 所有操作都是 O(1) ,都是原子操作,同一時(shí)間操作多個(gè) set 不會(huì)有任何的影響。

5:性能

memcached 性能高的原因主要在于 libevent 事件機(jī)制、多線程、全內(nèi)存操作、模型簡(jiǎn)單(比如 O(1),盡量避免鎖機(jī)制)。

配置相對(duì)較高的服務(wù)器,每秒可以處理 200,000+ 的請(qǐng)求,即使在很慢的機(jī)器上,每秒處理幾百次也毫無(wú)壓力。

memcached 所有的操作都是 O(1),set/get 操作不應(yīng)該出現(xiàn)滯后,一個(gè)請(qǐng)求正常情況下不到 1ms 就能返回,如果遇到 Hang,那可能是連接數(shù)過(guò)多、產(chǎn)生了 swap、遇到了網(wǎng)絡(luò)問題。

6:不推薦存儲(chǔ) session 數(shù)據(jù)

現(xiàn)在很多業(yè)務(wù)都用 memcached 存儲(chǔ) session 數(shù)據(jù),在使用之前一定要評(píng)估風(fēng)險(xiǎn),因?yàn)?memcached 是基于內(nèi)存的,如果存儲(chǔ)的 session 丟失了,會(huì)話用戶就掉線了。

7:不支持命名空間

memcached 一般針對(duì)某個(gè)key進(jìn)行操作,不支持 namespace 功能,原因在于為了實(shí)現(xiàn)namespace,會(huì)讓系統(tǒng)實(shí)現(xiàn)復(fù)雜化(比如為了實(shí)現(xiàn)過(guò)期設(shè)置功能)。

但命名空間的作用卻非常大,比如以下需求:

  • 希望批量刪除某些 key。
  • 如果獲取相關(guān)聯(lián)數(shù)據(jù)(比如有多個(gè)key),但 memcached 節(jié)點(diǎn)非常多,如果這些key根據(jù) Hash 算法分散存儲(chǔ)到多個(gè)節(jié)點(diǎn),那么獲取的時(shí)候性能就會(huì)下降。

但很多客戶端模擬實(shí)現(xiàn)了namespace功能 ,比如 PHP memcached 擴(kuò)展就有相應(yīng)的函數(shù),比如 addByKey(),getAllKeys() 等函數(shù),這些后續(xù)我再說(shuō)。

8:Failure or Failover

如果你的應(yīng)用沒有使用一致性hash算法或其他的hash算法,連接某一個(gè)memcache節(jié)點(diǎn)的時(shí)候,如果網(wǎng)絡(luò)連接超時(shí),或某個(gè)節(jié)點(diǎn)不能通信(比如網(wǎng)線被拔了),那么客戶端調(diào)用只能選擇 Failure,遇到這樣的情況,可能就要去后端讀取數(shù)據(jù)了。

如果你的應(yīng)用使用一致性hash算法,那么應(yīng)該選擇 Failure or Failover?

這里有一個(gè)誤區(qū),一致性 hash 算法是減少上線或下線服務(wù)器帶來(lái)的緩存失效問題,本質(zhì)上不是為了讓客戶端隨時(shí)隨地都能獲取到數(shù)據(jù)。

如果網(wǎng)絡(luò)連接超時(shí),或某個(gè)節(jié)點(diǎn)不能通信(比如網(wǎng)線被拔了),盡量不要選擇自動(dòng) Failover,比如三個(gè)節(jié)點(diǎn),本來(lái)某個(gè) key 對(duì)應(yīng)第一個(gè)節(jié)點(diǎn),如果客戶端發(fā)現(xiàn)第一個(gè)節(jié)點(diǎn)不可用,就自動(dòng)存儲(chǔ)到第二個(gè)節(jié)點(diǎn),原因就在于如果第一個(gè)節(jié)點(diǎn)恢復(fù)了,可能獲取到舊的數(shù)據(jù)(在 Failover 的時(shí)候新數(shù)據(jù)更新到第二個(gè)節(jié)點(diǎn))。

根據(jù)這一原則,PHP memcached 擴(kuò)展默認(rèn)是不做 Failover 的,這也是正確的應(yīng)用方式,如果你實(shí)在要 Failover,可以使用下面的代碼。

$memcache = new Memcached;
$memcache->setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT);
$memcache->setOption(Memcached::OPT_SERVER_FAILURE_LIMIT, 1);
$memcache->setOption(Memcached::OPT_AUTO_EJECT_HOSTS,true);
$memcache->addServer('localhost', 11212);
$memcache->addServer('localhost', 11213);
$memcache->set("abc",1);
echo $memcache->get("abc");
print_r($memcache->getResultMessage());

9:能不能list所有的keys

不能,memcached 本身不支持,它就是一個(gè) key-value 系統(tǒng),但如果實(shí)在想實(shí)現(xiàn)list,可以通過(guò)兩個(gè)辦法:

  • 推薦在啟動(dòng)的時(shí)候配置 -vvv,這樣能夠?qū)⑺衧et的key打印出來(lái),而且是排查問題非常好的方法。
  • 運(yùn)行 stats cachedump 命令,不過(guò)不推薦使用,因?yàn)椴僮鞅容^慢,而且只能拿到局部的數(shù)據(jù)。

10:memcached 應(yīng)用場(chǎng)景?

  • 能緩存任何數(shù)據(jù),有效減少后端的壓力并提升響應(yīng)能力。
  • 計(jì)算器,比如利用 incr 命令。
  • Rate limiting,非常有用,比如登陸系統(tǒng)可以使用它限制非法登陸。
  • 雖然 memcached 不支持隊(duì)列和堆棧,但 append/prepend 命令還是有一定作用的,比如可以實(shí)現(xiàn)排行榜。

11:一些小技巧

(1)Zero byte values

如果你只是要使用 memcached 的key ,其對(duì)應(yīng)的value沒有任何價(jià)值,那么為了減少內(nèi)存的使用,可以設(shè)置0字節(jié)長(zhǎng)的值。

(2)盡量減少 key 長(zhǎng)度,有效利用內(nèi)存。

(3)有效利用鎖機(jī)制,比如 add 命令,專門寫過(guò)一篇文章介紹過(guò)《使用Memcached實(shí)現(xiàn)抽獎(jiǎng)活動(dòng)》

memcached 相關(guān)文章:


我的書《深入淺出HTTPS:從原理到實(shí)戰(zhàn)》,如果覺得寫的還可以,歡迎在豆瓣做個(gè)評(píng)論;也可以關(guān)注我的公眾號(hào)(ID:yudadanwx,虞大膽的嘰嘰喳喳)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容