談談 Memcached LRU

一. Memcached 內存結構


可以看出 Memcached 將內存分爲一個一個 slab class,slab class 沒有大小,所有的 slab class 加起來就是 Memcached 啓動時設置的內存大小。slab class 裏面有 slab page,slab class 大小由 slab page 個數決定,默認的 slab page 爲 1M,可以在啓動 Memcached 時設置。slab page 裏又分爲同等大小的 chunk,chunk 就是存儲緩存的基本單元,chunk 大小,不同 slab class 的 page 大小一致,但是 chunk 大小不一致,默認 class1 的 chunk 大小爲 96 byte,不同 class 的 chunk 大小由啓動時設置的 factor 係數決定,下一個 class 的 chunk 是上一個 class 的 chunk 的 1.25 倍(默認是 1.25)。


Memcached默認情況下采用了名爲Slab Allocator的機制分配、管理內存。在該機制出現以前,內存的分配是通過對所有記錄簡單地進行malloc和free來進行的。但是,這種方式會導致內存碎片,加重操作系統內存管理器的負擔,最壞的情況下,會導致操作系統比memcached進程本身還慢。Slab Allocator就是爲解決該問題而誕生的。


      Slab Allocator的基本原理是按照預先規定的大小,將分配的內存以page爲單位,默認情況下一個page是1M,可以通過-I參數在啓動時指定,分割成各種尺寸的塊(chunk), 並把尺寸相同的塊分成組(chunk的集合),如果需要申請內存時,memcached會劃分出一個新的page並分配給需要的slab區域。page一旦被分配在重啓前不會被回收或者重新分配,以解決內存碎片問題。



二. 如何分配

Memcached在啓動時通過-m參數指定最大使用內存,但是這個不會一啓動就佔用完,而是逐步分配給各slab的。如果一個新的數據要被存放,首先選擇一個合適的slab(存入的數據大小和 chunk 大小最接近,這樣可以減少內部碎片的浪費),然後查看該slab是否還有空閒的chunk,如果有則直接存放進去;如果沒有則要進行申請,slab申請內存時以page爲單位,無論大小爲多少,都會有1M大小的page被分配給該slab(該page不會被回收或者重新分配,永遠都屬於該slab)。申請到page後,slab會將這個page的內存按chunk的大小進行切分,這樣就變成了一個chunk的數組,再從這個chunk數組中選擇一個用於存儲數據。若沒有空閒的page的時候,則會對改slab進行LRU,而不是對整個memcache進行LRU。(PS:局部 LRU)



三. 面臨的問題

在這樣的內存結構和內存分配的策略上,會有一些典型的問題,比如 Memcached 還有一般的空閒內存,但是進行了 LRU,原因就是某些緩存數據大小相近的都是分配在某個 slab class 上,這些數據又是熱數據,又不斷有加入的新數據,因爲是局部 LRU,所以導致在這個 slab class 上頻繁進行 LRU,但是其他 slab class 裏面卻有大量空閒空間。這樣的情況如果頻繁,可以考慮調小 factor,這樣大小類似的數據可能會分配到不同的 slab class 上,減少 LRU 情況。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章