Memcached Keys Expirations

首先必需說明 Memcached 使用鍵值過期策略,是使用 lazy expiry of items,Memcached 並會不主動去刪除鍵值。當數據容量用完MemCached分配的內存後,就會基於LRU(Least Recently Used)算法清理失效的緩存數據(放入數據時可設置失效時間),或者清理最近最少使用的緩存數據,然後放入新的數據。另外也要必需提到 LRU算法不是針對全局的,是針對特定 slab class的。

Jerry’s Notes
What’s next?
5 min readMar 23, 2022

--

Memcached Keys Expirations

Memcached does lazy expiry of items. If you store an item and it expires, it sits in the LRU cache at its position until it falls to the end and is reused. Memcached will also remove key from memory when you try to fetch it.

Eviction and LRU in Memcached are not Global, its ‘per slab class’. Items are evicted if there are no expired items, the slab class is completely out of free chunks, and there are no free pages to assign to a slab class for new items.

Q: How keys are selected? When expired keys are deleted?

■ Memcached does lazy expiry of items. If you store an item and it expires, it sits in the LRU cache at its position until it falls to the end and is reused.

■ Memcached will also remove key from memory when you try to use it.

Q: When eviction is triggered?

The only times expired items are removed:

■ When intentionally deleted — 使用者刪除。

■ When overwritten via SET — 被複寫。

■ When expired then re-accessed via GET, ADD, and so on. — 過期後被讀取到。

■ When an eviction is required, it would look at a few items around the tail in search of an expired item to reclaim rather than evict the actual tail. — 驅逐發生時

■ An important optimization was made early on which causes an item to only be bumped once every 60 seconds. Very frequently accessed items thus avoid excessive mutex locks and mutations. — 每60秒調整(bumped)。避免了過多的互斥鎖和突變。

LRU_Maintainer

LRU_Maintainer 是一個單獨的後端程序,使用 LRU 的策略去更新鍵值的狀態,當清除鍵值時,能夠更精準及效率性。

■ LRU is splits items into HOT, WARM and COLD LRUs.

HOT acts as a probationary queue, since items are likely to exhibit strong temporal locality or very short TTLs (time-to-live). As a result, items are never bumped within HOT: once an item reaches the tail of the queue, it will be moved to WARM if the item is active (3), or COLD if it is inactive (5).新的數據從這裡進來,數據在這裡排成隊列,一旦到了隊尾,如果 Active,放入 WARM;如果不是,放入 COLD。

WARM acts as a buffer for scanning workloads, like web crawlers reading old posts. Items which never get hit twice cannot enter WARM. WARM items are given a greater chance of living out their TTL’s, while also reducing lock contention. If a tail item has is active, we bump it back to the head (4). Otherwise, we move the inactive item to COLD (7).只有當數據被訪問至少兩次時,才會被放到 WARM,如果隊尾數據是 Active,放到隊頭;如果不是,放入 COLD。

COLD contains the least active items. Inactive items will flow from HOT (5) and WARM (7) to COLD. Items are evicted from the tail of COLD once memory is full. If an item becomes active, it will be queued to be asynchronously moved to WARM (6). In the case of a burst or large volume of hits to COLD, the bump queue can overflow, and items will remain inactive. In overload scenarios, bumps from COLD become probabilistic, rather than block worker threads.內存滿之後,COLD 的隊尾數據會被踢出,當 COLD 隊列裡的數據變得 Active,該數據會被異步放入 WARM。

TEMP acts as a queue for new items with very short TTL’s (2) (usually seconds). Items in TEMP are never bumped and never flow to other LRU’s, saving CPU and lock contention. It is not currently enabled by default.用於超短 TTL 數據,數據即使被訪問了,順序也始終不變,也不會移到其他地方。

■ LRU updates only happen as items reach the bottom of an LRU. If active in HOT, move to WARM, if active in WARM, stay in WARM. If active in COLD, move to WARM.

ru_maintainer: A background thread that shuffles items between the LRUs as capacities are reached. Values: 0, 1. (Default: 0)

LRU_Crawler

LRU_Crawler 是一個單獨的後端程序,使用 LRU 的策略主動從頭到尾去檢查過期的鍵值,並去調整順序。

lru_crawler: Cleans slab classes of items that have expired. This is a low impact process that runs in the background. Currently requires initiating a crawl using a manual command. To temporarily enable, run lru_crawler enable at the command line. lru_crawler 1,3,5 crawls slab classes 1, 3, and 5 looking for expired items to add to the freelist. Values: 0,1 (Default: 0)

■ If enabled, runs a background thread which will walk from the tail toward the head of requested slab classes, actively freeing memory for expired items. 啟動一個後台線程,主動從頭到尾去檢查過期的鍵值。

■ 從每個 class 的每個子 LRU 的隊尾同步開始向隊頭方向尋找,回收過期數據。這裡同步的意思是排好隊齊步走,這樣較短的 class 會很快完成,不至於要一直等到較長的 class 完成後被處理。

■ Crawler 邊走邊維護一個 TTL 直方圖,並根據直方圖決定多久以後再重新掃描該LRU。如果一個 class 有很多馬上就要過期的數據,那麼 Crawler 就會在短時間內重新掃描,反之,則可以等等。

Q: How to check the number of items in each LRU and the number of moves?

Q: 如果特定 Slab Class 報錯,內存不足時,但其他 Slab Class 仍有可用 pages 時,該如何處理?

由於 Memcached 會預先分配多個大小不同的 Slab Class,而每一個 Slab Class 會去跟作業系統申請 memory pages 來存放資料,而分配在該 Slab Class 的 memory pages 沒有使用,也不會主動歸還,而內存管理是依每一個 Slab Class來處理,所以當內存不足時,Memcached 跟作業系統申請額外的 memory pages來存放數據,即使其他 Slab class 有沒有使用的 memory pages,memcahed 仍然不會拿來使用。不過當您將參數 Parameter: slab_automove/slab_reassign 開啟時,就可以解決這個問題。

slab_reassign

slab_reassign: Enable or disable slab reassignment. If this parameter is set to 1, you can use the “slabs reassign” command to manually reassign memory. (Default: 0)

Changes Take Effect: At launch

這個功能是一個手動操作的觸發的,命令如下:

■ Slab Automove — Auto move

slab_automove: Adjusts the slab automove algorithm: If this parameter is set to 0 (zero), the automove algorithm is disabled. If it is set to 1, ElastiCache takes a slow, conservative approach to automatically moving slabs. If it is set to 2, ElastiCache aggressively moves slabs whenever there is an eviction. (This mode is not recommended except for testing purposes.) (Default: 0)

Changes Take Effect: After restart

■當內存不足時會自動移動page,平時不會移動。自動調整 slab class 的大小。

--

--

Jerry’s Notes
What’s next?

An cloud support engineer focus on troubleshooting with customer reported issue ,and cloud solution architecture.