複製程式碼
介紹
memcached是高效能多執行緒的分散式快取k-v資料庫。Memcached是記憶體中的鍵值資料庫,用於快取從資料庫呼叫,API呼叫的任意小塊資料(字串,物件)。可以通過快取減輕資料庫或IO的負載,從而增加應用的效能。
核心特徵和原理
- 分散式
使用一致性hash來進行分散式節點選擇,進行資料均衡和負載均衡。
- 快取
不持久化。採用LRU(最近最少使用)回收空間。
- k-v資料庫
功能單一的k-v資料庫。
分散式架構
支援。
使用環形hash空間,對server節點和key都進行hash(32位元的迴圈冗餘校驗(CRC-32)計算鍵值),並且選擇雙方hash值最靠近的server節點。解決普通取模造成大量遷移的情況。
通過對物理節點虛擬更多節點,比如‘10.0.0.0-1~10.0.0.1-n’,解決server過少導致不均衡的問題。如下(擴容前)
如下(擴容後)
memcached需要在客戶端維護節點列表,並進行業務分發。
快取策略
- 使用LRU(最近最少使用)回收空間。
LRU(least recently used)最近最少使用。假設 序列為 4 3 4 2 3 1 4 2物理塊有3個 則首輪 4調入記憶體 4次輪 3調入記憶體 3 4之後 4調入記憶體 4 3之後 2調入記憶體 2 4 3之後 3調入記憶體 3 2 4之後 1調入記憶體 1 3 2(因為最少使用的是4,所以丟棄4)之後 4調入記憶體 4 1 3(原理同上)最後 2調入記憶體 2 4 1複製程式碼
- 支援每個kv對的有效時限。
Kv的儲存有效時限可以在客戶端設定並作為引數傳遞給服務端
- 偷懶替代法。
服務端採用分類chunk定長記錄,因此刪除記錄可以只做個標記,可以通過覆蓋來回收並複用空間。
- 比較優秀的記憶體管理
相比redis等,應該有更高的記憶體利用率。
k-v資料庫
功能單一的k-v資料庫。
基本操作
Add
功能:往記憶體增加一條新的快取記錄
Delete
功能:從記憶體刪除一條快取記錄
Get
功能:從記憶體中提取一條快取記錄
Replace
功能:替換記憶體中的快取記錄
Set
功能:設定或者替換記憶體中的快取記錄,相當於add + replace的功能。
複製程式碼
原子操作和事務性策略
支援incr,decr,cas等操作
持久化策略---現狀
不支援。當機會丟失資料
需要配合mysql,mariaDb等進行資料持久化設計。或者memcachedb?效能可能會大大降低。
雖然不能持久化,但是目標單純,功能單一也有優點,可以避免額外設計帶來的問題。比如持久化涉及到io的訪問,有時候系統io的阻塞,可能會導致快取效能受影響。
持久化策略---快取資料一致性策略
- 查詢策略
先查詢cache,miss時查詢db,並寫入cache。
- 寫入策略
採用writethrough策略。寫db成功後,失效cache(寫只寫db;更新資料先更新db,再失效cache)
1,writethrough。如果配合高效能儲存。可以先同步到db,如果成功則讓快取失效。(假設刪除快取不會失敗,或極小可能性失敗)。如果刪除快取失敗(cache miss也算成功,其他不可預期失敗算失敗),則回退db操作(此間,快取命中優先從快取讀取資料)。
2,writeback。先寫入(刪除)快取,再寫入db。在高併發的情況,容易出現資料不一致的場景。比如刪除快取後,寫入db成功前,使用者發起讀請求,會導致讀取到舊資料,從而引起資料不一致。
3,readonly。不適用。
- 其他需要考慮的併發性問題
1,執行緒1查詢cache;執行緒2寫db,並失效cache(非原子,非同步寫db),寫cache
2,事務性問題:一個事務包含多個db操作,db1操作成功,寫cache1成功,寫db2操作失敗,事務回滾,db2資料回滾,cache1無法回滾,導致髒資料。
3,併發性問題:兩個更新操作併發,如更新名字,並且cache中key以名字為關鍵字,更新一寫db成功,寫快取XXXX_name1成功。更新二寫db成功,寫快取XXXX_name2成功。導致cache髒資料。(多讀少寫情況下,考慮樂觀鎖加version解決-類似CAS,如下圖)
效能
待測試。
據稱在高速網路下,memcached可以輕鬆處理每秒200,000個以上的請求。並且消耗更少的記憶體。
貌似不支援組合請求,或合併批量處理。
從其他找到的一個測試如下:memcached貌似不如redis。另外20k以上的大資料會導致請求數顯著下降。
其他
- 高可用和冗餘設計
不支援。當機後資料會丟失,需要配合其他設計。
- 併發策略
多執行緒充分利用多核處理器的優勢。
資料通過一致性hash分片儲存到不同節點。
- 其他功能
功能較單一。比如只支援單一的資料結構
- 可維護性
一般
- 擴充套件設計
一致性hash可以保證擴容或故障時,影響較小的資料。
- 商業成熟度
比較成熟。很流行,被廣泛使用。
通過memcached的客戶端實現分散式,支援多種語言的客戶端,包括c,java等等。
- 程式碼量
1.47大概只有1萬行左右。程式碼可讀性不如redis。
- 開源協議
BSD開源協議
- 依賴
依賴libevent
擴充套件
原作者開發go的替代版groupcache
https://www.csdn.net/article/2013-07-30/2816399-groupcache-readme-go
優化
記憶體要足夠避免使用swap減低效能,並儘量節點間記憶體一致。
總結
- key長度有限制。
儲存的key不超過250位元組,資料不能超過1M,最好小於10K。因為資料太大容易導致LRU淘汰比較嚴重,而且Memcached是CPU密集型的程式,容易降低QPS。
- 支援的資料型別單一
如果需要序列化和反序列化,需要考慮額外開銷
- 不使用場景
寫頻繁的資料不適合使用快取。
沒有持久化和副本。任意節點掉電(非多臺整系統掉電)都會導致資料丟失。對一致性,實時性,安全性要求極高的業務,可能不適合快取。
- 多執行緒開銷
在memcached多執行緒環境下使用CAS,在高併發上高QPS的情況下可能效能會顯著降低。
參考資料
http://www.quweiji.com/memcachedb-tokyo-tyrant-redis-performance-test/
http://www.cnblogs.com/hjwublog/p/5625275.html
http://ruturaj.net/redis-memcached-tokyo-tyrant-and-mysql-comparision/
https://stackoverflow.com/questions/2873249/is-memcached-a-dinosaur-in-comparison-to-redis/8494397#8494397
作者:luciham@gmail.com
出處:https://juejin.im/user/5a4e11d96fb9a01c9f5b3367
本文歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線。複製程式碼