memcached 的記憶體管理與刪除機制
一、記憶體的碎片化
如果用c語言直接 malloc,free 來向作業系統申請和釋放記憶體時,在不斷的申請和釋放過程中,形成了一些很小的記憶體片斷,無法再利用,這種空閒,但無法利用記憶體的現象稱為記憶體的碎片化。
二、slab allocator 緩解記憶體碎片化
memcached 用 slab allocator 機制來管理記憶體。slab allocator 原理: 預告把記憶體劃分成數個 slab class 倉庫.(每個 slab class 大小 1M)各倉庫,切分成不同尺寸的小塊(chunk)。需要存內容時,判斷內容的大小,為其選取合理的倉庫。
如圖:
三、系統如何選擇合適的 chunk?
memcached 根據收到的資料的大小,選擇最適合資料大小的 chunk 組(slab class)。memcached 中儲存著 slab class 內空閒 chunk 的列表,根據該列表選擇空的 chunk,然後將資料緩存於其中。
如圖:
注意:如果有 100byte 的內容要存,但 122 大小的倉庫中的 chunk 滿了並不會尋找更大的,如 144 的倉庫來儲存,而是把 122 倉庫的舊資料踢掉。
四、固定大小 chunk 帶來的記憶體浪費
由於 slab allocator 機制中,分配的 chunk 的大小是”固定”的, 因此,對於特定的 item,可能造成記憶體空間的浪費. 比如,將 100 位元組的資料快取到 122 位元組的 chunk 中,剩餘的 22 位元組就浪費了。
如圖:
對於chunk 空間的浪費問題,無法徹底解決,只能緩解該問題。開發者可以對網站中快取中的 item 的長度進行統計,並制定合理的 slab class 中的 chunk 的大小。可惜的是,我們目前還不能自定義 chunk 的大小,但可以通過引數來調整各 slab class 中 chunk大小的增長速度。即增長因子, grow factor。
五、grow factor (增長因子)調優
memcached 在啟動時可以通過f 選項指定 Growth Factor 因子,並在某種程度上控制 slab 之間的差異。預設值為 1.25. 但是,在該選項出現之前,這個因子曾經固定為 2,稱為”powers of 2” 策略。
六、memcached 的過期資料惰性刪除
1. 當某個值過期後,並沒有從記憶體刪除,因此,stats 統計時, curr_item 有其資訊。
2. 當某個新值去佔用他的位置時,當成空 chunk 來佔用。
3. 當 get 值時,判斷是否過期,如果過期,返回空,並且清空,curr_item 就減少了。
資料沒有在過期的瞬間立即從記憶體刪除,這個稱為 lazy expiration,惰性失效。節省了cpu時間和檢測的成本。
七、lru(最近最少使用) 刪除機制
如果以 122byte 大小的 chunk 舉例, 122 的 chunk 都滿了, 又有新的值(長度為 120)要加入, 要擠掉誰? memcached 此處用的 lru 刪除機制。