Thursday, February 28, 2008

memcached - Dağıtımlı (distributed) önbellek sistemi


TBD BİLİŞİM TERİMLERİ KARŞILIKLAR SÖZLÜĞÜ'nde "distributed" kelimesinin karşılığı olarak "dağıtımlı" yazıyor. Önceleri "distributed" kelimesi için "dağıtık", "dağıtılmış" kelimelerini kullanırdım. Madem Türkiye Bilişim Derneği "dağıtımlı" diyor bundan sonra benim de bu kelimeyi kullanmak boynumun borcudur. Bu yazıyı, okuduğum bir çok ingilizce yazının bir özeti olarak yazıyorum. (Kendi fikirlerimi eklemeyi unutmadım tabi ki :)) Yazıda ingilizce terimlerin türkçe karşılıklarını kullanmaya özen gösterdim fakat yine de tam türkçe karşılığını bulamadığım terimler var.

1. Nedir bu memcached denen şey?


Memcached, Danga Interactive http://www.danga.com/ tarafından geliştirilmeye başlanmış bir "distributed object caching" sistemidir. Yüksek trafik alan dinamik web uygulamalarının veritabanına gitme sayısını azaltmayı, bu sayede de performansı artırmayı hedefleyen bir uygulamadır.
Memcached'yi network üzerinden erişilebilen kocaman bir Hashtable olarak düşünebiliriz. Network üzerindeki herhangi bir makinadan "key" ile memcached'de sakladığımız bir nesneye, network üzerindeki başka bir makinadan aynı key ile ulaşabiliriz. Detaylar için okumaya devam...

2. Lisansı nasıl?


BSD License ile lisanslanmış. http://en.wikipedia.org/wiki/BSD_license

3. Hangi işletim sistemlerinde çalışıyor?


Linux, BSD, Windows üzerinde sorunsuz çalışıyor. Web sitesinde Solaris ile ilgili bir bilgi yok. Mail listelerine bakılınca solaris üzerinde çalıştırmak için taklalar atmak gerektiğini anlıyoruz. Memcached fazla CPU kullanmıyor ve tek ihtiyacı boş RAM. Bu yüzden memcached instance'larını çalıştıracağımız makinanın Sun sparc işlemcili bir makina olmasına gerek yok. Hızlı bir network kartı ve yeterli RAM'i olan linux PC'ler memcached çalıştırmak için yeterli olacaktır. (Ben testlerimi Ubuntu 7.10 kurulu Dell Laptop üzerinde yaptım :) )

4. Nasıl kurulur?


http://www.danga.com/memcached/download.bml adresinden indireceğiniz kaynak kodunu INSTALL ve README dosyalarını okuyarak derleyip kurabilirsiniz.
http://blog.ajohnstone.com/archives/installing-memcached/ adresinde kurulum ile ilgili bir tutorial var.

5. Nasıl çalıştırılır?


Memcached bir konfigürasyon dosyasına ihtiyaç duymaz. Gerekli bütün ayarlar komut satırından memcached daemon'u çalıştırırken verilebilir.

# ./memcached -d -m 2048 -l 192.168.43.47 -p 11211


Bu komut memcached'ye der ki:
  • (-d) daemon olarak çalışacaksın
  • (-m 2048) 2GB'dan fazla RAM kullanamazsın.
  • (-l) 192.168.43.47 makinasında çalışıyorsun
  • (-p) 11211 portunu dinleyeceksin.

Aynı makina üzerinde RAM yettiği sürece birden fazla memcached daemon çalıştırabiliriz (Farklı portlarda çalıştırmaya dikkat etmek lazım). Örneğin, herbiri 512MB kapasiteli 5 adet memcached daemon'u aynı makina üzerinde asaşıdaki şekilde başlatabiliriz. Toplamda 2.5GB'lık bir cache'imiz oluyor. (Dikkat böyle bir kullanım size mantıklı gelmeyebilir, sadece daemon'u nasıl başlattığımız göstermek için bir örnek.)

# ./memcached -d -m 512 -l 192.168.43.47 -p 11211
# ./memcached -d -m 512 -l 192.168.43.47 -p 11212
# ./memcached -d -m 512 -l 192.168.43.47 -p 11213
# ./memcached -d -m 512 -l 192.168.43.47 -p 11214
# ./memcached -d -m 512 -l 192.168.43.47 -p 11215



6. Memcached'ye uygulamalarımız nasıl erişecek?


Memcached'nin network üzerinden erişilebilen büyük bir Hashtable olduğundan bahsetmiştik. Uygulamaların memcached'ye erişebilmeleri için çeşitli dillerde yazılmış istemci kütüphaneleri var. Java dışında Perl, Php, Python, Ruby, C# ve C için yazılımış istemciler mevcut. Bu adresten http://www.whalin.com/memcached/ java memcached client indirilebilir.
Yazılımcılar gerek görürlerse memcached ile haberleşmeyi sağlayacak kendi istemci kütüphanelerini yazabilirler. Memcached ile client'lar arasındaki protokolün detaylarına http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt adresinden erişilebilir.

7. Tipik bir kullanım örneği


Örnek java kodu:

public VpnAccount getVpnAccount(String msisdn) {
VpnAccount account = memcachedClient.get(msisdn);
if (account == null) {
account = getAccountFromDatabase(msisdn);
memcachedClient.set(msisdn, account);
}
return accout;
}



6. Nasıl çalışıyor? Nasıl "distribution" sağlıyor?


Evet zurnanın "zıırrrt" dediği yere geldik. Memcached network üzerinden erişebileceğimiz boş RAM'i olan herhangi bir makinada çalıştırılabilir.

Örnek 1: Bir veya birden fazla uygulamanın tek bir memcached instance kullandığı senaryo:


Bu senaryonun üzerinde fazla durmaya gerek yok. Uygulamalara memcached'nin çalıştığı makinanin IP'si ve memcached'nin dinlediği port bilgisi verilir. Bütün uygulamalar aynı cache instance'ını kullanır. A uygulamasının K anahtar kelimesi ile cache'e gönderdiği V değerini, B uygulaması K anahtar kelimesini kullanarak alabilir.
Bu mimarinin artıları:
  • Basit bir mimaridir. (Fakat tavsiye edilen mimari değil)
  • Merkezi bir cache olduğu için uygulamalar (java uygulamalarından bahsediyorum) kendi cache'lerini tutmak zorunda değil. Uygulamaların Cache'leri arasında tutarlılık kontrolleri yapmaya gerek yok.

Eksileri:
  • Tek bir cache instance = SPOF (Single point of failure)

Örnek 2:


Birden fazla memcached daemon'ın kullanıldığı senaryo.


192.168.43.47:11211, 192.168.43.48:11211 ve 192.168.43.49:11211 da çalışan 3 adet memcached daemon olsun. Bizim de bu cache'leri kullanan A,B ve C uygulamalarımız olsun. (IN uygulamalarından örnek verecek olursak GW1, GW2 ve GW3).
memcached'nin çalışması iki adımdan oluşan hashing mekanizmasına bağlıdır.
  • 1. adımda client, memcached daemon listesini kullanarak "K" anahtarının hash'ini hesaplar. "K" ile saklanan "V" değerine ulaşmak için (ya da "K" ile "V" değerini saklamak için) hangi memcached server'a gideceğini bulur.

  • 2. adımda memcached serverda (çok büyük bir hashtable olarak düşünebiliriz demiştik) "K" anahtarının hash'i farklı bir algoritma ile hesaplanır. "Hashtable lookup" ile "V" değerine erişilir.

Telekom uygulamasından bir örnek:
MSISDN'leri anahtar olarak kullanıp VpnAccount nesnelerini memcached içinde saklayalım. MSISDN "905435022434", cache server listesine göre hash'lendiğinde "905435022434"e karşılık gelecek VpnAccount'un hangi memcached daemon'da saklanacağı bulunur. (Örneğin 192.168.43.48:11211).
Uygulamaların hepsi anahtar kelimenin (yani MSISDN'in) hash'ini hesaplarken aynı hash algoritmasını kullanacağı için "905435022434" numaralı VpnAccount'a ulaşmak için bütün uygulamalar aynı memcached daemon'a gidecektir.
Bu mimarinin artıları:
  • çok iyi ölçeklenebilir (highly scalable). Ne kadar çok RAM o kadar çok cache.
  • aklıma şimdilik başka birşey gelmiyor :D

Eksileri:
  • (Eksi alanına birşeyler yazmış olmak için yazıyorum) birden fazla memcached instance'ı yönetmek zor olabilir.


9. Authentication mekanizması nasıl işliyor?


Memcached authentication kullanmıyor. Network üzerinden erişimi olan bütün client'lar "set" ve "get" yapabilirler. Üzerinde memcached çalışan host'ların firewall ayarlarının dikkatli yapılması gerekir.

10. Failover senaryoları nasıl? Memcached failover destekliyor mu?


memcached failover desteklemez. memcached'yi "set(key, value)" ve "get(key)" işlemlerini destekleyen bir Hashtable olarak olarak tanımlamıştık. Memcached instance'larının birbirlerinden haberleri yoktur. Network üzerinden kaç tane memcached'nin çalıştığı bilgisi sadece client'larda vardır. Memcached server grubundan bir server'ın çıkartılması ya da yeni bir server eklenmesi durumu ile başa çıkmak client'lara kalmıştır.
A, B, C hostlarında çalışan 3 tane memcached server oldugunu varsayalım.

hash("905435022434")%(["A","B","C"].length) --> A
hash("905435022435")%(["A","B","C"].length) --> B
hash("905435022436")%(["A","B","C"].length) --> C olsun.


("905435022434" anahtarı ile bir nesneyi aramak için A'ya, "905435022435" anahtarı ile bir nesneyi aramak için B'ye gidilecek.)
Bu üç hosttan bir tanesi örneğin B erişilemez duruma gelirse, kullanılabilen 2 tane memcached server kalır. Bu durumda

hash("905435022434")%(["A","C"].length) --> C
hash("905435022435")%(["A","C"].length) --> A
hash("905435022436")%(["A","C"].length) --> A olabilir.


Yani 3 memcached server ile çalışırken "905435022434" anahtarı ile A hostuna yönlenilirken 2 memcached server ile çalışırken "905435022434" anahtarı ile C hostuna yönlenebiliriz. Bu da "905435022434" anahatarı ile cache içinde tutulan nesnenin artık geçersiz olduğu (DB'den yeniden çekilmesi gerektiği) anlamına gelir. Aynı tip senaryo memcached server grubuna yeni bir memcached server eklendiğinde de geçerlidir.
Yukarıda bahsedilen problemi çözmek için "consistent hashing" algoritmaları geliştirilmiş. memcached client'ların verilen bir anahtar için hangi memcached server'a gideceklerini hesaplayan bu algoritmalar sayesinde memcached server grubundan bir server çıktığı zaman ya da yeni bir server eklendiği zaman "K" anahtarına karşılık gelen memcached server'ın değişmemesi sağlanmıştır.
http://www.whalin.com/memcached/ adresindeki memcached client içerisinde "consistent hashing" algoritmasının implementasyonu mevcut.

11. JVM, cache için extra hafızaya ihtiyaç duyacak mı?


Memcached kullanıldığında nesneler JVM heap'te değil başka bir process'in (bu process JVM ile aynı host'ta ya da farklı bir host'ta olabilir) kullandığı hafıza alanında saklanır. Bugün cache kullanan uygulamalarımız için JVM'i başlatırken (yaklaşık olarak) 2GB heap kullan diyoruz (-Xms2048m -Xmx2048m). Memcached kullandığımız durumda JVM bu kadar geniş bir heap'e ihtiyaç duymayacaktır - çoğu uygulamalar için 256 MB'lık bir heap yeterli olur diye düşünüyorum. Bu sayede Garbage collection sureleri kısalacaktır. (Telekom uygulamalarında Garbage Collection suresinin ne kadar önemli olduğundan söz etmeye gerek yok.)

12. Cache dolduğu zaman ne olur?


Memcached'nin cache'i dolduğu zaman, cache'e yeni bir nesne eklemek istersek LRU (least recently used) yöntemiyle eski nesneler cache'den silinir.

13. memcached'nin arkasında kim var?


memcached kaynak kodu açık bir uygulama. Arkasında bizim gibi 100'lerce yazılımcı var. Daha da önemlisi bir çok yerde kullanıyor ve kendini kanıtlamış. http://developers.facebook.com/opensource.php adresinde, facebook yazılımcılarının memcached kaynak koduna yaptıkları katkılarla, memcached performansını 20% iyileştirdiklerinden bahsediliyor.
Aşağıdaki listede memcached kullandıklarını söyleyen bir kaç tane web sitesi var. Bu sitelerin ortak özellikleri çok hit almaları ve her sayfada dinamik bilgiler göstermeleri.


14. Daha detaylı bilgiye nereden ulaşabilirim?


Bu adreste (http://www.socialtext.net/memcached/index.cgi?faq) memcached ile ilgili bir FAQ var.

2 comments:

oddnone said...

gercekten guzel bir turkce kaynak hazirlamissin,cok tesekkurler

Ogün Heper said...

memcached için güzel bir giriş yazısı olmuş; elinize sağlık.