Merhaba arkadaşlar.
Bir önceki makalemde bir süredir Messaging yapıları üzerinde çalıştığımdan bahsetmiştim sizlere. Yine aynı şekilde bazı ihtiyaç ve kararlardan dolayı, NoSQL olarak Apache dünyasından Cassandra kullanmamız gerekti. Bu makalemde ise sizlere biraz geç de olsa Docker üzerinde Cassandra kurulumundan bahsedip, .Net üzerinde bir örnek gerçekleştireceğim.
Geliştirilmesine ilk olarak Facebook tarafından başlanıp sonrasında ise open-source bir hale gelerek, Apache tarafından devam edilmiş/edilmektedir. Özellikle yüksek ölçeklenebilirliğe ve yüksek performanslı bir distributed NoSQL mimarisine sahip olması dikkat çekmektedir.
Sorgulama dili ise CQL(Cassandra Query Language) olarak adlandırılıp, SQL’e çok benzemektedir. eBay, GitHub, Instagram, Netflix gibi hacimli siteler tarafından da kullanılmaktadır. Bir başka güzel yönü ise yüksek ölçeklenebilirliği sayesinde petabaytlarca veriyi tutabilirken, saniyeler içerisinde binlerce işlemi de gerçekleştirebilmektedir. Bunlara ek olarak doğrusal ölçeklenebilirliğe(fast linear-scale) de sahiptir. Yani -n sayıda node ile saniyede 200.000 işlem yapabilirken, sisteme bir node daha eklendiğinde ise işlem kapasitesi de artmaktadır.
Diğer bir güzel yanı da always on architecture’a ve tek kırılma noktasının olmaması(no single point of failure) ile sunucudaki herhangi bir hatadan dolayı tüm kümelerin çalışmasını engellememektedir. Çünkü klasik master/slave veya replication yapılarını kullanmaz. Verileri tüm node’lara dağıtmaktadır ve bu tüm node’lar, gelen request’lere response verebilecek şekilde tasarlanmıştırlar. Bu sayede herhangi bir node’da yaşanan sorun, tümünü etkilememektedir.
Cassandra’nın genel olarak şöyle özelliklerine bir bakmak gerekirse eğer:
Transaction içinde AID desteğini garanti ettiğini söylemiştik. Consistency konusunda ise opsiyonel bir seçenek sunar. Yani bu bizim ilgili veriyi nasıl okumak/işlemek istediğimizle alakalı bir durum. Örneğin response’u tüm node’lardan okuyarak al veya birkaçından okuyarak şu şu işlemi gerçekleştir gibi opsiyonel seçenekler mevcuttur.
Cassandra hakkında bu giriş bilgilerinden sonra dilerseniz kurulumuna geçelim. Kurulumu oldukça kolaydır ve farklı platform’lara destek vermektedir. Ayrıca Java ile yazıldığı için bilgisayarımızda java ortamının kurulu olması gerekmektedir. Download işlemlerini buradan gerçekleştirebilirsiniz.
Ben kurulum işlemini Docker üzerinden linux ortamında gerçekleştireceğim. Eğer sizde Docker üzerinden işlem yapmak isterseniz buradan ilgili işletim sisteminize göre olan versiyonu seçip, straightforward bir şekilde kurulumu gerçekleştirebilirsiniz.
Docker Quickstart Terminal’i açtıktan sonra
docker pull cassandra:latest
komutu ile güncel cassandra image’ini Docker Hub üzerinden sisteme çekelim.
Image’i sisteme çektikten sonra aşağıdaki komut ile container’ı çalıştıralım ve broadcast adresi olarak da “192.168.99.100” ip adresini kullanalım.
docker run --name cassandra -v /Users/MyProjects/scripts/:/script -d -p "9042 :9042" -e CASSANDRA_BROADCAST_ADDRESS=192.168.99.100 cassandra:latest
Bu komutun çalışmasından sonra, Cassandra’ya bağlanmak için hazır durumdayız.
Database işlemlerine başlamadan önce kafa karışıklığına sebebiyet vermemek için, Cassandra ile Relational Model’lerdeki kelime anlamlarına bir bakalım.
Relational Terms | Cassandra Terms |
Database | Keyspace |
Table | Column Family |
Row | Record |
Column | Column |
.Net tarafındaki değişiklikleri görebilmemiz için şimdi bize bir GUI lazım. Forumlarda biraz araştırma sonucu en yaygın olarak tercih edilen database tool’u olan DBeaver‘ı kullanmaya karar verdim. Free bir database tool’u olan DBeaver, multi-platform bir universal client’dır. Enterprise sürümünü buradan indirebilirsiniz.
DBeaver’ın kurulum işlemlerini gerçekleştirdikten sonra, açılan ilk ekrandan yeni bir connection oluşturalım. Bunun için connection type’ı “Cassandra CQL” olarak seçelim. Ardından “next” tuşuna basarak “host” adresi olarak daha önce broadcast olarak belirlediğimiz “192.168.99.100” adresini verelim ve “port” u “9042” olarak sabit bırakalım. Bu işlemlerin ardından ise “Test Connection” butonuna basarak her şeyin sorunsuz olduğundan emin olalım.
Connection işlemi başarılı bir şekilde gerçekleşti. Test işlemi ardından tekrardan “next” butonuna basarak işlemimizi tamamlıyoruz. Connection başarılı bir şekilde tanımlandı ve “Keyspaces” yani database listesi aşağıdaki gibi listelenmiştir.
GUI hazır olduğuna göre hemen bir adet test keyspace’i ekleyelim. Bunun için yeni bir SQL Editor açalım ve aşağıdaki sorguyu execute edelim.
CREATE KEYSPACE TestDB WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };
Not: Burada bulunan “WITH REPLICATION” satırı ile verinin kaç kopyasının yazılacağını ve “class” property’si ile de, verinin kopyalarının hangi node’lara yazılacağını replication strategy ile belirlemektedir. Burada iki adet strategy almaktadır. Bunlar özetle:
Execute işleminden sonra sol tarafda bulunan Database Navigator’ı refresh yaptıktan sonra oluşturmuş olduğumuz “TestDB” keyspace’inin geldiğini görebiliriz.
Test keyspace’ini oluşturduktan sonra içerisine bir adet de column family yani yeni bir table ekleyelim. “Products” column family’sini ekleyebilmek için aşağıdaki komut satırını kullanalım.
CREATE COLUMNFAMILY Products ( Id int, Name varchar, Quantity int, PRIMARY KEY (Id))
Yukarıdaki kodu execute ettikten sonra “products” column family’si aşağı görseldeki gibi “testdb” altında ki, “Tables” içerisine eklenecektir.
Diğer işlemler için artık .Net tarafına geçebiliriz. “CassandraSample” isminde yeni bir console application oluşturalım ve NuGet Package Manager üzerinden “CassandraCSharpDriver” paketini indirelim.
CassandraCSharpDriver paketi Datastax isimli firma tarafından geliştirilmekte olup, hakkında daha fazla bilgiye buradan ulaşabilirsiniz.
“CassandraCSharpDriver” client’ında context olarak “ISession” interface’i üzerinden ilerlemektedir. Bu interface’i initialize edebilmek için ise “Cluster” class’ının builder’ı kullanılarak, docker üzerindeki cassandra endpoint’ini girmemiz ve build etmemiz gerekmektedir. Build işleminin ardından elde ettiğimiz “Cluster” objesi ile, “Connect” method’unu kullanarak, daha önce oluşturmuş olduğumuz “keyspace” e bağlanıyoruz ve “ISession” interface’ini initialize etmiş oluyoruz. Dilerseniz kod üzerinden bir bakalım.
Cluster cluster = Cluster.Builder().AddContactPoint("192.168.99.100").Build(); ISession session = cluster.Connect("testdb");
Artık işlemlerimize “session” objesi üzerinden devam edeceğiz. Haydi bir kaç CRUD işlemi gerçekleştirelim.
using Cassandra; using System; using System.Linq; namespace CassandraSample { class Program { static void Main(string[] args) { Cluster cluster = Cluster.Builder().AddContactPoint("192.168.99.100").Build(); ISession session = cluster.Connect("testdb"); InsertNewRow(session); GetRowById(session, 1); UpdateRowById(session, 1, "Iphone 7 Gold", 400); GetRowById(session, 1); DeleteRowById(session, 1); Console.ReadLine(); } private static void InsertNewRow(ISession session) { session.Execute(@"insert into products (id, name, quantity) values (1, 'Iphone 7 Plus', 500)"); } private static void GetRowById(ISession session, int id) { var result = session.Execute($"select * from products where id={id}").First(); Console.WriteLine("Name: {0} Quantity: {1}", result["name"], result["quantity"]); } private static void UpdateRowById(ISession session, int id, string name, int quantity) { session.Execute($"update products set name='{name}', quantity={quantity} where id={id}"); } private static void DeleteRowById(ISession session, int id) { session.Execute($"delete from products where id={id}"); } } }
CQL sorguları ne kadar da SQL sorgularına benziyor değil mi? Evet CRUD işlemleri bu kadar basit. “session” objesinin “Execute” method’u kullanılarak, inline olarak CQL sorgularını yazıyoruz. Dilerseniz uygulamayı bir çalıştıralım ve sonucuna bakalım.
İlk önce “Iphone 7 Plus” isimli product’ı insert işlemini gerçekleştirdik ve ardından “GetRowById” method’u ile console’a yazdık. Ardından “UpdateRowById” method’u ile de product’ın name’ini “Iphone 7 Gold” ve quantity’sini 400 olarak güncelledik.
Peki hepsi bu kadar mı? Tabi ki hayır. Bir örnekte simple mapping üzerine gerçekleştirelim.
private static void SimpleMapping(ISession session, int id) { IMapper mapper = new Mapper(session); // Fluently bir şekilde entity'leri map'liyoruz. MappingConfiguration.Global.Define( new Map<Product>() .TableName("products") .PartitionKey(p => p.Id)); // Daha fazla örnek kullanım için: http://datastax.github.io/csharp-driver/features/components/mapper/#mapper-api-example var product = mapper.First<Product>("select * from products"); Console.WriteLine("Name: {0} Quantity: {1}", product.Name, product.Quantity); }
Burada ise “Mapper” objesini yine “session” üzerinden itinialize ediyoruz. Fluently bir şekilde “Product” entity’sini “MappingConfiguration” üzerinde map’liyoruz. Mapping işlemlerinden sonra ise oluşturmuş olduğumuz “mapper” context’i üzerinden “mapper.First<T>” method’unu kullanarak, içerisine girmiş olduğumuz CQL sorgusu sonucunda result’ın mapping işlemini gerçekleştiriyoruz.
Bu ve buna benzer daha fazla Fluent method’lar için ise, buraya bir göz atabilirsiniz.
Yukarıda vermiş olduğumuz bilgilerin ardından konuyu bir toparlamak gerekirse:
gibi bir çok nedenlerden dolayı tercih edilebilir.
Umarım keyifli bir yazı olmuştur. Örnek projeye ekten erişebilirsiniz.
Takipte kalın…
{:tr} Makalenin ilk bölümünde, Software Supply Chain güvenliğinin öneminden ve containerized uygulamaların güvenlik risklerini azaltabilmek…
{:tr}Bildiğimiz gibi modern yazılım geliştirme ortamında containerization'ın benimsenmesi, uygulamaların oluşturulma ve dağıtılma şekillerini oldukça değiştirdi.…
{:tr}Bildiğimiz gibi bir ürün geliştirirken olabildiğince farklı cloud çözümlerinden faydalanmak, harcanacak zaman ve karmaşıklığın yanı…
{:tr}Bazen bazı senaryolar vardır karmaşıklığını veya eksi yanlarını bildiğimiz halde implemente etmekten kaçamadığımız veya implemente…
{:tr}Bildiğimiz gibi microservice architecture'ına adapte olmanın bir çok artı noktası olduğu gibi, maalesef getirdiği bazı…
{:tr}Bir önceki makale serisinde Dapr projesinden ve faydalarından bahsedip, local ortamda self-hosted mode olarak .NET…
View Comments
Docker hakkinda detayli bir makale bekliyoruz hocam
Katılıyorum +1
Yazı için teşekkür ederim Gökhan Bey, şöyle bir senaryo için cassandra kullanmak ne derece uygundur.
Elimde yüksek miktarda resim ve bunlara ait text formatta etiket verisi var, bu veri üzerinde sürekli olarak read/write işlemi uygulanıyor herhangi bir os file system istenilen performansı vermiyor, bu durumda cassandrayı tercih etmek neler kazandırır/kaybettirir. Şimdiden teşekkür ederim.
Merhaba, ne derece büyük veriniz var ve bu resimleri nasıl persist ettiğinizi bilmiyorum. Cassandra özelinde değil de, sadece read/write işlemi yapmanız gerekiyor ise text formattaki etiket verileriniz için, size herhangi bir key-value store NoSQL çözümü yararlı olacaktır.
Son zamanlsrda cok karsilasiyorum bende duzgun detayli turkce bir yazi yok gercekten. Bir yazi gelirse mukemmel olur
Merhaba, teşekkür ederim öncelikle yorumunuz için. Uygun bir vakitte değerlendirmeye çalışacağım Docker hakkında bir kaç yazı.
Merhabalar, sharding mekanizması tam olarak nasıl işliyor bahsederseniz sevinirim.
Öncelikle yazı için teşekkür ederim.
Acaba ilk etapta pull ederken aşağıdaki gibi bir hatayla karşılaştınız mı ?
(Docker for windows)
Error response from daemon: Get https://registry-1.docker.io/v2/: x509: certificate signed by unknown authority
Merhaba, ben teşekkür ederim. Malesef o tarz bir hata ile karşılaşmadım. Proxy kaynaklı bir hata olduğunu söylüyorlar. Bir bakabilirsiniz. https://github.com/docker/toolbox/issues/603