Memcached Slab, Chunk, Page ve Boşa Giden Memory

Memcached açık kaynaklı, yüksek performanslı, dağıtık memory caching sistemidir. Danga Interactive tarafından LiveJournal.com'un database yükünü azaltmak ve siteyi hızlandırmak için geliştirilmiş.

Çok hızlı olmasından dolayı ve hem kurulumu hem de kullanımı çok kolay olduğu için yıllardır yoğun şekilde birçok yerde kullanılıyor. Son zamanlarda artan NoSQL trendinde bile popülerliğini hiç kaybetmedi.

Memcached'in bir sürü artısı var. Ama bunların yanıda genelde çok az bilinen eksileri de mevcut. Bunlardan en büyüğü aşağıda bahsedeceğim 'wasted memory' sorunu.

Page

Memcached'i başlattığınızda (memcached -d) kendisi için ayırılmış alanı küçük parçalara bölümlendirir. Bunlara page denir ve herbiri 1MB büyüklüğündedir. Örneğin memcached -d -m 128 şeklinde başlatınca max 128MB memory allocate edilir. Bu da 128 tane page yaratılır demektir.

Slab

Bu page'lerin bazıları slab-class'lara atanır bazıları ise boşta durur. Her slab-class sadece belirli büyüklüklerdeki öğeleri barındarmakla görevlidir. Bir item kaydetmek istediğinizde, o değer boyutuna göre hangi slab ile ilişkilendirilmiş ise oraya kaydedilir.

Chunk

Bunu yapabilmek için slab-class'lara atanmış page'ler daha da küçük parçalara bölünür. Bunlara da chunk denir. chunk boyutları bütün slab'lar için farklı ama herbir slab içinde aynıdır.

Slabs, Pages, Chunks

growth factor adı verilen değer ile (1.25) minimum chunk değeri (96byte) ilk slab sonrası için hesaplanıp slab chunk size değeri bulunur.

Herbir slab'a başlangıçta 1 adet page atanır. page kendi içinde slab chunk size değerine göre chunk'lara bölünür. 1MB alana kaç adet chunk sığıyorsa o kadar chunk yaratılmış olur.

$ memcached -vv -I 1k
slab class   1: chunk size        96 perslab      10
slab class   2: chunk size       120 perslab       8
slab class   3: chunk size       152 perslab       6
slab class   4: chunk size       192 perslab       5
slab class   5: chunk size       240 perslab       4
slab class   6: chunk size       304 perslab       3
slab class   7: chunk size       384 perslab       2
slab class   8: chunk size       480 perslab       2
slab class   9: chunk size       600 perslab       1
slab class  10: chunk size       752 perslab       1
slab class  11: chunk size      1024 perslab       1

Memcached start with 1k max

Bu da şu demek oluyor; yukarıda ki resimde de görüldüğü gibi bazı slab'lar başlangıçta sadece 1 adet chunk ile yaratılmış olacaktır. chunk'lar doldukca boştaki page'ler ihtiyaç duyulan slab'a atanır. Boşta hiç page kalmadığında tek chunk'a sahip slab'lar boş page'lerden de alamadıysa sadece 1 değer barındırabilirler. Örneğin 1MB'a yakın bir değer set etmiş olalım. Aynı chunk'a denk gelicek büyüklükte başka bir değer set etmek istersek slab kendi içinde LRU çalıştırıcak ve ilk değeri silip yeni gelen değeri set edicek. memcached bir sürü RAM ile başlatılmış olsa bile set edilen değerlerin karakteristiğine (mesela %99.9 küçük değerler) göre yaşanması çok muhtemel bir senaryo.

Wasted Memory

chunk'lar belirli aralıklarda ki değerleri tutarlar.

slab class 1 için chunk size 96byte demek 96 byte ve daha küçük değerler bu slab'a kayıt edilir. slab class 2 için 96 ile 120 byte arasındaki değerler geçerlidir.

Yine bir örnek üstünden gitmek gerekirse; sürekli 97 byte (item overhead dahil) büyüklüğünde değerler kaydettiğimizi farz edelim. slab class 2'ye bu değerleri kaydediyor olucak. chunk size 120 olduğu için herbir chunk sadece 1 değer barındırabilecek.
Memcached Chunk 120byte chunk size - 97byte data = 23byte wasted memory

slab istatistiklerini stats slabs komutu ile görebilirsiniz. Örnek bir slab class istatistiğinde wasted memory değeri görülebilir.

**Slab 13 Stats**
Chunk Size  1480.0 Bytes
Used Chunk  27515 [38.1 %]
Total Chunk 72216
Total Page  102
Wasted      12.4 MBytes
Hits        15.2 Request/sec
Evicted     0

wasted memory artık kullanılamaz gibi bir durum yok. Silinen, süresi dolan ve yeniden yazılan değerlere göre sürekli değişmektedir.

set edilen değerlere göre optimizasyon yapmak mümkün. Ayrıca growth factor ve minimum chunk size değerini küçültmek de bu sorunu azaltacaktır ama başka sorunlara yol açacaktır.

memcached kullanırken göz ardı edilen bu durumlar performans ve verimlilik açısından beklediğinizi alamamanıza hatta boş memory varken gereksiz eviction yaşanmasına sebep olabilir. O yüzden dikkat etmek gerekli.

Boş memory varken kimse kullanıcı sessionlarını kaybetmek istemez.