Bu yazıda, veri ile ilgilenen herkesin çok duyduğu, bir seviyede aşina olduğu ve çokça karşımıza çıkan kavramlardan bahsedeceğiz. Bu kavramlar ve teknolojiler üzerine konuşacak, neden ve nasıl oluştuklarını anlamaya çalışacak, avantaj ve dezavantajlarını tartışacağız.

1. İlişkisel veritabanı sistemleri

Veri ile alakalı çalışma yapan çoğu kişinin de bildiği üzere, tek bir bilgisayar üzerinde çalışan ilişkisel veritabanı sistemleri uzun yıllar boyunca veri sektörüne başarıyla hizmet etmiştir. Bu sistemlerin hayatımıza girmesi, 1970 yılında Dr. Edgar F. Codd tarafından yazılan “A Relational Model of Data for Large Shared Data Banks (Büyük Paylaşımlı Veri Bankaları için İlişkisel Bir Veri Modeli)” adlı makale ile büyük ölçüde hızlandı. Bu model o zamanlardan bu yana hala yoğun olarak kullanılmaktadır ve bu yüzden yazılım ve veri dünyasının en başarılı icatlarından biri olarak gösterilmektedir. Elbette ki bu ilk modelin üzerine birçok geliştirme ve ekleme yapıldı fakat ana prensipler çoğunlukla aynı kaldı.

Örnek ilişkisel veri tabanı

Hepimizin bildiği üzere, bu ilişkisel model tanıdık SQL dilini kullanmaktadır ve bu da onu analitik sorguları desteklemesi açısından çok güçlendirmektedir. İlişkisel modeldeki ilişki kavramı da, aslında bilinenin aksine tablolar arasındaki ilişkilere değil, matematikteki “ilişki (bağlantı)” kavramına dayanmaktadır. Zaten SQL dili de matematikteki küme teorisi ve önerme mantığı temellerine dayalıdır. Bu iki temel birleşerek ilişkisel modeli ortaya koymuş, bu modelin üstüne de SQL dili bina edilmiştir.

İlişkisel Veritabanı Sistemleri (RDBMS)’nin endüstrinin çoğunluğu tarafından benimsenmesinde kompleks veri sistemlerini ilişkisel bir biçimde rahatlıkla ifade edebilmesi ve bu ilişkisel sistemi yine SQL üzerinden kolaylıkla sorgulayabilmesi etkili olmuştur. SQL dili geliştiricilere basit ve anlaşılabilir bir dil vasıtasıyla veriyi kolayca manipüle edebilme fırsatı sunmuştur. Ek olarak, veritabanı objelerini rahatça oluşturabilme veya değiştirebilme, kullanıcılara yeni erişimler tanıyabilme veya bu erişimleri geri alabilme gibi özellikler de barındırmaktadır. Veriye sorulmak istenen potansiyel sorular, SQL dili ile zorlanılmadan ifade edilebilmektedir.

SQL’in yanı sıra, RDBMS’lerin ACID prensiplerini sağlaması ve “transaction” kavramını desteklemesi de bu sistemlerin benimsenmesinde etkili rol oynamıştır. ACID prensiplerine birazdan değineceğiz, öncesinde “transaction” kavramına kısaca bakalım. “Transaction” kavramı, “The Transaction Concept: Virtues and Limitations (Transaction Konsepti: Üstünlükleri ve Sınırları)” adlı eserin yazarı Jim Gray tarafından da belirtildiği gibi, “Bir durum değişikliği” dir. Yani veritabanı içerisinde bulunan verinin bir durumdan başka bir duruma geçmesi de denebilir. Transaction’lar fiziksel olarak gerçekleşmeden önce sanal olarak gerçekleşir, böylece eğer transaction esnasında istenmeyen bir işlem olursa, “ROLLBACK” komutu kullanılarak işlem geri alınabilir. Bir problem yoksa, “COMMIT” komutuyla transaction tamamlanabilir. Bir transaction’ın başarılı olduğunun ölçütü ise, ACID prensipleridir. Bu prensipleri aşağıdaki gibi sıralayabiliriz:

  • Atomicity (Atomik olmak-tekillik): Bir transaction içerisindeki tüm işlemler başarıyla tamamlanmadıkça, transaction başarılı olmuş sayılamaz. Bir işlemin tamamlanması ve bir diğer işlemin tamamlanamaması söz konusu olamaz. Ya tüm işlemler başarılı olmalı, ya da hepsi başarısız olarak iptal edilmelidir.
  • Consistency (Tutarlılık): Herhangi bir transaction vasıtasıyla bir durum değişikliği yaşandığında, veritabanı içerisinde bu durum değişikliğine aykırı herhangi bir veri kalmamalıdır. Aksi takdirde, birbiriyle çelişen veriler veritabanından okunabilir, bu da transaction’ın başarısız olduğu anlamına gelir.
  • Isolated (İzole edilmiş): Birden fazla transaction işlemi bir veritabanı içerisinde devam ediyorsa, bunlar birbirleri ile çakışmamalı, hepsi kendi alanında devam etmelidir. Birden fazla transaction aynı veriyi aynı anda değiştirmeye çalışıyorsa, birbirlerinin tamamlanmalarını beklemelidir ve bir anda sadece bir tanesi veri üzerinde değişiklik yapmalıdır.
  • Durable (Dayanıklı): Bir transaction sonucunda oluşan değişiklikler, bozulmadan veya silinmeden veritabanında kalmalıdır. İkinci bir transaction aynı veriyi modifiye etmek istediğinde, bir önceki transaction’ın yapmış olduğu değişiklikleri görebilmeli ve bunların üzerinden devam edebilmelidir.

İşte bu ACID prensipleri ve transaction desteği, RDBMS sistemlerinin gittikçe yaygınlaşmasında büyük rol oynamıştır. Fakat RDBMS sistemlerinin tek güzel yönleri elbette bunlar değildi. Bir örnek daha vermek gerekirse, ilişkisel veritabanı sistemlerinde veriyi çok daha rahatlıkla organize etmek için şemalara bölmek de mümkündü. Her ne kadar her senaryo için bu şemalar iş görmese de, genellikle çok kullanışlı ve işe yarar bir halde karşımıza çıktılar. Şemalar sadece veriyi organize etmede değil, kullanıcıların yetkilerini sınırlandırmada da çok faydalıydı. Her kullanıcıya sadece kendisiyle ilgili şemaya erişim yetkisi vermek ve bu yetkileri de SQL dili vasıtasıyla kolayca yönetebilmek büyük avantaj sağlıyordu.

Üstte saydığımız bu faydalı özellikler RDBMS sistemlerini çoğu veri senaryosu için biçilmiş kaftan haline getiriyordu ve hala da getirmeye devam ediyor. Yukarıda bazı ifadelerde geçmiş zaman kullanmış olabiliriz, fakat bu RDBMS’lerin geçmişten günümüze gelişme aşamalarını anlatmak adınaydı. İlişkisel veritabanı sistemleri ve SQL dili hala günümüzde de yoğun olarak kullanılmaktadır ve görünen o ki kullanılmaya da devam edecektir.

İlişkisel veritabanı sistemleri ile ilgili problemler

RDBMS sistemleri hala yoğun olarak kullanımda olmasına rağmen, günümüzde verideki hacim, çeşitlilik ve üretim frekansının hızla artmasıyla beraber, bu sistemler bazı problemler yaşamaya başladı.

1. Kapasite problemleri

Öncelikle, bu veri akışı artışıyla beraber tek bir bilgisayar üzerinde çalışan RDBMS sistemlerinin kapasitesi bu veriyi saklamaya ve işlemeye yetmemeye başladı. Sadece verinin hacmi ve frekansı değil, gelen veri formatlarının çeşitliliği de RDBMS sistemlerini zorluyordu.

Probleme çözmeye yönelik geliştirilen yöntemler:

Veri akışıyla baş edebilmek adına denenen ilk ve en doğal çözüm, eldeki makinenin donanımsal gücünü artırmak oldu. Varolan RAM artırıldı, diskler kuvvetlendirildi ve ek CPU eklendi. Bu işleme literatürde “Vertical Scaling (Dikey Ölçekleme)” adı veriliyor. Bu çözüm, bir müddet boyunca RDBMS kullanıcılarını gerçekten de rahatlattı. Fakat bir noktada bu da yetmemeye başladı, çünkü verinin hacmi giderek artıyordu. İşte tam burada, dikey ölçeklemenin bu işi kurtaramayacağına karar verildi ve “Horizontal Scaling (Yatay Ölçekleme)” adı verilen kavram konusunda kafa yorulmaya başlandı. Yatay ölçeklemede, varolan tek makinenizi güçlendirmek yerine, sisteme başka makineler ekleyerek bunların paralel çalışmasını sağlıyorsunuz. Ve böylece tek bir server mantığından çıkarak birden fazla serveri dağıtık bir mimaride birleştiriyor ve bir “cluster” elde ediyorsunuz. Baktığınız zaman bu şekilde düşünmek çok daha doğal, çünkü dikey ölçeklemenin bir sınırı var, elinizdeki tek bir makineyi ancak bir yere kadar güçlendirebilirsiniz. Fakat yatay ölçeklemenin teorik olarak bir sınırı yok (teorik olarak diyorum, çünkü pratikte burada da sınırlamalar ortaya çıkabiliyor).

Yatay vs Dikey Ölçekleme

Dağıtık mimarilerin nasıl çalıştığına birazdan bakacağız, fakat bu dağıtık mimariler de geldiklerinde aslında kendi sorunlarını beraberlerinde getiriyor. Bunlara da ilerleyen bölümlerde değineceğiz. Fakat buralara gelmeden önce, RDMBS’lerde dağıtık mimari problemi dışında hangi problemler ile karşılaşıldı, bunlar hakkında da konuşmak istiyorum.

2. Performans problemleri

Bahsedilmesi gereken bir ikinci problem, üstte söylediğimiz ilişkisel sistemin dezavantajları. Bunlardan en büyüğü, bu ilişkileri kullanarak veri setlerini birbirlerine bağlamak için kullanılan join işlemleri. Veritabanı sisteminiz göreceli olarak küçük olduğunda ve tablolarınızda makul miktarda satır olduğunda bu joinlerin yarattığı performans problemleri gözardı edilebilir. Fakat daha büyük veri hacimlerine doğru ilerlendiği zaman joinler gerçekten çok yavaş gerçekleşir hale gelebilir ve bu da performans olarak büyük eksiler doğurur. Datayı almak isteyen tarafın joinlerin yarattığı yavaşlık yüzünden bayağı bir süre beklemesi çok görülen bir vakadır.

Probleme çözmeye yönelik geliştirilen yöntemler:

Bu probleme de çözüm üretmek adına, genellikle sorgular optimize edilmeye çalışılır. Gereksiz join işlemleri varsa bunlar kaldırılmaya ve sorgular sadeleştirilmeye uğraşılır. Genel olarak daha basit SQL sorgularıyla iş çözümlenebiliyorsa, o yola gidilir. Fakat bazı senaryolarda bu da imkansızdır. Yani sizin uygulama katmanınızdaki (veriyi okuyan katman diyebiliriz) sorgular en fazla bir yere kadar optimize edilip sadeleştirilebilir. Bir yerden sonra, sorgu bazında elinizden bir şey gelmeyecektir. İşte tam bu noktada, artık geliştiricilerin gözü uygulama katmanındaki sorgulardan vazgeçerek veritabanı katmanındaki mimariye yönelir ve normalizasyon kurallarından feragat edilerek veri denormalize hale getirilir. Böylece sade bir mimari kullanılarak joinler ciddi ölçüde azaltılır. Aslında bu senaryo size tanıdık gelmiş olabilir çünkü herkesin bir seviyede aşina olmuş olabileceği veri ambarı mimarisinin doğuşudur bu. Fakat bu hikayenin sonunu siz de tahmin ettiniz, bir yerden sonra geleneksel veri ambarı mimarisi de yetmemeye başlayacaktır. Bu da işte bir üstte bahsettiğimiz dağıtık mimari ihtiyacını tekrar gündeme getirecektir.

3. Erişilebilirlik problemi

Dağıtık mimariye giriş yapmadan önce, RDBMS’ler özelinde karşılaşılan son bir problemden daha bahsetmek istiyorum. Üstte “transaction” kavramından bahsetmiştik ve verideki bir durumu değiştirdiğini söylemiştik. Fakat transaction bunu yaparken, değiştirdiği verinin tablosunu da kilitler. Bunu yapmasındaki sebep, bir veride aynı anda birbirleriyle çelişebilecek modifikasyonlar yapılamamasını sağlamak ve okuyucuların da çelişkili veri okumasını engellemektir. Böylece transaction işlemi tabloyu kilitleyerek, tüm okuma ve yazma işlemlerinde veri tutarlılığını sağlamış olur. Farklı okuyucuların aynı datayı okumayı talep etmesi üzerine, bu kilitleme işlemi sayesinde çelişki içermeyen tutarlı bir data tüm okuyuculara sunulabilecektir. Fakat bu kilitleme işleminin çok belirgin bir dezavantajı vardır, o da kilitleme esnasında datanın erişilebilir olmayışıdır. Yani aslında bu tutarlılığın bedeli, erişilebilirlikten taviz vermek ve veriyi okumak isteyenleri de transaction işlemi tamamlanıp kilit açılana kadar bekletmektir. Zaten bu durum da CAP teoreminin ana konusudur, ona da yazının ilerleyen bölümlerinde değineceğiz. Hızlı cevap gerektiren bazı büyük sistemlerde ise bu erişilebilirlik ve bekleme durumu çok büyük problemler yaratmaktadır.

Probleme çözmeye yönelik geliştirilen yöntemler:

Saymış olduğumuz bu problemlere çözüm olarak alternatif metodlar da denenmektedir. Bir tane örnek verecek olursak, varolan veritabanı sistemlerinin üzerine bir “cache layer” eklenmesini gösterebiliriz. Bu katman, çok fazla kullanılan ortak sorgu paternlerini RAM üzerinde tutmaya olanak sağlar. Bu sayede, memory (RAM) içerisinde veri saklama ve sorgulara hızlı cevap verme imkanı doğmaktadır. Verinin RAM üzerinden okunması, disk üzerinden okunmasına göre çok daha hızlı olduğundan, bu çözüm yolu da çok fazla kullanılmaktadır. Cache layer dediğimiz bölge, veritabanı sisteminden tamamen ayrı konumlanabilir ve kendi dağıtık mimarisine sahip olabilir. Böylece uygulamalar tarafından da ulaşılabilir. Piyasada bu cache tabakasını sağlayan birçok teknoloji bulunmaktadır(Redis, Memcached gibi). Fakat bu çözüm de elbette ki kendi problemleriyle gelmektedir. Bunlardan bir tanesi, cache tabakası ve veritabanı arasındaki veri tutarlılığını sağlamaktır. Bunu yapmak da ekstra efor gerektirecektir. Elbette kendine has başka ufak problemleri de vardır, fakat yazıyı çok uzun tutmamak adına burada fazla detaya girmeyelim.

Buraya kadar olan bölümde, RDBMS sistemler konusunda karşılaşılan önemli problemlerden ve bunların çözümlerinde kullanılan yöntemlerden bahsettik. Artık yavaş yavaş dağıtık mimariler hakkında konuşmaya başlayalım.

2. Dağıtık mimariler

Üstte bahsettiğimiz nedenlerin tümünün, aslında bir şekilde bizi dağıtık mimarilere ve yatay ölçeklemeye götürdüğünü görmüştük. Örneğin join işlemleri maliyeti yüksek olan işlemler, fakat bu işlem dağıtık bir mimaride farklı işlemcilere parça parça paylaştırıldığında, çok daha efektif bir biçimde tamamlanabilir. Ya da dikey ölçeklemenin yetmediği durumlarda, sistem izin verdiği müddetçe ekstra makineler eklenerek cluster genişletilebilir. Fakat dağıtık mimariler konusu, burada anlattığımız kadar basit değildir. Bir sistemi dağıtık hale getirmek ciddi uğraş ve dikkat gerektirir. Dağıtık mimariler ve dağıtık veri işleme (distributed computing) bilgisayar biliminin başlı başına uğraştığı ayrı bir konudur. Yazıya devam etmeden önce, dağıtık mimarilerden kısaca bahsedelim ve yazının geriye kalanı için bir temel oluşturalım.

Buraya kadar da ara ara bahsettiğimiz gibi, dağıtık mimarilerde birden fazla makine vardır ve bu makineler ayrı ayrı hesaplamalar gerçekleştirebilirler. Hepsinin kendine has kaynakları (örneğin kendi RAM’leri) vardır ve bu kaynaklar sayesinde verinin bir bölümünü işleyebilirler. Fakat elbette bu makineler birbirleri ile haberleşmek durumundadır. Aksi takdirde tutarsız veriler ortaya çıkabilirdi. Dolayısıyla bu makineler kendileri veri işlemelerinin yanında, bir mesajlaşma sistemi vasıtasıyla da birbirleri ile konuşurlar. Her makine kendi kaynaklarını kullanarak verinin kendisine düşen kısmını işlediği için, aslında verinin diğerlerinden bağımsız ve ayrık bir görüntüsüne sahiptir. Her makinenin girdisi ve çıktısı farklıdır. Mesajlaşma sistemi sayesinde, bu birbirinden ayrı süreçler birleştirilir, tutarsızlıklar giderilir ve böylece makinelerin birbirlerinden haberi olur.

Bugüne kadar çok aşina olup duyduğumuz bir başka terim de paralel veri işlemedir. Paralel ve dağıtık mimariler aslında birbirlerine çok benzerdir ve gerçekten de sektörde çok farklı noktalarda birbirlerinin yerine kullanılabilmektedir. Aynı zamanda bu konularda farklı kaynaklar da birbirlerinden farklı şeyler söylemektedir. Fakat bunları derlemeye kalktığımızda, genel olarak bu iki terim için aşağıdaki detaylara ulaşıyoruz.

Paralel veri işlemede, mimaride ortak bir memory (RAM) vardır ve tüm işlemciler bu ortak memory’e ulaşarak birbirleri arasında bilgi paylaşımı yaparlar ve böylece sistemin tutarlılığını sağlarlar.

Dağıtık veri işlemede, işlemciler (bilgisayarlar) kendi özel memory’lerine sahiptir ve ortak bir memory yoktur. Burada ise tutarlılık yukarıda da bahsettiğimiz gibi mesajlaşma sistemleri ile sağlanır.

Dağıtık ve paralel veri işleme

Farkı görsel olarak da anlamak adına, Wikipedia’dan aldığım şu resme bakalım:

Bu görselde b şeması bir dağıtık sistemi, a şeması ise paralel sistemi gösteriyor. Memory farkları üstte de bahsettiğimiz gibi paralel sistem için ortak iken, dağıtık sistem için ayrık olarak gözükmekte.

Fakat bu resim ve detaylar dahi, sektörde herkes tarafından üzerinde uzlaşılmış değil. Bahsettiğim gibi, paralel ve dağıtık kavramları birbirleriyle çok iç içe geçmiş olduğundan netlikleri de kısmen kaybolmuş durumda.

Dağıtık sistemlerde kullanılan birkaç mimari vardır, bunların da bazılarından kısaca bahsedelim:

Client-Server: Client’ların veriye ulaşmak adına server’a istek gönderdiği ve aldığı veriyi de kullanıcılara formatlayarak gösterdiği mimarilerdir.

n-tier: Web uygulamalarının çoğunun kullandığı mimaridir, bu mimari içerisinde veri yönetimi, işleme ve sunum katmanları birbirinden ayrıdır ve farklı yazılımlar tarafından gerçekleştirilir.

Peer-to-peer: Bu mimaride, servis ya da ağ kaynaklarını yönetmek adına ekstra makineler yoktur. Tüm sorumluluklar eşit bir şekilde mimarideki bilgisayarlara dağıtılmıştır ve bu bilgisayarlar hem client hem de server görevi görürler.

Dağıtık mimariler hakkında apayrı bir makale yazılabilir ve bu işin teorik temellerine kadar inilebilir. Fakat elbette bunlar bizim yazımızın konusunun dışında olduğundan, biz bunlara burada değinmeyeceğiz.

Bunun yerine, bu dağıtık mimarilerin hem ilişkisel hem de ilişkisel olmayan sistemlerdeki kullanımlarını inceleyecek ve NoSQL’in doğuşuna bakacağız.

3. NoSQL veritabanları

Yazının ilk kısmında, RDBMS sistemleri ile ilgili problemlerden bahsetmiş ve sonrasında da bunların çözümüne bir temel oluşturması adına dağıtık mimariler konusuna giriş yapmıştık. İşte NoSQL veritabanları, RDBMS problemlerini dağıtık mimariler kullanarak çözmeye çalışan ve bunun sonucunda tamamen bambaşka bir yapıya ulaşan veritabanı sistemleridir. İlişkisel olmayan bu veritabanları, veri mimarisine başka bir bakış açısıyla yaklaşır ve sorgulara hızlı cevaplar verebilmek üzere kuruludur. Bu da onları web ölçekli uygulamalar için çok müsait bir yapı haline getirir.

NoSQL teriminin, “Not Only SQL” ifadesinden türetildiği konusunda sektörde fikir birliği vardır ve bu da aslında sadece SQL’in sunduğu imkanları desteklemekle kalmayan veritabanları gibi bir anlama çıkmaktadır.

Bu veritabanı sistemleri genelde dört başlık altında toplanır, fakat daha fazla kategoriye ayıranlar da mevcuttur. Biz burada dört ana başlığı inceleyelim:

  1. Key-Value (Anahtar-Değer) Veritabanları: Adından da anlaşılabileceği gibi, bu veritabanlarında veri bir anahtar ile temsil edilir ve bu anahtarın değerinde de birden fazla özellik bulunabilir. Değerler kendi anahtarlarıyla beraber saklanır ve düzenli olarak da çoğaltılır. Örnek verecek olursak; Dynamo DB, Voldemort ve cache sistem olarak da Redis verebiliriz.
  2. Wide-Column (Kolon-Odaklı) Veritabanları: Bu sistemlerde veri geleneksel satır bazlı saklama bakış açısı yerine sütun bazlı saklanır. En bilinen örnekleri Apache HBase, Kudu ve Druid’dir denebilir.
  3. Document (Döküman) Veritabanları: Döküman veritabanlarında adından da anlaşılabileceği gibi saklanan ana birim bir dökümandır. Bu döküman JSON, XML ya da YAML gibi popüler döküman formatları dışında elbette başka alternatifler de olabilir. MongoDB bu tarz veritabanlarının en bilinen örneğidir.
  4. Graph (Grafik) Veritabanları: Bu veritabanı sistemlerinde veri bir grafik halinde saklanır. Burada grafikten kasıt elbette pasta grafik, sütun grafik gibi grafik türleri değildir. Grafik derken aslında kastedilen bir ağdır. Örneğin köklerden ve kenarlardan oluşan bir sosyal ağ, bir grafik olarak temsil edilebilir ve bu veritabanlarında saklanılabilir. Köklerin ve kenarların kendilerine has özellikleri olabilir. Veriler de bu şekilde saklanır ve analiz edilir. Bu tarz veritabanlarının en bilinen örnekleri ise Neo4J ve JanusGraph’dir. Hatta grafik ifadesinin daha net olabilmesi açısından buraya aşağıdaki gibi de bir görsel ekleyelim(mavi ve mor yuvarlaklar kök, oklar ise kenarları ifade etmektedir):

Örnek grafik veri tabanı

Üstte saydığımız kategoriler dışında, endüstride NoSQL tabanları başka kategorilere de ayrılmıştır fakat herkesin üzerinde uzlaştığı dört ana başlık bunlardır. Biz de daha fazla detaya girmemek adına bu bölümü bu dört farklı kategoriyle sınırlı tutacağız.

NoSQL veritabanlarının özellikleri

NoSQL sistemlerin adının klasik SQL’den daha fazla özelliği desteklemelerinden dolayı geldiğini üstte söylemiştik. Bu sistemlerdeki veri modelleri, buna göre düzenlenmiştir. Unutmayalım ki bunlar ilişkisel olmayan sistemlerdir ve dolayısıyla SQL’de gördüğümüz gibi JOIN işlemleri kullanılarak tabloların birbirlerine bağlanması genellikle söz konusu değildir. Bu da aslında üstte saydığımız JOIN işlemlerinin yavaşlığı problemine bir noktada çözüm sunmaktadır.

Yüksek erişilebilirlik

Ek olarak, bu mimariler dikey ölçeklemeye zıt olarak yatay ölçeklemeye (horizontal scaling) odaklanmış ve buna bağlı olarak da yüksek erişilebilirlik (high availability) sağlama konusunda da gelişmiştir. Bu noktada hatırlayalım ki erişilebilirlik problemi RDBMS sistemlerde “transaction” operasyonları yüzünden bir sorun teşkil etmekteydi, dolayısıyla NoSQL sistemler burada da bir çözüm sunmuş gibi görünüyor. Elbette, bu ölçekleme ve erişilebilirliğin de bir bedeli vardır ve bu da veri tutarlılığından ve üstte bahsettiğimiz ACID prensiplerinden biraz uzaklaşmak anlamına gelebilir. Çünkü NoSQL veri sistemleri ACID prensiplerinden çok BASE prensiplerine göre çalışır. Dolayısıyla beklentiyi de buna göre ayarlamak gerekir. ACID ve BASE sistemlerin bir karşılaştırmasını aşağıda yapacağız.

Esnek veri yapıları

NoSQL sistemlerin bir başka özelliğine de değinecek olursak, veri yapıları konusunda da daha esnek olduklarını söyleyebiliriz. RDBMS sistemlerde, veritabanı bir verinin girebilmesi için bu verinin şeması ve yapısının önceden belirlenip, girecek olan verinin de bu yapıya uygun olması gerekir. Fakat NoSQL veritabanlarında böyle bir sistem söz konusu olmak zorunda değildir. Hatta bazı noktalarda veriyi bu veritabanlarına alabilmek için herhangi bir şema veya yapı belirlemenize bile gerek yoktur. Aynı durum veri okuma konusunda da geçerlidir. RDBMS üzerinden veriyi okurken verinin şeması bellidir, fakat NoSQL sistemlerde isterseniz verinin şemasını okuma esnasında da belirleyebilirsiniz. Elbette bunun bir dezavantajı da vardır, bu da okuyucunun veriye hangi şemayı vermesi gerektiğini bilmediği durumlarda verinin tamamen tanınmaz bir şekilde kalması riskidir. Verinin yapısının önceden tanınması da dolayısıyla kendine göre avantajlara sahiptir.

Kendine has sorgulama dili

NoSQL sistemlerinin ilişkisel olmayan sistemler olduğuna değinmiştik. Bu durumun ilk başta göze çarpmayan bir dezavantajı da bulunmaktadır. O da SQL’in zengin analitik syntax sisteminden faydalanamamaktır. NoSQL sistemler JOIN işlemine genellikle izin vermedikleri için (aynı zamanda ihtiyaç da olmadığından), farklı tablolardaki veriler birleştirilip SQL’in analitik fonksiyonlarıyla desteklenmeleri her zaman mümkün değildir. Elbette NoSQL sistemler veriyi okunmak için daha optimize şekilde tutmakta ve buna göre destek sunmaktadır, fakat SQL üzerinde rahatça yapılabilen analitik sorgular buralarda aynı rahatlıkla gerçekleştirilemeyebilmektedir. Elbette ki sorgulama syntax’i benzerdir. Örneğin bir NoSQL veritabanı olan Cassandra kendi sorgulama dili olan CQL (Cassandra Query Language) dilini oluşturmuştur. Bu dilin sorgulama işlemleri çoğunlukla klasik SQL’e benzerdir, fakat bahsettiğimiz problemleri yine de yaşamaktadır. Benzerliği görmek adına aşağıda CQL’den bir görsele bakalım:

Örnek CQL sorgusu

Sizin de görebileceğiniz gibi basit sorgular SQL ile birebir aynı.

Şunu belirtelim ki üstte bahsettiğimiz her NoSQL veritabanı kategorisi, kendine has amaçlarla kullanılır. Örneğin siz basit ve hızlı lookup sorgular istiyorsanız, key-value NoSQL sistemler sizin ihtiyacınız için en uygun veritabanı olacaktır. Çünkü gerekli anahtarı hızlıca aratıp, ona dair değerleri çok kısa sürelerde döndürebilir. Fakat analitik sorgular için uygun değildir. Diğer yandan eğer wide-column bir NoSQL veritabanı kullanıyorsanız, tahmin edilebilir sorgu paternleri için çok uygun olacaktır. Büyük miktarda veriler üzerinde organizasyonunuzun çalıştırdığı sorgular genellikle aynı ise, bu tarz veritabanları üzerinde bu sorgular için optimize edilmiş veri saklama mimarileri kurup, çok hızlı sonuç alma şansına sahip olabilirsiniz. Son olarak, örneğin bir sosyal ağ analizi yapacaksanız sizin için en uygun seçenek graph NoSQL veritabanlarıdır. Kısaca şöyle özetleyebiliriz, RDBMS sistemler genel-amaçlı kullanılırken, NoSQL sistemler spesifik amaçlar için farklı veri mimarisi yapılarına sahiptir ve bu alanda optimize edilmiştir.

Kolay ve hızlı geliştirilebilirlik

Bahsedilmesi gereken önemli bir diğer özellik de NoSQL veritabanlarının geliştiriciler için daha kolay ve hızlı geliştirilebilir olmasıdır. Bu sistemlerin veri şeması konusunda esnek olması ve veri yapılarının da popüler programlama dillerindeki veri yapılarına direkt olarak eşlenebilir olması çok daha hızlı geliştirmeler yapılmasına olanak sağlamalarına yardımcı olur.

Özetleyecek olursak, NoSQL veritabanı sistemlerinin avantajları esnek veri şeması, kuvvetli yatay ölçekleme özelliği, sorgulara hızlı cevap verebilmesi ve kolay geliştirilebilmesi olarak gösterilebilir. Dezavantajları ise analitik SQL’den yeteri kadar faydalanılamaması, ACID prensiplerinin genellikle desteklenememesi, spesifik kullanım amaçları için ayrı mimarilerde NoSQL veritabanı sistemlerine ihtiyaç duyulması olarak söylenebilir.

Şimdi üstte bahsettiğimiz konuya geri dönelim. ACID prensiplerinden bahsetmiş ve NoSQL veritabanlarında bunların bir problem olduğunu belirtmiştik. Bu veritabanı sistemlerinin daha çok BASE modeline göre çalıştığını söylemiştik. Şimdi bu iki modeli karşılaştıralım ve konuyu daha da netleştirelim.

ACID vs BASE prensipleri

Yazının başlarında ACID prensiplerinden ve bunların ne anlama geldiğinden bahsetmiştik. ACID ve BASE veri tutarlılığı modellerini karşılaştırmadan önce BASE modelinden ufakça bahsedelim. Fakat bunun da öncesinde, “Veri Tutarlılığı” kavramına kısaca değinmek gerekiyor.

Veri tutarlılığı derken neyi kastediyoruz?

Aslında az ve öz tanım olarak şunu kullanabiliriz: veritabanına en son yapılan son insert ya da update ne ise, cluster içerisindeki tüm node’lar bu insert ya da update işlemini gelen sorgulara güncel bir şekilde yansıtmalıdır. Dolayısıyla bir cluster içerisindeki hangi node üzerine sorgu atarsanız atın, tutarlı bir veri görmelisiniz. Bu bahsettiğimiz durum RDBMS sistemlerde “transaction” kavramı sayesinde sağlanmaktadır, bundan üstte bahsetmiştik. Fakat şunu da eklemiştik ki bu tutarlılığın sağlanması esnasında gerekli tablo kilitlenerek tutarsız okuma işlemlerinin önüne geçilir. Bu da aslında üstte bahsettiğimiz bir diğer kavram olan “erişilebilirlik” kavramına zıt olarak karşımıza çıkmaktadır. Dağıtık mimarilerde de aynı durum geçerlidir. Eğer tüm node’ların aynı tutarlı veriyi yansıtmasını istiyorsak, erişilebilirlikten taviz vermek durumundayız. Eğer tamamen erişilebilir olmak istiyorsak, bu kez de direkt olarak tutarlı olmak yerine “finalde tutarlı” olmaya razı olmalıyız. Finalde tutarlılık kavramından da zaten birazdan BASE modelini açıklarken bahsedeceğiz.

Veri tutarlılığı elbette daha detaylı bir kavram ve bunun da çeşitleri var. Bunlar katı tutarlılık, nedensel tutarlılık ve zayıf (finalde) tutarlılık olarak gösterilebilir. Bunların detaylarına burada değinmeyeceğiz çünkü bu yazının da bayağı uzamasına neden olacaktır.

Veri tutarlılığı kavramına da giriş yaptığımıza göre, BASE prensiplerine geri dönelim.

BASE modelin açılımı “Basically Avaliable, Soft-State, Eventually Consistent” olarak geçmektedir. Türkçeye “Temelde Erişilebilir, Esnek Yapıda ve Finalde Tutarlı” olarak çevirmek mümkündür. Peki bu ne demektir? Aşağıda madde madde açıklamaya çalışalım:

Basic Availability (Temelde Erişilebilirlik): Veritabanı çoğu zaman çalışır vaziyettedir ve veriye erişim sağlamaktadır.

Soft-State (Esnek Yapı): Herhangi bir zaman diliminde veritabanındaki veriler tutarlı görünmeyebilir ve bu esnek bırakılmıştır. Yani farklı node’lar birbirinden tutarsız verilere sahip olabilir. Burada “state” kelimesinden kasıt verinin ifade ettiği durumdur.

Eventual Consistency (Finalde Tutarlılık): Sistem zamanla tutarlı olacak ve node’lar arasındaki tutarsız görüntü giderilecektir. Fakat burada da sistemin bu esnada bu tutarlı görüntüyle çelişecek herhangi bir input almadığı varsayımı mevcuttur. Finalde tutarlılık ifadesi de sistemin eninde sonunda tutarlı hale geleceğinin ifadesidir.

Peki ACID ve BASE modellerini karşılaştıracak olursak karşımıza nasıl bir tablo çıkacaktır?

Elbette dünyada hiçbir şey siyah ya da beyaz olmadığı gibi burada da öyle değildir. Karşımıza gri alanlar çıkmakta ve biz senaryomuza hangisi uygunsa onu seçmekteyiz.

  • ACID prensiplerinin en belirgin avantajı veri tutarlılığını ve güvenilirliğini ön plana çıkarmasıdır. Dolayısıyla bu iki konunun çok büyük öneme sahip olduğu sistemlerde ACID prensiplerinden taviz verilemez.
  • Diğer yandan, esnek ve kolay geliştirilebilir aynı zamanda veri tutarlılığında da finalde tutarlı olmayı kabul edebilir bir senaryonuz varsa, BASE sizin için elbette daha iyi bir seçenek olacaktır.
  • Burada karar mekanizmasının bakması gereken en önemli nokta, eldeki senaryonun hangi model ile daha başarılı bir şekilde çalışabileceğidir.

4. NewSQL

Bu makalede şuana kadar RDBMS sistemlerin yaşadığı problemlerden ve alternatif olarak dağıtık mimarileri kullanan NoSQL sistemlerin ortaya çıkışından bahsettik. Bunları karşılaştırarak avantaj ve dezavantajlarını inceledik. Ayrıca bunlara olan ihtiyacın detayına indik ve kullanım alanlarına göz attık. Fakat şunu belirtmek gerekir ki, RDBMS sistemlerin sağladığı ACID prensipleri garantisi çoğu şirket ve uygulama için çok değerliydi. Dolayısıyla RDBMS sistemlerin ölçekleme ve sorgulara hızlı cevap verme konusundaki problemlerini çözmek adına yola çıkmış olan NoSQL veritabanlarının ACID garantisi verememesi ve BASE prensipleri üzerine çalışması büyük soru işaretleri yaratmıştı. Bunun üzerine ilişkisel sistemler üzerine çalışmak isteyen ve bundan vazgeçmek istemeyen insanlar bu sistemleri ölçekleyebilmek adına çözümler geliştirme ve ilişkisel sistemlerin sunduğu yararlardan da faydalanabilmeye devam etme eğiliminde oldular. Yani hem dağıtık mimarileri hem de ilişkisel sistemleri birlikte kullanmak buradaki ana amaçtı. Bu amaç uğrunda yapılan çalışmalar NewSQL dediğimiz yapıyı oluşturdu.

NewSQL veritabanı sistemleri, hala RDBMS sistemlerin sunduğu garantileri sunmak fakat paralel veri işlemeden de faydalanmak üzere tasarlanmış sistemlerdir. Bu tanımı “ölçeklenmiş ilişkisel sistemler” olarak kısaltabiliriz. Bu sistemlerin, vadettikleri faydaları sunmak konusunda ne kadar başarılı oldukları sektörde hala tartışma konusudur. Bu sistemlere örnek olarak CockroachDB, VoltDB ve YugabyteDB’yi gösterebiliriz. Elbette burada adını zikredemediğimiz birçok teknoloji daha mevcut.

NewSQL sistemlerden bahsederken, ACID prensipleri konusuna bir kere daha değinmek gerekir. Hatırlarsanız bir SQL sistemde çalışırken (RDBMS), “transaction” işlemlerinin ACID garantisi sunduğunu ve bu şekilde başarılı olduğunu söylemiştik. Fakat bu, tek bir makine üzerinde çalışan RDBMS sistemler için geçerliydi. Ne zaman ki siz bir NewSQL sisteme geçmek istersiniz yani varolan RDBMS sisteminizi ölçeklemek istersiniz, işte o zaman karşınıza dağıtık bir sistemde “transaction” işlemlerinin hala ACID garantisi sunmasını sağlama problemi çıkar. Bu iş tek bir makine üzerinde çalışırken kolaydı fakat dağıtık mimariye geçildiğinde zorlaştı ve aslında daha önce sahip olmadığınız bambaşka bir problem olarak karşınıza çıktı. Yani siz bir problemi çözmeye çalışırken, başka bir problemle karşılaştınız.

Dağıtık sistemlerde “transaction” işlemlerinin ACID prensiplerini sağlaması için birçok çözüm geliştirilmeye çalışılmıştır. Bunlardan belki de en bilineni, “Two-Phase Commit (2PC)” denilen yöntemdir. Bu yöntem türkçeye “İki Aşamalı İşleme” olarak da çevrilebilir. Bu yönteme kısaca bakarak dağıtık sistemlerde ACID prensiplerini nasıl sağlamaya çalıştığını anlamaya uğraşalım:

Üstteki görsel biraz karışık gelebilir, dolayısıyla burada ana hatlarıyla anlatacağım. Üstte de bahsettiğim gibi, 2PC algoritması dağıtık bir sistemde node’ların birbirleriyle uzlaşmasını sağlar. Yani bir node üzerinde bir “transaction” işlemi gerçekleşiyorsa, bu işlem diğer node’lara da yansımalı ve veri tutarlılığı asla bozulmamalıdır. Unutmayalım ki tutarlılık (consistency) ACID prensiplerinden bir tanesiydi, dolayısıyla kesinlikle sağlanmalıdır(Bu konuda NoSQL sistemlerin tutumunu hatırlayalım). 2PC esnasında iki aşama vardır, bunlardan ilki “hazırlık” aşaması, ikincisi ise “commit (işleme)” aşamasıdır. Bu aşamalar cluster’ı yöneten ana makine(transaction coordinator) ile diğer node makineler arasındaki konuşma aşamalarıdır. Bir “transaction” işlemi gerçekleşecekse, ana makine katılımcılardan birinin işlemi tamamlamasını bekler ve katılımcının onay vermesi halinde diğer tüm katılımcılar içerisinde “transaction” işlemini işlemeye çalışır. Tüm makineler bu işlemi tamamlayabilirse, işlem başarılı olur. Fakat bir tanesinin başarısız olması durumunda, transaction işlemi tamamlanamaz. Bu algoritma esnasında, koordinatör makine ve katılımcılar arasında iletişim kopuklukları olması 2PC işlemini zaman zaman zora sokar. Ayrıca 2PC işlemi tamamlana kadar ilgili tüm makineleri kilitler. Bu senaryonun tek bir makine üzerinde “transaction” işlemi yapılırken de tekrarlandığını söylemiştik. 2PC algoritmasının içerisindeki tüm katılımcı makinelerin kilitlenmesi, verinin bu süre boyunca erişilebilir olmayacağı anlamına gelir ki bu da 2PC’nin bir problemidir. Üstte söylediğimiz gibi makineler arası potansiyel iletişim kopuklukları ise bu makine kilitlenmesi durumunun çok uzun hatta sınırsız olabileceğini gösterir ki bu daha da büyük bir problemdir. Görüleceği üzere, 2PC algoritmasını bu tarz bariz problemleri bulunmaktadır.

Endüstri bunları gördüğünden dolayı, 2PC algoritmasına alternatifler de elbette oluşturmuştur. Bunlardan yine en belirgini, “Compensation (Telafi)” metodlarıdır. Bu metod içerisinde, bir “transaction” işlemi direkt olarak “commit” aşamasını tamamlar ve eğer bu işlemden sonra bir hata mesajı alınırsa, yeni bir operasyon çağrılarak verinin eski “durumu” geri getirilir. Compensation metodlarının detayına burada elbette girmeye gerek yok. Bu metodları da dağıtık sistemlerde “transaction” işlemlerinin ACID prensiplerini sağlaması için 2PC algoritmasına alternatif olarak geliştirilmiş metodlar olarak bilebiliriz. Merak edenler için, internette bunlar ile alakalı birçok kaynak mevcut.

Yine biraz detaya girmiş olsak da, bu bölüm NewSQL veritabanı sistemleri ve bunların karşılaştıkları problemleri açıklamak adına gayet faydalı oldu. Bundan sonraki bölümde, endüstride NoSQL sistemlere getirilen eleştiriler ve bunların NewSQL ile ilişkileri hakkında konuşacağız. Makale içerisinde böyle bir bölüm ayırmamın sebebi, şu ana kadar NoSQL sistemlerin RDBMS sistemlerdeki problemleri nasıl çözmeye çalıştığı üzerinde durmuş olmamız. Biraz da olaya zıt açıdan yaklaşanların görüşlerini inceleyelim.

NoSQL eleştirileri ve NewSQL

NoSQL için saymış olduğumuz özellikler bir yana, bu sistemlere karşı ortaya konulmuş olan eleştirilerden de üstte bahsetmiştik. Fakat sektörde bu sistemlerin artık tamamen gereksiz olduğunu iddia edenler dahi bulunmaktadır. Bu iddialardan en belirgini, NoSQL teknolojilerin zamanında RDBMS sistemler ölçeklenmeyi başaramadığı için ortaya çıktığı fakat artık RDBMS sistemlerin de ölçeklenme konusunda gereken başarıyı yakaladığı dolayısıyla NoSQL’e de gerek kalmadığıdır. Şüphesiz burada NewSQL’in NoSQL’e tercih edilebileceği kastediliyor. Yukarıda, NewSQL’in başarısının da tartışma konusu olduğunu söylemiştik, dolayısıyla bu konuda endüstride hala tartışmalar sürmektedir.

Elbette ki NoSQL’e yöneltilen en büyük eleştirilerden biri ACID prensiplerini tam anlamıyla sağlayamamasıdır(sağlamayı tercih etmemesi demek daha doğru olacaktır). Modern uygulamaların çoğunluğu için ACID prensiplerinin önemli olduğu, “finalde tutarlılık” kavramının bu uygulamalar için yeterli olmadığı sürekli gündeme gelmektedir. BASE prensipleri bazı spesifik senaryolarda ihtiyaçları karşılamak için yeterlidir fakat aklımıza bir banka senaryosu getirdiğimizde ACID’den vazgeçilmesinin mümkün olamayacağını hepimiz düşünebiliriz.

Getirilen ikinci eleştiri, şema eksikliğidir. Şema eksikliğinin esnek bir yapı olduğundan ve geliştiricilerin işini de son derece kolaylaştırdığından bahsetmiştik. Fakat işin “read”, yani okuma kısmına baktığımızda, şemasızlık tam tersi bir problem haline gelebilir. Geliştiricilerin işini kolaylaştırayım derken, datayı aktif değer üretmek için kullanacak kişilerin işini zorlaştırmak elbette kimsenin isteyeceği bir durum değildir. Ancak unutmamak gerekir ki veriyi okuyacak kişi veriyi nasıl formatlandırması gerektiğini veya nasıl bir şema uygulaması gerektiğini biliyorsa veya belirleyebilirse, bu da problem olmaktan çıkabilir. Buradaki eleştiri haklıdır fakat işe diğer ucundan da bakmak gereklidir. Diğer yandan, bir veri seti için uygun ve anlaşılabilir bir şema belirlemek küçümsenecek bir efor değildir, ciddi zaman alabilir. Fakat bunun da kendine has meyveleri olacaktır.

Üçüncü eleştiri, SQL syntax’ının kullanılamayışıdır. Günümüzde çoğu senaryoda veriyi sakladığınız şeklinden farklı bir şekilde okumanız gerekmektedir. NoSQL veritabanları yukarıda da bahsettiğimiz gibi bunu sağlamakta zorlanmaktadır. Bir veri ambarı üzerinde uzun ve analitik bir SQL yazdığınızı düşünün. Bu sorgu birçok dönüştürme ve join işlemi içereceğinden, büyük ihtimalle uzun sürecektir(ciddi miktarda veri üzerinde çalıştırdığınızı varsayıyorum). Fakat başarılı olan ilişkisel ve dağıtık bir sistem üzerinde çalışırsa(NewSQL), hem SQL’in analitik gücünden taviz verilmemiş hem de performans ciddi oranda artırılmış olacaktır. Elbette NewSQL sistemlerin de bunu ne kadar başarabildiği hala tartışma konusudur fakat burada varsayım ile ilerliyoruz. Öte yandan, NoSQL sistemlerde bu tarz yüksek analitik kapasiteli bir sorguyu oluşturmaya çalışmak genellikle istenilen sonucu vermemektedir. Eğer ufak bir sorgu ve hızlı dönecek bir cevap istiyorsanız(“2 numaralı id’li müşterinin adresini getir” şeklinde) NoSQL sistemler biçilmiş kaftan olacaktır. Fakat bahsettiğimiz gibi analitik bir dizayn ile şekillendirilmiş bir sorgu isteği NoSQL üzerinde genellikle sizi tatmin etmeyecektir.

Dördüncü ve son eleştiri, NoSQL kullanımı için insanların yeniden yetiştirilmesi gerekliliğidir. RDBMS sistemler ve SQL dili belli bir olgunluğa ve oturmuşluğa sahip olduğundan, bu konuda insanların bilgi ve tecrübe düzeyi de oldukça yüksektir. Fakat aynı durum NoSQL sistemler için geçerli değildir. İnsanların bu teknolojileri(birçok tür mevcut olduğundan bahsetmiştik) sıfırdan öğrenmeleri ve tecrübe etmeleri gerekmektedir. Hatta bu çoğu zaman eski bilgilerini çöpe atmaları gerektiğini bile düşündürtebilmektedir. Bu konu da endüstride çokça tartışılmış ve tartışılmaya devam eden başlıca konulardandır.

NoSQL’e yöneltilen eleştirilerden yazının önceki bölümlerinde de kısaca bahsetmiştik. Bu bölümde ise bunları daha da detaylandırdık ve NewSQL ile olan ilişkilerinden bahsettik. Son olarak, yazıyı önemli bir final bölümüyle bitireceğiz.

5. CAP Teoremi

Yazının bu final bölümünde, çok ünlü bir teorem olan CAP teoremini inceleyeceğiz. Bu teoremin neden ortaya atıldığı ve bize ne söylemeye çalıştığı konularında kafa yoracağız.

CAP teoremi, dağıtık bir sistemin en çok istenen üç özellikten sadece ikisini sağlayabileceğini söyler. Bu özellikler Tutarlılık (Consistency), Erişilebilirlik (Availability) ve Bölünme Toleransı (Partition Tolerance)‘dır. Bu özelliklerden sadece ikisinin üst düzeyde sağlanabileceğini bilmek, bize ihtiyaçlarımıza uyun dağıtık sistemi seçmekte yardımcı olacaktır, zaten teoremin söylemeye çalıştığı ana mesajlardan biri de budur.

CAP kısaltmasındaki harflerin nereden geldiğini zaten üstteki özellikleri sayarken anladınız, ve bunların ilk ikisinden yazının önceki bölümlerinde bahsettik. Tutarlılık ifadesinin ne demek olduğunu ve nasıl uygulandığını, aynı zamanda erişilebilirliğin de açıklamasını yapmaya çalıştık. O zaman geriye kalan son harf olan “P” harfi, yani “Partition Tolerance(Bölünme Toleransı)” üzerine de biraz konuşalım.

Partition” yani “bölünme” ifadesi, dağıtık bir sistemdeki iki bilgisayarın(node) arasındaki bir iletişim kopukluğudur. Bu kopukluğun elbette birden çok nedeni olabilir. Bir bölünme olması durumu, elbette iki bilgisayar arasındaki bağlantının da tamamen kopması veya gecikmeye uğramasıdır. Bölünme toleransı ise şunu ifade eder; dağıtık bir sistemin içerisinde bir veya birden fazla bölünme olması durumunda dahi o cluster çalışmaya devam etmelidir. Dolayısıyla, o dağıtık sistem bölünmeyi “tolere” edebilmelidir.

CAP kısaltmasını açtığımıza göre, devam edelim. CAP teoremi kısaca şunu söyler; bir dağıtık sistem CP(Consistency-Availability), AP(Availability-Partition Tolerance), ya da CA(Consistency-Availability) olabilir fakat üçü birden olamaz. Bunların özelliklerine değinelim.

CP Sistemler: Tutarlılık ve Bölünme Toleransı özelliklerine önem verip, bunun bedelini de erişilebilirlikten taviz vererek ödeyen sistemlerdir. Bu sistemlerde bir bölünme olayı meydana geldiğinde, tutarlılığı korumak adına sistem tutarlı olmayan tüm node’ları kapatır ve dolayısıyla bu node’lardaki veri erişilemez olur. Bölünme çözümlendiğinde ve tutarlılık tekrar sağlandığında, tüm node’lar açılır ve veri tekrar okunmaya devam edebilir. Elbette bölünmenin çözümlenmesinin uzun sürdüğü durumlarda veri erişilebilirliği açısından veriyi okumaya çalışan taraflar büyük beklemeler ile karşılaşabilir.

AP Sistemler: Erişilebilirlik ve Bölünme Toleransı özelliklerine önem verip, bu kez ise bedeli tutarlılık tarafında ödeyen sistemlerdir. Bir bölünme olduğunda, herhangi bir node’a kapatma işlemi uygulanmaz ve veri erişilebilir olmaya devam eder. Fakat bölünmedeki bağlantı kopukluğundan ya da gecikmesinden dolayı, bu gecikme düzelene kadar iki node üzerindeki veriler birbirlerinden farklı olabilir ve bu da farklı okuyucuların tutarsız veriler okuyabileceklerine işaret eder.

CA Sistemler: Tutarlılık ve Erişilebilirlik üzerine yoğunlaşmış fakat bölünme toleransı tarafında zayıf olan sistemlerdir. Bu sistemler, bölünme olayları gerçekleşmesi halinde çalışmaya devam edemediklerinden dolayı, dağıtık mimariler söz konusu olduğunda çok kullanışlı olmayan ve günümüzde de çok tercih edilmeyen sistemlerdir.

CAP teoremi ile ilgili üsttekine benzer çok ünlü bir görsel vardır. Burada da görüleceği üzere, teknolojiler CAP teoremindeki harflerin ikili versiyonlarına dağılmıştır.

Örneğin, AP tarafında Cassandra’yı görüyoruz. Cassandra master/slave metodu ile çalışmadığından dolayı, herhangi bir bölünme esnasında geri kalan tüm node’lar her zaman erişilebilir haldedir fakat bu, tüm node’lardan okunan verinin tutarlığı olacağı anlamına gelmez. Elbette bu sadece bir süre içindir, sonrasında Cassandra “finalde tutarlı” bir hale ulaşacaktır. Bu kavramdan da üstte bahsetmiştik.

CP tarafında HBase ve MongoDB gibi teknolojiler görüyoruz. Casandra’nın aksine MongoDB master/slave metodu ile çalışır, bu da demektir ki master node’un düştüğü durumlarda yeni bir master node seçilene kadar cluster erişilemez halde kalacaktır. Seçim işlemi tamamlandığında cluster tekrar erişilebilir hale gelir. Böylece MongoDB tutarsız veri okunmasını tüm cluster’ı erişilemez hale getirerek çözmektedir. Bölünme öncesi ya da sonrası okunan veriler tutarlıdır. Fakat bölünme çözümlenirken, okuyucular sıraya girmiş veriyi okumayı beklemektedir.

CA tarafında ise SQL Server, MySQL gibi çoğumuzun aşina olduğu sistemler bulunmakta. Bunlar dikey olarak ölçeklendiğinde ve dağıtık bir mimaride çalışmadıklarında, herhangi bir bölünme potansiyeli bulunmadığından dolayı, sadece tutarlılık ve erişilebilirlik üzerine odaklanırlar. Dolayısıyla bu da onları CA kategorisine alabilmemize olanak sağlar.

Evet, CAP teoremini de bitirerek yazının finaline geldik. Bu yazı boyunca elimden geldiğince büyük veri dünyasında adını çok duyduğumuz kavram ve teknolojilerden bahsetmeye çalıştım. Bu teknoloji ve kavramların sadece tanımları değil, aynı zamanda birbirleriyle bağlantıları ve büyük resimde oturdukları noktalar da bir o kadar önemli olduğundan, o konuda da yazıyı başarılı kılmak için uğraştım. İleride yazacağım yazılarda bu teknolojileri kullanırken direkt olarak buradaki kavramlara atıfta bulunacağımdan, bu yazı blogdaki büyük veri ve veri mühendisliği alanındaki diğer yazılara da bir temel teşkil edecektir.

Notlar

  1. Bu yazıda bahsettiğim kavram ve teknolojiler sektörde hala tartışılmaktadır. Bazıları üzerinde tamamen fikir birliği henüz oluşamamışken, bazıları ise çok nettir. Elbette ben de bunu mümkün olduğunca yansıtmaya çalıştım.
  2. Buradaki konuların çok daha detaylı makaleleri ve alternatif kaynakları internette mevcuttur. Ben mümkün olduğunca yüzeysel olarak ve giriş düzeyde bilgi sahibi olmaya yetecek kadar değindim. Bunun için de zaten internette bulunan birçok kaynaktaki bilgileri, kendi bilgi ve tecrübelerimle harmanlayarak bu yazıyı yazdım.

Kaynakça

The Transaction Concept: Virtues and Limitations, Jim Gray

Cassandra The Definitive Guide, Jeff Carpenter & Eben Hewitt

CAP Theorem

Distributed Architectures