Apache Cassandra’ya Genel Bir Bakış

Hakan Kurt
Finartz
Published in
8 min readJan 14, 2021

Apache Cassandra açık kaynak, NoSQL ve dağıtık bir mimariye sahip veritabanıdır. Verilerin tek bir sunucuda tutulmasındansa birden fazla sunucuya yayılmış bir şekilde depolamamıza olanak sağlar.

Facebook’ta çalışan mühendisler Facebook Messenger uygulamasını canlıya alacakları sırada yatayda ölçeklenebilir ve yapısal bir veritabanına ihtiyaç duymaktaydılar. Bu ihtiyaçlar doğrultusunda mühendisler bir araya gelerek Amazon’un DynamoDB’sinin dağıtık mimarisini ve Google’ın BigTable veri modelini Cassandra olarak adlandırılacak veritabanında bir araya getirmişlerdir.

History of Apache Cassandra

2009 senesinin Mart ayında Cassandra, Apache Kuluçka Merkezine verildi. Bu şekilde Cassandra’ın ilgi görmesi sağlandı ve Apache Cassandra haline geldi.

2010 şubatında ise Apache’in en çok önem verdiği proje haline geldi. Bunlar yaşanırken Apache Cassandra etrafında bir topluluk da oluşmaya başlamıştı.

Bunlar yaşanırken Facebook, Facebook Messenger’ı revize ettikleri dönemde Cassandra’nın kullanımı bırakıp farklı bir sisteme geçiş yaptılar.

2011 senesinde ise Cassandra’nın 0.8 sürümü yayınlandı. Bu sürümde CQL (Cassandra Query Language) sorgulama dili tanıtıldı ve bu gelişme Cassandra açısında büyük öneme sahipti. Çünkü önceleri kullanıcılar Cassandra veritabanına sorgu atabilmek için Java kodu yazmak durumunda kalıyorlardı. CQL, SQL’e çok benzeyen ve Cassandra veritabanıyla etkileşime geçebileceğimiz çok zengin bir API’ye mevcut. CQL, Cassandra’nın daha hızlı bir şekilde kabul görmesini sağlayan bir gelişmeydi.

Bu kadar tarihçeden sonra biraz da Apache Cassandra’nın iç dinamiklerinden ve nasıl çalıştığından bahsedelim :)

MongoDB ile Arasındaki Farklılıklar

Cassandra versus MongoDB

Cassandra ve MongoDB’nin her ikisi de NoSQL veritabanıdır. NoSQL (not only sql) geleneksel veritabanlarının bir alternatifidir ve ilişkisel veritabanlarına göre çok sayıda veriyi depolamamıza olanak sağlar. Hem de bunu yaparken mantıksal bir kategorizasyona ve bir şemaya ihtiyaç duymadan yaparlar.

Cassandra ilk olarak 2008 yılında piyasaya çıkarken MongoDB ise bundan bir sene sonra piyasaya çıkmıştır.

Arasındaki farklılıklar şu şekildedir:

  • Data Availability : Cassandra ve MongoDB arasındaki en büyük temel farklılıklardan biri data availability’i sağlama şeklidir. Bu özellik esasen bir cluster’daki master node’ların sayısına bağlıdır. MongoDB’de slave node’larını yönetmek için tek bir master node bulunur ve bu master node’un down olma durumunda slave node’lardan biri master rolünü üstlenir. Bu devir işleminin gerçekleşmesi de belli bir süre alabilir. Cassandra’da ise bir cluster içerisinde birden fazla master rolünde node bulundurur. Buda her zaman high availability’i sağlar. Eğer yüksek seviyede data availability bizim için önemli bir parametre ise Cassandra’yı bu noktada tercih edebiliriz.
  • Scalability (Ölçeklenebilirlik) : Ölçeklenebilirlik temelde cluster modeliyle ilişkilidir. Bir cluster da master node’lar yazma isteklerini kabul ederken slave node’lar sadece read isteklerinde kullanılırlar. MongoDB cluster içerisinde sadece bir adet master node’a yer verir. Buna karşın Cassandra cluster içerisinde birden fazla master rolüne sahip node bulundurması daha iyi bir yazma performansı sağlar ve Cassandra’yı ölçeklenebilirlikte MongoDB’ye göre daha avantajlı bir konuma getirir. Eğer yazma hızı ve ölçeklenebilirlik bizim için bir öncelikse Cassandra daha iyi bir seçim olacaktır.
  • Data Model (Veri Modeli) : MongoDB de veri modeli nesnesel ve döküman bazlı olarak kategorize edilirken Cassandra biraz daha geleneksel bir yaklaşım olan satır ve sütunlardan oluşan tablo yapısını kullanır. Cassandra’nın ilişkisel veritabanlarındaki benzer yapıyı kullanmasına karşın tabloda bulunan her satırın aynı sütunlara sahip olması zorunluluğu olmadığından ilişkisel veritabanlarına göre daha esnektir. Öte yandan MongoDB’nin döküman bazlı yapısı bize bir alan içerisinde farklı seviyelere ve nesne yapısına sahip veriler saklamamıza olanak sağlamaktadır. Bu nedenle daha zengin bir veri modeline ihtiyaç duyuyorsak MongoDB bu noktada bizim için daha iyi bir seçim olacaktır.
  • Query Language (Sorgulama Dili) : MongoDB, henüz bir sorgulama dilini desteklemediğinden JSON parçacıklarından oluşan sorguları kullanmaktadır. Eğer takımınızdaki çalışanlar SQL’e aşina iseler buradaki yapıya alışmaları biraz süre alacaktır. Cassandra’nın ise kendisine ait CQL (Cassandra Query Language) sorgulama diline sahiptir ve sözdizimi SQL ile çok benzerdir. Fakat yinede bazı kısıtlamaları içermektedir. Eğer bir sorgulama dilinin mevcudiyeti bizim için olmazsa olmaz ise Cassandrayı bu noktada seçebiliriz.
  • Desteklenen Programlama Dilleri :

MongoDB : Actionscript, C, C#, C++, Clojure, ColdFusion, D, Dart, Delphi, Erlang, Go, Groovy, Haskell, Java, JavaScript, Lisp, Lua, MatLab, Perl, PHP, PowerShell, Prolog, Python, R, Ruby, Scala, Smalltalk

Cassandra : C#, C++, Clojure, Erlang, Go, Haskell, Java, JavaScript, Perl, PHP, Python, Ruby, Scala

Cassandra Veri Modeli

Cassandra Data Model

Cassandra veri modeli, geleneksel ilişkisel veritabanları modellerine çok benzemektedir. Veriler yine aynı şekilde satır ve sütunlardan oluşan tablolarda tutulmaktadırlar. Buradaki veri modelinde ayrıca “keyspace” ve “cluster” kavramlarıyla karşılaşıyoruz.

Keyspace : Bir veya birden fazla node yayılmış tabloların tutulduğu yapı

Cluster : Bir veya birden fazla keyspace’i barındıran yapı

Cassandra Kısıtları

Cassandra Constraints

Apache Cassandra, NoSQL olması sayesinde getirdiği avantajların yanında bazı dezavantajlar da getiriyor. Cassandra’da geleneksel ilişkisel veritabanlarındaki gibi tablolar da “foreign key” yapısı yok. Bunun sebebinin ise dağıtık bir mimaride bunun bize performans açısında çok maliyetli oluşudur.

Cassandra da ayrıca sorgularda WHERE ifadesiyle beraber herhangi bir kolonu kullanamayız. Bu nedenle Cassandra ile çalışırken yapacağımız uygulamanın kısıtlarını iyi şekilde belirleyip Veri Modelini o şekilde dizayn etmemiz gerekir.

Primary Key

Cassandra’da primary key alanı veriyi sadece eşsiz bir şekilde tanımlamada değil verinin hangi node’a yazılacağı kararının verilmesinde de kullanılır.

Cassandra Composite Key

Primary Key, partition key ve clustering key alanlarından oluşur. Partition key, verinin hangi node üzerine yazılacağına, Clustering key ise verinin yazılacağı node üzerinde nasıl bir sıralamada kaydedileceğinin bilgisini tutar.

Cassandra Veri Tipleri

Cassandra Data Types

Cassandra’da geleneksel ilişkisel veritabanlarında bulunan veri tiplerinin yanında ayrıca yeni bazı kullanışlı veri tipleride mevcuttur.

Blob : Rastgele dizilmiş byte dizisi ( Genelde multi-media, ses, görüntü gibi içerikleri temsil etmede kullanılan bir veri tipidir.)

UUID : Primary key gibi alanları tanımlada ya da verinin bir kopyasının olmayacağını garanti altına almak için kullandığımız bir veri tipidir.

TIMEUUID : Eğer zamana bağlı olarak uuid leri sıralamak istiyorsak yani eğer bir hesaplama ya da bir olaya ait veriyi eşsiz bir şekilde saklamanın yanında ayrıca zamana bağlı olarak sıralamak istiyorsak o zaman timeuuid kullanabiliriz.

Set, List, Map (Collection veri tipleri) : Collection veri tipleri bir satır içerisinde çok sayıda veriyi bir arada tutmamıza olanak sağlar. Yatayla ölçeklendirilebilir dağıtık veritabanlarında joinlerin ve normalizasyonların birer imtiyaz olmadığını düşünürsek 200, 300 adet veriyi bir satırda tutmak bize baya yardımcı olacaktır.

Temel CRUD İşlemleri

Cassandra’da veritabanı üzerinde işlemler yapmak için CQL sorgulama dili kullanılır. Tablo oluşturma, kayıt oluşturma, okuma, yazma ve güncelleme sorguları SQL’dekilere çok benzerdir.

  • Tablo Oluşturma :
CREATE TABLE books_by_author (author_name TEXT,publish_year INT,book_id UUID,book_name TEXT,rating FLOAT,PRIMARY KEY ((author_name), publish_year, book_id)) WITH CLUSTERING ORDER BY (publish_year DESC, book_id ASC);

Buradaki ifadede primary key alanı tanımlanırken 3 farklı alan kullanılmıştır. author_name alanı partition key’i, publish_year ve book_id alanları ise clustering key’i tanımlar. Bu iki keyin birleşimine kompozit anahtar (composite key) adı verilir. Ayrıca WITH CLUSTERING ORDER BY ifadesi ile de clustering key’lerin nasıl sıralanacağını belirlenmiştir.

  • Kayıt Oluşturma :
INSERT INTO books_by_author (author_name, publish_year, book_id, book_name, rating) VALUES (‘James Patterson’, 2008, uuid(), ‘Witch & Wizard’, 4);
  • Kayıt Güncelleme :
UPDATE books_by_author SET publish_year=2009 WHERE book_id=10;
  • Kayıtları Getirme :
SELECT * FROM books_by_author;

Yukarıdaki komutu çalıştırdığımızda aşağıdaki gibi bir çıktı alırız.

  • Kayıt Silme :
DELETE FROM books_by_author WHERE author_name='James Patterson';

Nodes and Clusters

Cassandra’yı temelde Cassandra kılan şey dağıtık bir mimaride olmasıdır. Ve dağıtık yapıda olması beraberinde bazı zorluklarda getirmektedir. Eğer tüm depolama işlerimizi tek bir sunucuda görebiliyorsak o şekilde devam etmemiz bizim için hayatı daha kolay kılacaktır :)

Ama problem şu ki bu davranış herkesin problemini çözmemektedir. Bu da “one computer is not enough” yani tek bir bilgisayarın yeterli olmaması durumunu ortaya çıkarıyor ve dağıtık sistemdeki yapılara yönelmemizi gerektiriyor.

Cassandra da her bir node birbirinin aynısıdır ve bir master-slave yapısı yoktur. Bu nedenle tüm node’lar birbirleriye eş seviyededirler.

Cassandra cluster’ları genelde bir ring yapısıyla şematize edilirler. (Aşağıda bulunan görseldeki gibi.) Cassandra bize sistemi elastik bir biçimde ölçeklendirebilmemize olanak sağlar. Örneğin Cassandra içerisindeki bir clustera yeni bir node ekleyip var olan bir node’u silebiliriz. Böylelikle sistem hiç bir şekilde down olmaz. İstediğimiz şekilde cluster’ı genişletebilir ya da küçültebiliriz. Tabi fiziksel olarak donanım destek verdiği müddetçe :)

Multi Data Center Architecture

Peki ya veri node’lar ve cluster’lar içerisinde nasıl dağıtılır?

Cassandra’da her bir node verinin nereye gideceğini belirleyen bir token aralığı ile ilişkilendirilir. Ne zamanki bir veri yazma isteği gelirse veriye ait partition key Cassandra içerisinde bulunan Partitionersınıfının partitioner metoduna tabi tutularak bir değer üretilir. Ve bu değere bakılarak cluster içerisindeki hangi node üzerine yazılacağı belirlenmiş olur. Buradaki işleyişi aşağıdaki örneğe bakarak daha iyi anlayabiliriz.

Example of how data is distributed across nodes

Buradaki örnekte 1 ile 100 arasında bir aralık belirlenmiş ve bu aralık node sayısına bölünmüş. Böylece her bir node’a atanacak token aralığı belirlenmiştir. Örnekte olduğu gibi emp_id si 20 olan bir kayıt gelmiş ve bu değer Cassandra’nın Partitioner sınıfının ilgili metoduna tabi tutularak 62 değeri üretilmiştir. 62 değeri 4. node’a atanmış token aralığına denk geldiği için veri oraya yazılacaktır.

Node’lar birbileri arasında nasıl haberleşir?

Cluster içerisinde bulunan node’lar birbirleri arasında gossipadı verilen bir protokol ile haberleşirler.

Gossip Protocol

Gossip Protokolü, deterministik olmayan olasılıksal bir protokoldür. Yani her bir node rastgele bir node seçerek birbirleriyle bilgi alışverişi yaparlar. Bu bilgi alışverişinde önceden iletişime geçmiş olunulan node’ların ayakta olup olmadığı bilgisi ve durumu bilgileri aktarılır. Ve bu bilgi alışverişinin insanların arasındaki dedikodu yapma durumuna benzediği için bu protokole Gossip adı verilmiştir.

Replication

Sunucular (node’lar) malesef ki her zaman stabil bir biçimde çalışmayabiliyorlar. Örneğin sunucudaki disk bozulabilir ya da sunucuya giden güç kaynağında bir arıza meydana gelebilir. Böylesi felaket senaryolarına hazırlıklı olma adına verilerin sadece bir kopyasını bulundurmak pekte mantıklı bir yaklaşım olmayacaktır.

Cassandra replikasyonu iki kavramla ele almaktadır. Bunlar:

  • Replication Factor : Bir veriden kaç adet kopya üretileceği. Örneğin replication_factor 3 olarak belirlenirse, cluster içerisinde aynı veriden 3 adet tutulacaktır demektir.
  • Replication Strategy : Verinin cluster içerisinde nasıl tespit edileceğini belirler.

Consistency

Dağıtık bir veritabanı kullanıyorsanız consistency çok önemli bir kavramdır. Eğer tek bir sunucuda çalışan bir veritabanına sahipseniz consistency sizin için bir problem olmayacaktır. Ama birden fazla data center’a dağılabilen birden fazla sunucu üzerinde çalıştırıyorsanız verinin bir node’da farklı başka bir node’da farklı olması gibi problemlerle karşılaşabiliriz. Cassandra Consistency Level, bir read ya da write işleminin başarılı sayılabilmesi için kaç adet node’un isteği aldığını bildirmesi gerektiğidir. Cassandra bu konuda geliştiricilere baya kontrol sağlamaktadır.

Cassandra da çeşitli consistency seviyeleri mevcuttur. Bunlardan başlıcaları:

  • Level One : Replika node’lardan sadece birisinin yanıt vermesi yeterlidir.
  • Level Quorum : Node’ların çoğunluğunun (n/2+1) yanıt vermesi gerekir.
  • Level ALL : Tüm node’ların yanıt vermesi gerekir.
  • Level Each Quorum : Her bir datacenter’da ki node’ların çoğunluğunun yanıt vermesi gerekir.

Yazımı giriş seviyesinde tutmak istediğimden dolayı burada sonlandırıyorum. Umarım okuyanlar için faydalı bir yazı olur.

Kaynaklar :

--

--