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

dead_lee發表於2021-09-09

基於memcached官方wiki,寫了幾篇 memcached 內部機制的文章,比如記憶體分配、LRU的工作原理。接下來從應用的角度說說memcached,只有從正確的角度理解,才能更好的應用,否則就會出現很多誤解,比如有時候比較memcached和redis是毫無意義的。

1:記憶體、記憶體、記憶體

memcached是完全基於記憶體操作的,是一個快取系統,從本質它不是一個資料庫系統,也不支援持久化。

既然是記憶體,在使用之前問自己,memcached快取的資料如果丟失,會影響你的業務嗎?

2:分散式系統

memcached本身是一個非常輕量級的服務,不支援主輔同步,也沒有叢集的概念。但為了可擴充套件性,memcached 伺服器端和 memcached 客戶端結合起來可以構成一個分散式系統。

在memcached分散式系統中,各個 memcached 節點之間無須通訊,所以擴充套件性非常好。

3:不支援複雜的操作

和 redis 不一樣的是,memcached 沒有複雜的資料結構(比如佇列、集合),它只能儲存字串型別,也不關心具體儲存什麼,這是它的一個優勢:簡單。但很多人用的時候可能就不爽了,說它比 redis 弱爆了,其實雙方的應用場景不一樣。

當然也可以基於基本命令模擬一些資料結構,這是允許的,但這和memcached無關。

4:原子操作

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

5:效能

memcached 效能高的原因主要在於 libevent 事件機制、多執行緒、全記憶體操作、模型簡單(比如 O(1),儘量避免鎖機制)。

配置相對較高的伺服器,每秒可以處理 200,000+ 的請求,即使在很慢的機器上,每秒處理幾百次也毫無壓力。

memcached 所有的操作都是 O(1),set/get 操作不應該出現滯後,一個請求正常情況下不到 1ms 就能返回,如果遇到 Hang,那可能是連線數過多、產生了 swap、遇到了網路問題。

6:不推薦儲存 session 資料

現在很多業務都用 memcached 儲存 session 資料,在使用之前一定要評估風險,因為 memcached 是基於記憶體的,如果儲存的 session 丟失了,會話使用者就掉線了。

7:不支援名稱空間

memcached 一般針對某個key進行操作,不支援 namespace 功能,原因在於為了實現namespace,會讓系統實現複雜化(比如為了實現過期設定功能)。

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

  • 希望批次刪除某些 key。

  • 如果獲取相關聯資料(比如有多個key),但 memcached 節點非常多,如果這些key根據 Hash 演算法分散儲存到多個節點,那麼獲取的時候效能就會下降。

但很多客戶端模擬實現了namespace功能 ,比如 PHP memcached 擴充套件就有相應的函式,比如 addByKey(),getAllKeys() 等函式,這些後續我再說。

8:Failure or Failover

如果你的應用沒有使用一致性hash演算法或其他的hash演算法,連線某一個memcache節點的時候,如果網路連線超時,或某個節點不能通訊(比如網線被拔了),那麼客戶端呼叫只能選擇 Failure,遇到這樣的情況,可能就要去後端讀取資料了。

如果你的應用使用一致性hash演算法,那麼應該選擇 Failure or Failover?

這裡有一個誤區,一致性 hash 演算法是減少上線或下線伺服器帶來的快取失效問題,本質上不是為了讓客戶端隨時隨地都能獲取到資料。

如果網路連線超時,或某個節點不能通訊(比如網線被拔了),儘量不要選擇自動 Failover,比如三個節點,本來某個 key 對應第一個節點,如果客戶端發現第一個節點不可用,就自動儲存到第二個節點,原因就在於如果第一個節點恢復了,可能獲取到舊的資料(在 Failover 的時候新資料更新到第二個節點)。

根據這一原則,PHP memcached 擴充套件預設是不做 Failover 的,這也是正確的應用方式,如果你實在要 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 本身不支援,它就是一個 key-value 系統,但如果實在想實現list,可以透過兩個辦法:

  • 推薦在啟動的時候配置 -vvv,這樣能夠將所有set的key列印出來,而且是排查問題非常好的方法。

  • 執行 stats cachedump 命令,不過不推薦使用,因為操作比較慢,而且只能拿到區域性的資料。

10:memcached 應用場景?

  • 能快取任何資料,有效減少後端的壓力並提升響應能力。

  • 計算器,比如利用 incr 命令。

  • Rate limiting,非常有用,比如登陸系統可以使用它限制非法登陸。

  • 雖然 memcached 不支援佇列和堆疊,但 append/prepend 命令還是有一定作用的,比如可以實現排行榜。




作者:虞大膽的嘰嘰喳喳
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4686/viewspace-2821290/,如需轉載,請註明出處,否則將追究法律責任。

相關文章