Sunday, March 29, 2009

Arama Mimarisi

Kisilerin profilini ve arkadasliklarini idare eden bir sistemde, profil esleme (matching), ya da kisileri isim bazinda arama gibi ozellikler icin arka planda arama kabiliyetinin olmasi gerekiyor.

Daha once, uygulamamizin verisel bazli dagitik olabilmesi icin Voldemort veri tabanini sectigimizi soylemistik.

VM, tekil id bazli objelere hizli bir sekilde erisebilen, depolayabilen ve dagitabilen bir anahtar-deger tabanidir.

ID haricindeki alanlar uzerinden indeksleme yapmak icin, ek bir ozellige ihtiyacimiz var.

Piyasada bu is icin genellikle Lucene kullanilir (ve yatay sekilde dagitik olsun diye bir onceki yazida Katta/Hadoop dusunuluyordu). Biz arama icin mysql fulltext ozelligini kullanmayi sectik. Katta ve Hadoop seksi ozelliklere sahipler fakat isi simdilik gereginden fazla zorlastiracaklar. "Idare edilecek bir kume teknolojisi daha" olacaklar.

Mimariyi su sekilde kurmaya karar verdik (yerel calisan Lucene olsaydi da mimari aynidir -Katta degil, o baska-).

1) JBoss isleten App Server makinalarinin her birinin kendine ozel, sahsi mysql tabani olacak. 2) Her app server'da isleyen bir toptan isleyici (batch job) belli araliklarla uyanip, Voldemort'a "en son eklenen objeleri" alacak. 3) Bu objeler ilgili alanlarina gore arama tabaninda indekslenecek. 4) Bu sayede her app server kendine hususi, ve "tum tabani" yansitan bir arama tabanina sahip olacak.

Bir app server cokerse, tekrar ayaga kalktiginda kaldigi yerden indekslemeye devam edebilecek.

Voldemort'a obje ekleme, guncelleme islemi, indeksleme isleminden tamamen bosanacagi icin performans konusunda mysql bir sorun ol(a)mayacak.

Niye bir toptan islemci her app server'da "tum objeleri" VM'den aliyor, app server web aksiyonlari hem tabana eklerken, hem indeklese olmaz mi?

Olmaz, cunku 1) arama tabaninin merkezi olmamasi lazim (olcekleme amaciyla -ve yatay dagitik olmayacagina Katta'dan vazgecince buna otomatik olarak karar vermis olduk-) ve 2) her app server, kume ortaminda ekleme isteklerinin sadece bir bolumunu karsiliyor olacagi icin (yuk dagitimi istekleri dagitiyor) o zaman her app server hususi arama tabanina her objeyi ekleyemeyecekti. Voldemort'a giderek her app server her objeyi ekleyebilir.

"Arama tabani cok buyuyebilir mi?" sorusu akla gelebilir, fakat tum online VM tabanini buraya eklemiyoruz. Sadece arama icin gerekli seyleri ekliyoruz.

Arama tabanini online tabandan nasil bu kadar rahat ayirabildik? Onemli bir faktor, arama ozelliginin "en son en mukemmel" online kopyaya sahip olma mecburiyeti olmamasi idi... Bu taban, birkac dakika geriden takip edebilir, bu onemli degil. Bu sayede arada sirada uyanan bir toptan isleyici "herkese yerel" bir arama tabani uzerinden indeksleme yapabildi.

"Eklenen en son objeleri bana ver" ozelligi icin Voldemort projesiyle irtibata gectik. Onlar da boyle bir ozelligi uzun suredir dusunduklerini soylediler, biz vesile olduk. Bu ozelligin kodlamasini oncelikli olarak ele almaya karar verdiler. Bu ozellik olmadan, ilk basamak olarak biz, nasil olsa tek makina baslangici yapacagimiz icin hem VM hem fulltext eklemeyi web aksiyonu icinden ayni anda yapacagiz.

Fakat yeni ozellik hazir olunca (ve biz cok app server ortamina gecince), bu baglanti koparilacak ve toptan islemci devreye sokulacak.

Arama motorunda mysql kullanarak rdbmslerin iliskisel karmasasina geri donmuyoruz aslinda; Burada tutulacak fulltext tablolari son derece basit tablolar olacaklar.
CREATE TABLE `xxx_index` (        
`id` binary(32) NOT NULL,
`index_me` varchar(255) default NULL,
PRIMARY KEY (`id`),
FULLTEXT KEY `index_me` (`index_me`)
) ENGINE=MyISAM;
Arama yapmak icin
select id from xxx_index where match(index_me) against ('filan')
Geri dondurulen id alinip, Voldemort'ta objenin tamamina erisim icin kullanilabilecek. Arkadas listeleri, profil detaylari vs. tamamen VM'den geliyor olacak.

Final mimari:

Thursday, March 26, 2009

Katta

RDBMS'in farkli islevleri yuksek olcekli dunyada RDBMS'den cekip cikartilarak degisik aktorlere dagitilmisa benziyor. Tekil id uzerinden tekil objelere erisme, onlarin iliskilerini kayit altinda tutma gibi isler anahtar-deger tabanlarina verilmis. Belli alanlar uzerinden indeks yaratip onlara tam/yarim uyum uzerinden erisme isi de bu is icin ozel yazilmis, kendi verisini kendine ozel formatta tutan Arama Motor yazilimlarina birakilmakta..

Lucene projesi Java dunyasi icin yabanci bir yuz degil. Belli alanlari, ya da duz metin dosyasini indeksleyerek hizli bir erisimi bize saglayan bir motordu Lucene.

Lucene kullanarak, ve bunu yuksek olcekli ortamda isleterek arama servisi vermeye talip projelerden biri ise Katta.

Katta bir kume halinde calisabiliyor ve yazilimin ilginc bir ozelligi, bilim dunyasina tanidik gelen Hadoop sistemi uzerinde, onun dagitik dosyalama sistemini kullanarak calisiyor olmasi. Hadoop bazi veri ozetleyici servisleri de saglayan bir yazilim. Veri Madenciligi, Biotech dunyasinda sIk olarak isminden bahsedilmeye baslandi. Biz su anda IT mod'undayiz fakat temel bilimler mod'una donersek, o zaman Hadoop ve analitik ozelliklerinden bahsetmek farz olacak.

Bu sistemi test ediyoruz. Hakkinda iyi seyler duyduk - Katta'yi kullanmamiz yuksek bir ihtimal.

Wednesday, March 25, 2009

Master/Slave Modeli ve Voldemort

Master/Slave bazli calisan yapilar, okumalari N sayida slave'e, yazmalari tek master'a gonderirler, ve okumalarin yazmadan cok oldugu durumlarda sistemi olcekleyebiliyorlar.

Voldemort gibi bir sistem, hem okuma, hem yazma icin ayni anda olceklenebilen bir sistemdir. Ortada bir master, slave yoktur - her islem ne olursa olsun, anahtar bazli olarak bir "bolume yonlendirilir" ve gerekli makinaya gider. Ayrica, M/S cozumunde kullanilmasi gereken master ve slave arasindaki replikasyon suresi, bir VM kumesinde problem degildir cunku replikasyon kullanilmamaktadir. Her verinin yeri bellidir. (Replikasyon kullanildiginda yedekleme amaciyla yapilir, ama bu replikasyonun kac baska makinaya dogru olacagi sistem tarafindan kontrol edilir, hic bir kurulum, ek efor, kodlama gerektirmez).

Bu da akilda tutulmasi gereken bir husus.

Bir ek not: Tek makinadan cok makinaya gectiginizde transaction problem olabilir - bu durumda VM cozumu, versiyon bilgisi eklenmis anahtar-deger eslerinin once-sonra hallerini kontrol etmektir. Bu uygulama programinin seviyesinde yapilir. 2 asamali commit (two-phase commit) bazli cozumlerin istenen seviyede olceklenmesi imkansiz oldugu icin VM'e dahil edilmemistir.

Proje Voldemort - II

Yeni nesil Internet sitelerinin gereksinimleri sebebiyle iliskisel modelden bir uzaklasma oldugunu onceki yazida belirttik. Buyuk olcekte calisan Google ve Amazon sirketlerinin sirasiyla Bigtable ve Dynamo teknolojilerini gelistirmis olmalari raslanti degil herhalde. Bu ihtiyac, yeni bir trend, ve anahtar-deger veri tabani gelistirme alaninda bir patlama yaratti - herkes, pek cok dilde, pek cok sekillerde kendi anahtar-deger veri tabani uzerinde calisiyor.

Dogal olarak, toz bulutu yere indiginde, kazananlar, kaybedenler daha belirginlesecek. Bu tur gelecegi olan paketi secmek IT programcisi icin onemli; isten ise, projeden projeye gecerken, yaninda goturebilecegi alet kutusunda daha az degisen arac kumesi tasiyabilir boylece. Bu daha az egitim masrafi demektir. Bir arac uzerindeki tecrubelerini ust uste koyarak, buyutup, derinlestirebilir.

Voldemort'a donersek:

VM onbellekleme isini tamamen kendi uzerine aliyor. Yeni nesil bir tabandan bekledigimiz zaten budur; Veri dagilimi, onbellekleme, cokusten kurtulma gibi "fiziksel" isleri ustune almasi. Bu tur programlama ile ilgisi olmayan (olmamasi gereken) ozellikler icin bizim yeni taklalar atmamizin gerekmemesi.

Veri dagilimi hakkinda onemli bir nokta, veriyi tekrar dengeleme (rebalancing) konusu. VM bir anahtara baktigi anda, onun hangi bolume (partition) gidecegini biliyor. Fakat bunu yapabilmesi icin bolum sayisinin bir kere set edildikten sonra hic degismemesi gerekli. Eger 20 tane bolumum var diyorsaniz, bu database yapisi, hep 20 bolum ile calismali. Bunun fiziksel makinalar ile alakasi ne?

Kurallar soyle. 1) Isterseniz birden fazla bolumu ayni makinaya esleyebilirsiz. 2) Bir bolum sadece belli bir makina uzerinde olabilir, baska makina uzerinde olamaz.

Burada amaclanan sudur. Kumenin fiziksel yapisi degisecegi icin anahtardan makinaya gitme kavrami, anahtardan bolume gitmeye cevrilmis, boylece sistemin degismeyen bir sey ile calisabilmesi saglanmis, fakat siz arka planda makina basina kac bolumun olacagina admin seviyesinde karar veriyorsunuz (tekil makina secimini VM arka planda kendisi yapiyor). Sisteminizin ihtiyaclari buyudukca ayni makina uzerinde daha az bolum gitmeye basliyor. En son olcekleme noktasinda, artik tek bolum tek makina uzerinde oluyor. Bu sistemin gelebilecegi en son nokta, bundan sonra makinalarin daha fazla kapasiteye sahip olmasi gerekli.

Bu pek kisitlayici degil bence, son derece esnek bir yapi. Dikkat edelim, bolum sayisi "soft" bir ayar ve herhangi (makul) bir sayi atamanin az sayida makine ile calisirken bile hicbir ek performans bedeli yok. O zaman projemizin ilk acilisinda DB bolum sayisi 30 diye baslayabiliriz, tek bir fiziksel makina olabilir, sonra daha fazlasi eklenir ve bolumler degismez. 1-15 arasi makina 1'e, 16-30 arasi makina 2'ye gitmeye baslar.

Tekrar dengeleme (rebalancing) islemi iste budur. Bunun dinamik sekilde yapilmasi uzerinde calisiliyor. Sahsen benim icin nihai baglamda onemli bir ozellik, ama yine de projeme hala bu olmadan baslayabilirim. En kotu durumda, Amazon EC2'de yeni bir database kumesi baslatirim, birinci kumeme baglanip tum verileri teker teker okuyup ikinci kumeye toptan sekilde yazarim. Sonra uygulama kodlarimi birinci kumeden ikinciye isaret ettiririm. EC2'de birinci kumenin makinalarini kapatirim. Bu kadar.

Onbellekleme hakkinda fazla detaya gerek yok. Bir buyukluk ayarliyorsunuz, ve islemeye basliyor. Kendi isini kendi yapiyor.

Depolama: Voldemort farkli "depolama" formatlari ile calisabiliyor. BDB dosya formati bunlardan biri, digeri ise MySQL. Bu noktada MySQL aptal bir veri kutusu olarak kullaniliyor sadece, biz kullanmayacagiz fakat bu ozelligin olmasi iyi. Eger sirkette mevcut MySQL admin bilgisi var ise, VM ham verisinin yedeklenmesi, vs. baglaminda, bu bilgiler MySQL seviyesinde devreye sokulabilir. Biz yedeklemeyi BDB dosya seviyesinde, rsync ile yapacagiz.

Cokusten kurtulma icin VM'in cozumu bir nodun verisini kismen "yedek olarak" diger kumelerde tutmaktir. Eger bir nod cokerse, ayni bolum, baska makinadan calismaya devam eder. Coken makina geri gelince bolum bilgisi geri alinir, isler eskisi gibi devam eder. Bu ozellik test edilmis ve isliyor.

Mimari olarak VM "hicbir sey paylasmayan (share nothing)" mimarisidir (cokusten kurtulma durumunda olan kopyalamanin "yedekleme" amacli oldugunu hatirlatirim). Internet'te yuksek olcegi baska turlu karsilamak mumkun degil zaten... Veri yatay olarak bolundu mu, tam bolunmeli. Ahmet, Bora makina 1'de ise, Can, Dogan makina 2 uzerindedir. Bu kisilerin yan bilgilerinin "tamami" da ayni makinalar uzerindedir. Hicbir sey paylasilmaz. Boylece isteklerin "cogunlukla" sadece tek bir makinaya giderek islerini bitirebilmeleri saglanir. Bu paralelizasyonun iyi isledigi anlamina gelir. Her istek, tum makinalari, surekli mesgul ediyorsa, bolunme iyi yapilmamis demektir. Bu durumda normal RDBMS yapisina geri donulmustur. Hicbir avantaj saglanmamistir.

Tuesday, March 24, 2009

Proje Voldemort - I

SQL database'leri tahtindan etmek icin eforlar tam gaz devam ediyor. Google'in Bigtable veri tabani hakkinda yazdigi makale pek cok IT programcisi icin surpriz olmustu; Herkes veri depolamasi hakkindaki cekismenin hiyerarsik vs. iliskisel, ya da objesel vs. iliskisel duzlemde oldugunu dusunmekteydi. Iliskisel tabanlar girdikleri savasi 70'li yillarda kazandilar, fakat 21. yuzyilin Web uygulamasinin dehset gereklilikleri karsisinda onlar da yavas yavas mevzi kaybetmeye basladi. Gorunuse gore yuksek olcek dunyasinda kazanan ne objesel, ne hiyerarsik taban oldu. Kazanmaya baslayan giris seviye bilgisayar bilim dersinden hatirlayacagimiz o basit Hash veri yapisinin dagitik halinden ibaretti.

Iliskisel tabanlarin (RDBMS) sorunlarini onceki yazilarda gormeye baslamistik.

Eger ucuz, her yerde bulunabilen donanim (commodity hardware), ve open source bazli cozumler ariyorsak (bu noktaya donecegiz), verinin yatay bir sekilde degisik DB makinalarinda bolunecegini kabul ediyoruz demektir. Bunu kabul ettigimiz anda, zaten bir iliskisel tabanin tablolar arasinda tuttugu o guzel yabanci anahtar (foreign key) bazli iliskileri, butunluluk kontrollerini (integrity check) kullanmiyoruz anlamina gelir.

Veriyi niye yatay boldugumuzu hatirlayalim: Eger bir kullanici istegine servis etmek icin N tane DB makinasinda okuma/yazma yapiyorsak, bu olceklemeyi iyi yapamamisiz demektir. Her kullanici istegini ne kadar "tek" bir makinaya yonlendirebilirsek, o zaman DB kapasitesini arttirmak icin donanim, takviye makina eklemek o olcude yeterli olabilecektir. Yukler N makina yerine N+1 makina arasinda bolunurse, bu sistemin butunu icin bir ilerleme olacaktir.

Ek olarak, iliskisel sistemlerin bize cok kuvvetli indeks bazli, anahtar kolon olmayan kolonlar uzerinden sorgulama yapmamiza izin verdigini biliyoruz. Fakat Internet'in devasa veri depolayan sistemlerinde hicbir akillica sistem zaten ana anahtar kolonu haricindeki kolonlari sorgulamada kullanmaz. Kullaniyorsa da, bunu icin uygulama tarafindan ozel sekilde idare edilen bir veri yapisi kullanir. Facebook sisteminde "tum kadin kullanicilari bana getir" turunden bir sorgulama dusunebilir miyiz? Biraz abartsam da, isin ozu baglaminda anlatilmak istenen buna benzer bir durum.

Devam edelim: Onbellekleme ihtiyaci. Nesnelerimizi SQL uzerinden iliskisel tabana esliyoruz. Sonra onbellekleme ihtiyaci ortaya cikiyor, bu objeleri Hash temelli bir veri yapisina yaziyoruz! Zaten performans icin bu yapiya gecmisiz bile.. Bu baglanti bizim icin arka planda idare ediliyor, ama bu katmanlar arasinda cok fazla entegrasyon eforu demektir. RDBM -> ORM (Hibernate mesela) -> Cache -> Uygulama -> Kullanici derken pek cok katmandan geciyoruz, ve bu katmandaki her birimin ve onun bir alt katmanla olan iliskisi ayri ayri test edilmeli, uzun sure o sekilde kullanilmali ki problemler ortaya ciksin, duzeltilsin, vs. Ve tum bunlarin ustune yatay boldugumuz icin zaten o guzel JOIN kavramini kullanamaz hale geldik.

Biz kendi ihtiyaclarimiz icin arayisimizda yatay bolme, olcekleme dunyasinda tum RDBMS (ve OSS) temelli cozumlerin yari pismis oldugunu gorduk.

MySQL Proxy temelli cozumler de aslinda bizi hic tatmin etmedi. Hibernate Shards'da gelecek var gibi gozukuyor, fakat ORM uzerinde "bir katman daha" bizce fazla.. Zaten bu cozumlerin arkasinda gerekli enerjiyi de goremiyoruz; sebebi ortada. IT dunyasi bir kolektif butun olarak bir yone gitmeye baslamis, ve diger alternatilerden giderek oksijen cekilmeye basliyor. Couch DB'den baslayarak Amazon'un Dynamo yaklasimina kadar giden genis bir yelpaze bu. Dikkat edin: "Niye bu cozum" sorusuna cevaplardan biri olan "herkes yapiyor da ondan" cevabini en sona sakladim, cunku bu cok zayif bir iddiadir. Fakat tum usttekilerden sonra "niye herkes bunu yapiyor" sorusunun cevabini almis olduk herhalde, ve simdi butunun gittigi yonde kalmanin faydalarindan bahsedebiliriz. Bu tabii ki mevcut bilgiden ve tecrubelerden faydalanabilme avantajidir.

Voldemort

Aradigimiz sistemin ozelliklerine en iyi uyan Proje Voldemort oldu. Bu secimi yapisimizda onemli bir faktor suradaki yaziydi. Java arayuzu bizim icin cok onemliydi, iyi dokumantasyon, yatay dagilimin en bastan planlanmis bir konu olmasi cok onemliydi. Sistem buyudukce DB makinasi ekleyebilmeliyim ve aninda DB'nin kapitesi artmali. Bunun icin bir suru takla atmam, geceleri uyku kacirmam gerekmemeli.

Madem anahtar-deger veri tabanlari (hash tipi tabanlar yani) depolama kavramini daha basitlestirdiler, onlara erisim de hakikaten basit olmali. Couch DB anahtar-deger yontemi ustune bir de dokuman kavramini eklemis - hiyerarsik misin, hash misin? Nesin? Kafasi karisik bir teknoloji.

Voldemort bahsedilen tum gereksinimlere uydu. Su anda LinkedIn sirketinde canli/sonuc (production) ortaminda aktif olarak kullaniliyor. Performans problemleri yok (bir diger Java bazli cozum HBase hakkinda performans problemleri isittik, hemen arkamiza bakmadan kactik).

Veri Idaresi

Voldemort ile, mesela, objeler arasindaki iliskileri nasil idare edecegiz? User objesi dusunelim, onun arkadaslari User objeleri olsun. Voldemort'ta "store" kavrami var, bu iliskisel dunyadaki tablo kavramina tekabul etmekte. Bir User store'u olacak. Ayri bir Friendship store'u olacak. Kullanicilarin kendisi birincide, iliskileri ikincide depolanacak. Her iki store'da ana anahtar kullanici ID. Bu ID GUID bazli koca bir integer olabilir, ya da e-mail olabilir. Uygulamanin gereksinimleri bunu belirler.

Kullanici A icin makina #4'e gidebilecegim, o kullanicinin arkadas listesi, ID listesi olarak, o objenin uzerinde, anahtar-degerin deger kisminda yani, java.util.List'te olacak. Bazi ozet bilgiler denormalize olarak bu listede olabilecek. Detaylari gormek icin bir istek olursa, o arkadas ID'si kullanilarak makina #5'e gidilebilecek, ayni anda, A elindeki ozet bilgisi de guncellenecek. Bunu uygulama kodu halledecek. Diger makinalarda olabilecek B, C gibi kullanicilarin ellerindeki ozet onlar ayni detayi isteyene kadar guncellenmeyecek. Bu IT dunyasinda tembel okuma (lazy read) kavrami.. gercekten ihtiyaci olana kadar birine bir seyi vermeme durumu.

Voldemort arka planda veri bazli fiziksel bolmeyi yapacak, dokumanlarina gore sanal bolumler (partition) oncede tanimlanir, ve bir ID degerinin kendisi onu bir bolume esler. Bu bolunme icin "merkezi bir otoriteye" gitmek gerekmez, zaten bu yapilmamalidir, cunku olceklemenin ve cokuse dayanikliligin ilk kurali, merkezi otoriteden kurtulmaktir. Bu bolum, bir makina, yani bir fiziksel 'lokasyon' anlamina gelir. Bir ID'ye baktigimiz anda, hangi makinaya gidecegimizi biliyoruz demektir.

Open Source konusuna donelim. Eger yeterince paraniz varsa, o Oracle lisanslarina yuzbinlerce dolar atmaya devam etmek istiyorsaniz, muhakkak Oracle'i olcekleyebilirsiniz. Bu durumda "tek" tabanin "tek" makinasini buyuttukce buyutursunuz. Daha sukseli Oracle bolunme cozumleri mumkun, ama bu daha fazla ev ici (in house) DBA bilgisi gerektirir, tek bir ticari urune baglanirsiniz, ve Oracle sirketine daha fazla para kazandirmaya devam edersiniz.

Muhakkak SQL ve iliskisel tabanlar belli sistemler icin cok uygunlar. Fakat ideal kullanim haliyle, bir iliskisel tabanin ufak/orta olcek uygulamalar icin oldugu acik. Bir ORM kullanarak bile, nesnesel -> obje eslemesi hala "gariplikler" iceriyor, ve bu evlilik hicbir zaman dogal ve uygun bir evlilik olmadi, ihtiyactan dogan bir evlilik oldu.

Biz onumuzdeki yuksek olcek kullanimi icerecek proje icin Voldemort ile ilerlemeye karar verdik. Kullanilan diger teknolojiler Apache, JBoss, JBoss Seam, Javascript olacak. Hibernate ve MySQL'e ihtiyacimiz kalmadi.

Friday, March 20, 2009

Mysql Proxy

Hibernate Shards'in tamamlanmasini beklerken, ve uygulama kodlamasina baslamadan once alternatif bazi seceneklere bakmaya basladik. Isleyecegimiz seceneklerden biri Mysql Proxy, ve genel olarak bu tur yazilimlar uzerinden SQL veri tabanlarina baglanirken proxy'lerin nasil kullanilacagi.

Proxy ne ise yarar? Proxy, yer tutucu anlaminda, servis tarafindaki bir 'sey' ile ona 'baglanan' arasina gecen ve aracilik rolunu ustlenen bir ara program/katmandir. Bu ara programa baglaninca servisteki seye baglanmis gibi olursunuz.

Bunun faydalarindan biri, ara katmanda ek bazi islemleri yapabilir hale gelmektedir. Yani SQL proxy'leri bir veri tabaniymis gibi size bir servis sunarlar. Proxy'ler bunu ya JDBC seviyesinde, pur Java kodu ile, ya da tamamen DB yerine gecerek SQL seviyesinde yapiyorlar.

MySQL sirketinin kendi yazdigi, kendi database'leri icin hazirladigi proxy programi MySQL Proxy. Bu programi kurup, arka planda hangi veri tabanini (ya da tabanlari -host ve db ismi ile beraber-) yansitmasi gerektigini soyluyorsunuz ve Mysql Proxy bu arkadaki tabanlar icin bir gecis noktasi oluyor. Bunun yatay olcekleme, sharding ile alakasi surada: Bu ara katmanlar SELECT, INSERT gibi komutlarin icine bakarak, o komutu veri icerigine gore belli bir 'shard'a yonlendirme isini de yapabilir.

Bu durumda Java katmaninin Hibernate Shards'a ihtiyaci kalmaz, cunku yonlendirme isi JDBC'nin bile ruhunun duymadigi baska bir katmanda yapilacaktir. JDBC, MySQL'e konustugunu zannedecektir halbuki MySQL Proxy ile konusur olacaktir, onun uzerinden belli bir database'e yonlendirilecektir - Hibernate ve Java bununla alakadar olmayacaktir. Tabii onceden belirttigimiz gibi, yazilim mimarisi ve veriye erisim "stili" Hibernate kullanim seviyesinde 'sharded' kavramina hazir olacak, o baska. Iliskilere, vs. dikkat edilecek filan. Fakat bunlar yine pur Java/Hibernate seviyesindeki dikkat edilmesi gerekenler.

MySQL Proxy ilginc bir program: Bu programin kendisini de 'kodlamaniz' mumkun bir kere - Lua adinda bir programlama dilini destekliyor. Belli noktalara cengel (hook) koyulmus ve bu cengellere sizin programiniz takilabiliyor, ve iste o ara noktada istediginiz ek taklalari atabiliyorsunuz. O zaman SELECT icerigine bakip yonlendirme isi bir Lua programi olacak. Simdiden mevcut bir Lua programi, mesela, "yazim icin master'a okuma icin slave'e gitme" isini kodlamis. MySQL sitesinde paylasilan kodlardan biri. Pek cok diger kodlar var.

Sonuclari buradan paylasiriz. Testler devam ediyor.

Thursday, March 19, 2009

OpenJPA: Olmadi

OpenJPA testlerini yaparken baytkodlari tekrar islemden gecirdigini (enhance) ve bunu derleme zamaninda yapmamizi bekledigini farkettim. Hibernate bunu islem aninda (dinamik olarak) yapiyor. Bu enhance isi bana bir zamanlarin JDO'su ve Kodo'yu hatirlatti; baktim bu projelerden adamlar OpenJPA'ye gecmisler. Isin asli belli oldu. OpenJPA: OUT. Slice Hibernate ile kullanilabilirse ne ala (pek zannetmiyorum), yoksa Shards'i JPA usulu kullanmanin bir yolunu bulacagiz. Aslinda Shards projesi bunun farkinda ve uzerinde calisiyor. Doc'ta soyle demisler:

"Many of you will quickly realize that the configuration mechanism we've provided won't work if you're configuring your SessionFactory via JPA. It's true. We expect this deficiency to be addressed shortly."

Bu durumda bizim yapacagimiz, obje mimarimizi, semamizi sharding kavramina hazir hale getirmek ve Shards JPA destegini ekler eklemez ona gecmek. Teknolojinin en uc noktasinda (bleeding edge) olmak boyle bir sey. Hareketli bir hedefle calismayi ogrenmek gerekiyor.

OpenJPA ve Slice

Hibernate Shards'i su anda kontrol ediyorum. Kullanim sekli olarak EJB3 ortamina uyumlu bir kullanimi olmadigi gozukuyor.. Bu isleri biraz zorlastiracak ve acikcasi tercihim degil. Boyle bir paketi test etmeye basladigimda (evaluate), aklimda bekledigim, olmasi gereken bir kullanma sekli vardir; Eger Hibernate uzerinden sharding yapacaksa bir sistem, diyelim, o zaman persistence.xml uzerinde yapacagim bir kac ayar degisikligi ile verinin DB'lere dagilmaya basladigini gormek isterim. Shards'da bunu goremiyorum. SessionFactory, bilmemne uzerinde bir takim hareketler yapmamiz bekleniyor.

Simdi rakiplere bakmaya basladim: Mesela javax.persistence JPA standartina uyumlu OpenJPA paketini gordum. Bu paketin kullanimi ustte tarif ettigim gibi. Buraya nasil geldim? Slice denen Hibernate Shards'dan ilham almis bir paket uzerinden.

Arkadas Slice paketini OpenJPA uzerinden yazmis, eger iyi bir yatay olcekleme paketi ise o zaman sirf Slice icin OpenJPA'ye gecebilirim. Sonucta standartlar bunun icin degil midir?

Testler suruyor.

Bazi ek konular: Veriyi yatay bolmeye basladiginiz zaman, mimarinizin bunu yansitmasi lazim. Diyelim ki Facebook'u kodluyorsunuz, User class'inin arkadas listesinde User objeleri var. Adam kendi kendine referans ediyor yani (biz buna basketboldaki hareketten hareketle 'hook shot' derdik). Fakat bu durumda User XXX bir database uzerinde, User YYY baska bir database uzerinde olacak ve arkadas listesi alirken iki database uzerinden JOIN yapmaniz gerekecek (daha dogrusu JPA'in yapmasi gerekecek). Bu tur "attraksiyon" hareketlere simdilik izin yok.

Yani, iki shard arasinda iliskiye izin yok. Aslinda olmamasi daha iyi belki de.. Sonuc: Eger User class'inin arkadasi olacaksa, onun arkadaslari Friend gibi degisik bir class'ta yani baska bir tabloda olmali. Ayni User kisisi farkli Friend satirlarinda denormalize olarak olabilmeli, sonuc olarak farkli shard/db uzerine yazilabilmeli.

Ozet olarak uzerinden veri dagitimi yaptiginiz veriyle, ana tabloyla iliskide olan her "yan veri", "yan tablo" tamamen o oteki DB'ye gidebilmeli.

Facebook'un veri yapisinin da bu sekilde olduguna emin olabilirsiniz. Aynen App Server dunyasindaki "yapiskan oturum (sticky session)" gibi, bir DB'ye veri icin gittiginizde o operasyon surecinde o DB'ye yapismalisiniz.

Hibernate Shards

MySQL'i olceklemenin yontemlerinden biri master/slave kurulusudur. Bu kurulusta, tum veri yazma islemleri master'a yapilir ve bu yazim operasyonlari master'dan slave'lere belli araliklara replicate edilir. Tum okumalari slave'lere gider. MySQL replicate isini oldukca hizli yapmaktadir, bu sebeple fena bir cozum degildir. Eger uygulamaniz 'cogunlukla okuyan (read-mostly)' turunden bir uygulama ise (youtube gibi), master'in uzerindeki yuk fazla olmaz.

Yukun cogu okunan slave MySQL veri tabanlarina gidecektir.

Bir diger yontem sudur: Verinin icerigine bakarak, hem yazim hem okuma operasyonlarinin ikisinin de belli/tek (unique) bir MySQL nod'una yonlendirmek. Mesela ilk isminin ilk harfi A-F arasindaki musteri kayitlari Nod#1'e, ilk isminin ilk harfi G-R arasindakiler Nod#2'ye gitsin demek gibi.

Bu stratejiye 'yatay olcekleme' stratejisi deniyor, cunku herhangi iki MySQL nod'u arasinda bir hiyerarsi iliskisi yok. Herkes esit.

Bu strateji IT dunyasinda oldukca eskidir. ABD'de bir arkadasim bile calistigimiz danismanlik sirketinde (ki danismanlik sirketleri genelde framework islerine girmezler) boyle bir SQL paketi yazmisti - SQL komutlari ile DB arasina oturan bir katman idi bu, SQL icindeki veriye bakiyor, ve elindeki DB baglantilarindan ona gore hangisini kullanmasi gerektigini biliyordu.

Bugun bu ara katman Java dunyasi icin Hibernate'dir. Eh, Hibernate hem verimizi, veri komutlarimizi idare ederken bu tur yatay veri bazli dagitim (sharding) yapsa iyi olmaz mi?

Yapmaya baslamis. Hibernate Shards projesi, bunu amacliyor. Sistemi ayarladiktan sonra kodunuzun geri kalani hala bilinen Hibernate operasyonlarini kullanmaya devam ediyor, Hibernate Shards arka planda DB islemini veriye bakarak gereken makinaya yonlendiriyor.

Bu konu hakkinda ek yazilar gelecek.

Wednesday, March 18, 2009

Git

Ekteki video'da Linus Torvalds'in Git versiyon kontrol sistemi hakkindaki konusmasini izleyebilirsiniz. Git sistemini yazan Torvalds'in kendisi; ve Linux kernel kodunun boyutlari ve onemi goz onune alinirsa, Linus'un kendi isine yarayacak bir VKS yaratmak icin gerekli motivasyona sahip oldugu acik... Her zaman oldugu gibi Linus'un bu konuda da guclu fikirleri var - ozellikle CVS ve Subversion hakkinda soylediklerinn iyi dinlenmesi lazim. Torvalds CVS ve Subversion sistemlerinden pek hoslanmiyor :)

Git dagitik sekilde calisabilen bir VKS. CVS ve Subversion aksine, her gelistirici kendi kod deposuna sahip, ve bu depoya check-in yapabiliyor. Bu sistemde kimse "merkez" degil - herkes birbirinden serbest sekilde merge edebiliyor. Bu Internet'in ruhuna uygun. Ayrica merge islemi optimize edilmis ve cok kolaylastirilmis. CVS'te branch yaratanlar ve merge etmeye ugrasanlar bilir, hic de kolay bir islem degildir.

Son zamanlarda ardi ardina gelen tool merkezli gelismelere bakinca, kod gelistirme aleminde bir koca degisim yasandigini goruyorum. Hersey kolaylasiyor ve kabuk degisimine ugruyor. IT baglaminda, en azindan, CVS'ten, C++ dilinden ezelden beri sikayet ederdik - ikisinden de kurtulduk. Linux geldi, Ubuntu geldi, Java, Ajax, JBoss Seam, Python, Ruby... Siteler renklendi, basitlesti, kullanim kolayligi rahatlasti. Simdi de Git geldi. Iyi gidiyor!


Monday, March 16, 2009

Icerik Guncelleme

JBoss ile gelistirme yaparken sadece xhtml sayfalari, css dosyalari degisti ise, sadece bu degisen icerigi JBoss'a gondermek yeterli; EAR derlemesi yapip, JBoss'un tekrar baslatilmasina gerek yok. Hot-deploy devrede olsa bile bu baslatma uzun zaman alabiliyor. Icerik guncellemesi icin bir jboss_tmp_dir.py adinda bir Python script ve bazi build.xml degisiklikleri yeterli.
import shutil
import os
import glob

basedir = "[JBOSS DIZIN YERI]"
dir = basedir + "/server/default/tmp/deploy"

os.chdir(dir)

list = glob.glob('*[SIZIN EAR ISMINIZ]*contents*')
list.sort()
if len(list) < 1: raise RuntimeError
to = dir + "/" + list[len(list)-1] + "/" + "pocketbudda-exp.war"
print to
Bu script'i build.xml icinden soyle cagirabiliriz:
  <target name="x">
<exec outputproperty="jboss.tmp.dir" executable="python">
<arg line="src/script/jboss_tmp_dir.py"/>
</exec>
<copy overwrite="yes" toDir="${jboss.tmp.dir}">
<fileset dir="src/view"/>
</copy>
</target>
Python script icinde JBoss'un sayfalari EAR'den cikartip koydugu tmp altindaki dizinin nerede oldugunu buluyoruz. Bu dizinin yeri EAR her yuklendiginde degistigi icin eger buraya parasutle dosya atacaksak her seferinde nerede oldugunu tekrar bulmamiz gerekiyor.

Ayrica yukarida Ant ve Python arasindaki baglantinin nasil kurulacagini da goruyoruz. outputproperty bu amacla kullaniliyor, Python icinde "print" ile ekrana basilan her sey, Ant'e outputproperty icine set edilecektir.

Thursday, March 12, 2009

Bilimsel Hesaplama: Hangi Dil?

Matlab'e alternatifler listesinde NumPy ve SciPy ile takviye edilmis Python'un iyi bir alternatif olacagini okudum.

Son not: Artik Python kullaniyoruz.

Wednesday, March 11, 2009

Wine

Ubuntu uzerinde Windows emulasyonu yapan Wine gayet guzel isliyor; Simdiye kadar hic bir Windows programimi isletmemezlik etmedi. Zaten cok fazla "Windows'a ozel" programim kalmamisti, tek tuk olanlarin hepsi Wine ile isler halde.

Hangi programlar bunlar? Bir tanesi favori SQL onyuzu programim SQLyog. Ne kadar aradiysam da bir turlu bu programin yanina yaklasan bir Linux varyantini bulamadim. Diger program ise Unreal Tournament. Evet! O koca, diskten haldir huldur kurulan, bir suru grafik iceren Birinci Sahis Ates Etme oyunlarindan. Bu programa ihtiyacim var cunku yazdigim robot simulator Ardabot UT'ye baglanarak calisiyor. Unreal Tournament Ardabot'un "Matrix'i" oluyor. Iceri girip etrafta geziniyor bizim ufaklik. Neyse; Wine UT'yi bile kurabildi, yanliz grafik arabirimini degistirerek grafik kartindan "software" secimini yapmaniz lazim. Grafik icin yazilim kullanmak demek, video kartinin yaptigi bazi isleri yazilimin ustlenmesi demektir. Eger hizli bir islemciniz var ise, bu degisiklik problem olmayacaktir.

Sunday, March 8, 2009

InnoDB ve Hibernate

MySQL her tablonun depolanma seklini secmenize izin verir. Depolanma sekli (storage engine) secenekleri MyISAM, InnoDB gibi secenekler. Bu seceneklerden InnoDB islemsel (transactional) depolama yapabilmenize izin verir, MyISAM FULLTEXT kavramini kullanmaniza izin verir, vs. Her iki metotun kendine has guclu ve zayif taraflari vardir. Mimari secim olarak bizim tavsiyemiz islemsel olan InnoDB kullanilmasi, arama icin Lucene paketinin kullanilmasi. MyISAM kullanimini tavsiye etmiyoruz.

Her tabloyu yaratirken depolama seklini CREATE TABLE komutuna ekleyerek secebiliyoruz. Fakat eger tablolari Hibernate'e otomatik olarak yarattiriyorsak, yani DDL'i Hibernate uretiyorsa, o zaman istedigimiz depolama seklini bir sekilde Hibernate'e bildirmemiz lazim.

Yeni bir dialect yaratarak bunu cozebiliriz:
package vs.vs;

import org.hibernate.dialect.MySQL5InnoDBDialect;

public class CustomMysqlDialect extends MySQL5InnoDBDialect {

public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
}
}
persistence.xml icinde

<persistence ...
....
<property name="hibernate.dialect" value="vs.vs.CustomMysqlDialect">
....
</persistence>

Kaynak

Wednesday, March 4, 2009

Site Ismi Bulmak

Yeni Internet sitenize isim ararken hangi ismin alinip, alinmadigini, verdiginiz ismin degisik varyasyonlarina da hemen bakip rapor edebilen guzel bir site: Psychicwhois.

Tuesday, March 3, 2009

FriendFeed ve MySQL

Friendfeed.com programcilarindan Bret Taylor blogunda MySQL ile kumeli ortamlarda nasil calistiklarini anlatti. Canli, calismakta olan db'lerde indeks eklemenin, silmenin cok zaman aldigini ve bunun canli tablolari kitledigini, sonuc olarak sitenin optimal isleyisini engellediginden bahsetti.

Cozum olarak DB yapilarini tamamen degistirmisler. Klasik iliskisel yapi yerine veri iceren tek tablo Entities diye bir tablo, erisim icin UUID bir id tanimlanmis. Indeksler bu tek tablo tipine erismek icin, ihtiyac duyuldugu sekilde yaratilip silinebilen "ek tablo semalari" haline gelmisler. Yeni tablo yaratmak canli siteye bir engel teskil etmiyor, o problem boyle cozulmus. Silinmek istenen indeks tablolarina koddan erismeyi birakiyorsun, o kadar. O da halloldu.

Indekslerin nasil kullanilacagini evde pisirdikleri in-house DB katman kodu biliyor.

Post'un yorumlarina bakilirsa, MySQL'in diger tur db'lerden bazi eksikleri var. "Indeks guncellemenin db kitlemesi" problem Oracle da gorulmezdi mesela. Fakat MySQL'in bedava olmak gibi bir avantaj var, ayrica replikasyon, veri temelli bolme (sharding) hala isleyen, ve ici disi iyice bilinen ozellikler.

Bu yaklasim hosuma gitti; Ustunde calistigim site servis tarafi kodlama asamasina gelince, aynisini Java'ya port edip kullanmaya baslayabilirim. Bu mekanizmayi, eger yazarsam, acik olarak paylasacagim.