Geçtiğimiz iki yılda küresel İnternet ve bilgisayar kullanımı logaritmik olarak artmıştır. Web 2.0 konseptinin doğuşu ile beraber bilgisayara yüklenerek çalıştırılan birçok uygulama İnternet’te yerini almaktadır. Bu değişim ile uygulamaların tabiatı tekli kullanım modelinden çoklu kullanım modeline doğru yer değiştirmiştir.
Böylesine büyük bir değişim mobil kullanımının yaygınlaşması ile beraber müthiş ölçüde kaynak ihtiyacı doğurmuştur. Her ne kadar donanımların hızı her geçen yıl artıyor olsa da geleneksel uygulama geliştirme yöntemleri mevcut donanım kapasitesini kullanamamaktadır. Bu durumun en tipik örneği I/O olarak adlandırılan veri işleme (okuma ve yazma) yöntemlerindeki dar boğazlardır. İnsanlık tarihi boyunca kayıt altına alınan verinin sadece 2012 yılı içinde kaydedildiği düşünüldüğünde bu denli büyük bir veri işlem artışının hızlı olarak servis edilebilmesi için yenilikçi kod geliştirme ve veri işleme yöntemlerine ihtiyaç duyulduğu aşikardır. Neden Asenkron Programlama?
Temel olarak bilgisayar CPU ve RAM bileşenlerinin her geçen gün daha yüksek hız ve kapasitelere çıkmalarına karşın veri saklamak için kullanılan disk teknolojisi ve uygulama geliştirme teknolojileri geçtiğimiz 10 yılda aynı artışı gösterememiştir. Bu nedenle daha verimli kod işleme ve veri barındırma hizmetleri geliştirilmiştir.
Aşağıdaki tablo veri işleme aşamalarında bilgisayar ekipmanlarının hız farklarını göstermektedir. Bir http browser HTTP GET yada POST işlemleri çalıştırdığında data stream’in frekans cycle’ı düzlemindeki gecikmesi aşağıdaki tabloda gösterilmektedir.
I/O Latency CPU L1 Cache 3 cycles CPU L2 Cache 14 cycles RAM 250 cycles Disk 41.000.000 cycles Network 240.000.000 cycles
Buna göre CPU’da I/O fetch execute edildiğinde CPU internal cache ile RAM arasında yaklaşık 20 kat, DRAM ile rotasyonel disk arasında ise 164.000 kat hız farkı vardır. Bu durumda mevcut kaynakların son derece efektif olarak kullanılması elzemdir. Verimlilik artışı en etkin kaynakta sağlanabilmekte, dolayısıyla kod işleme ve kod yazım tekniklerindeki yüksek concurrency ile sağlanabilmektedir.
Geleneksel kod yazım tekniklerinde kod genelde seri execute edilmektedir. Her ne kadar bir süre önce threaded kod yazım ve execute teknikleri geliştirimiş olsa dahi her bir thread içindeki kod dizileri seri olarak işlenmekte ve ek olarak bir çok yerde (örneğin veri işleme ya da kimlik doğrulamada) threaded kod execute edilmemektedir. Aşağıdaki tipik bir örnek ile bu durum anlatılabilir.
Toplam 270ms = SUM (kullanıcı,faaliyetler,aktif)
Bu tip bir kod yazım tekniğinde I/O bloke olmaktadır (Blocked I/O). Zaten fiziksel olarak yavaş olan I/O katmanı gecikmesine bir o kadar da kod katmanında gecikme eklenmektedir.
Aşağıda ise Non-Blocking I/O olarak tabir edilen yöntemi ile kod yazım tekniği bir örnek ile açıklanmaktadır.
Toplam 150ms = MAX (kullanıcı,faaliyetler,aktif)
// Kullanıcıyı bulalım – 20ms $query = ‘SELECT * FROM users WHERE id = ?’; $users = query($query, array($id)); print_r($users); // Kullanıcı faaliyetlerini okuyalım – 100ms $query = ‘SELECT * FROM activities ORDER BY timestamp LIMIT 50’; $activities = query($query); print_r($activities); // En aktifleri bulalım – 150ms $query = ‘SELECT count(points) as total, user_id FROM activities LIMIT 50’; $leader_board = query($query);
// Kullanıcıyı bulalım – 20ms var query = ‘SELECT * FROM users WHERE id = ?’; db.query(query, [userId], function (err, results) { console.log(results); }); // Kullanıcı faaliyetlerini okuyalım – 100ms var query = ‘SELECT * FROM activities ORDER BY timestamp LIMIT 50’; db.query(query, function (err, results) { console.log(results); }); // En çok faaliyette bulunanları bulalım – 150ms var query = ‘SELECT count(points) as total, user_id FROM activities LIMIT 50’; db.query(query, function (err, results) { console.log(results); });
Milyonlarca üyesi bulunan bir web sitesinde aynı anda yüzbinlerce talebin işlenmesi olağandır. 150ms beklemeden kaynaklanan hız farkı yüzbinlerle çarpıldığında olağanüstü bir fark ortaya çıkmaktadır. Bu fark donanım takviyesi ile rasyonel olarak kapatılamayacağı gibi kod geliştirme ve operasyonel yönetim imkansıza doğru kaymakta, günün sonunda yeni bir özellik eklemeye ayrılan zamandan çok mevcut uygulamayı istenilen hızda çalıştırmaya zaman harcanmaktadır. Sonsuz kaynak ile işletilen bir sistem dahi olduğu var sayılsa üretim karmaşıklığı ve yüksek hata oranları aşılamaz darboğazlardır.
Threaded (Bunnies) vs Eventloop (Hyperactive-Squid)
Asenkron kodlama ve beraberinde sunduğu non-blocking I/O avantajı eventloop denen kod execution tekniğine dayanır. Event-loop tekniği geleneksel threaded kod execution tekniğine göre bambaşka bir bakış açısı sunmaktadır. Bu nedenle threaded yazılan kodların event-loop yöntemine kolay dönüşümü yapılamaz. Projelerin en baştan bu şekilde ele alınması gerekmektedir.
Aşağıda sıklıkla kullanılan bir benzetme ile threaded ile event-loop kod execution teknikleri farklılıkları anlatılmaya çalışılmaktadır.
Her bir thread süratli tavşanlara benzetilmektedir. Her gelen talep için bir thread koşmakta ve talep sayısı thread sayısını geçtiğinde queue uygulanmaktadır.
Thread# 1 fetch web API (2sn)
Thread# 2 image yükle (2sn)
Thread# 3 fetch web API (2sn)
Thread# 4 fetch web API (2sn)
Thread# 5 long polling (2sn)
Impatient hamsters
fetching a web AP I (2 seconds)
uploading an image (3 seconds)
fetching a web AP I (2 seconds)
comet long polling (10 seconds)
fetching a web AP I (2 seconds)
Impatient hamsters
fetching a web AP I (2 seconds)
uploading an image (3 seconds)
fetching a web AP I (2 seconds)
comet long polling (10 seconds)
fetching a web AP I (2 seconds)
Impatient hamsters
fetching a web AP I (2 seconds)
uploading an image (3 seconds)
fetching a web AP I (2 seconds)
comet long polling (10 seconds)
fetching a web AP I (2 seconds)
Impatient hamsters
fetching a web AP I (2 seconds)
uploading an image (3 seconds)
fetching a web AP I (2 seconds)
comet long polling (10 seconds)
fetching a web AP I (2 seconds)
Impatient hamsters
fetching a web AP I (2 seconds)
uploading an image (3 seconds)
fetching a web AP I (2 seconds)
comet long polling (10 seconds)
fetching a web AP I (2 seconds)
Burada ise süratli tavşanların yerini tek bir hiperaktif mürekkep balığı yer almaktadır. Mürekkep balığı yukarı ve aşağı olağanüstü bir hızla gider gelir ve her bir talebi alır. I/O operasyonlarını anında arka plana atar ve tamamlandığında geri bildirim yapar.
Bu örneği gerçek HTTP istekleri için anlatmak gerekirse her bir HTTP talebi için bir thread açılmaktadır. Bu şekilde paralellik sağlanmaya çalışılmaktadır. Ancak thread’ler kod dizinlerine göre değil kullanıcı session’larına göre örtüşür. Bu durumunda kullanıcıların art arda gelen talepleri farklı thread’lere bölünemez ve kuyruğa düşmektedir. Ayrıca thread sayısı session sayısını geçtiğinde yeni gelen sessionlar beklenmeye alınır.
Event-loop tekniğinde ise her bir kod dizini Call-Back ile yazılmaktadır. Callback’e bağlanan kod dizinleri asenkron olarak aynı anda çalıştırılır. Call-back yöneticisi her bir kod dizininden işleri alır ve asenkron olarak arka planda çalıştırır. Her bir Call-Back dönüşü yine asenkron olarak kontrol edilir ve session içindeki çoklu taleplere büyük bir hız farkı ile geri dönülür. Aşağıdaki örnek ile dünya genelinde kullanılan iki web sunucu performans testleri sonucu threaded ile event-loop teknikleri arasındaki farkı göstermektedir.
concurrency × reqs/sec
concurrency × memory
Apache ile NGINX web sunucusu arasındaki fark nedir? Apache her bir bağlantı için bir thread kullanmaktadır. NGINX ise thread kullanmaz, event-loop tekniği ile gelen bağlantıları yönetmektedir. Milyonlarca kullanım söz konusu olduğunda aradaki fark muazzamdır. Asenkron kod tekniği yeni bir tekniktir. Geleneksel yöntemler ile tamamen ayrışmaktadır. Hem kod işleme dili hem execution platformu farklılık göstermekte ancak en büyük fark kod yazımıdır. Kod dizileri en temel belirleyici unsurdur, senkron yazılan bir kod asenkron platformda yine senkron olarak çalışmaktadır.
Neden NoSQL?
Muazzam kullanıcı artışı ile beraber veri depolama ihtiyacı hiç olmadığı kadar artmıştır. Bu artış donanım üreticileri tarafından üretim tekniklerindeki sağlanan yüksek verimlilik ile karşılanabildiyse de mekanik rotasyonel plaka tabanlı disklerde aynı oranda hız artışı sağlanamamıştır.
Bu durum veri saklayan, servis eden ve koruyan uygulama platformları için (veri tabanı uygulamaları) yeni zorluklar getirdi. On yıllar öncesi teknolojik tasarıma sahip veri tabanı uygulamaları RMDBS yaklaşımın limitlerine yaklaştılar. Tek çözüm olarak görülen yanal büyüme ve yük dengeleme yöntemlerinden faydalanma çabaları ise RMDBS’in temel tasarım limitlerini aşamadı ancak daha yüksek kapasiteleri hizmet vermeye yetti. Bunun karşılığında yüksek maliyetli ve idamesi zor özel donanım kullanımı ortaya çıktı.
Geçtiğimiz bir kaç yılda özellikle mobil kullanımın exponensiyel artış ile veri hacimlerini hiç olmadığı kadar arttı. RMDBS ile yanal ve pahalı büyüme limitleri zorlandı. Bu nedenle veri tabanı uygulamalarına güncel bir tasarım yaklaşımı gerekti. Bu yeni yaklaşıma NoSQL adı verildi. NoSQL veritabanı sistemleri binlerce terrabyte veriyi hızlı ve kolayca servis edebilmeye uygun olarak tasarlanmakla beraber RMDBS’in hantal veri işleme engine’lerine göre muazzam hızla veri işleyebilmektedir.
NoSQL veri tabanları geleneksel veri tabanlarından tamamen farklıdır. Bilindik veri tabanı dizaynı, geliştirme ve yönetimi NoSQL veri tabanlarında geçerli değildir.
Aşağıda SQL ve NoSQL yaklaşım temel unsurları verilmektedir.
Temel SQL Karakteristikleri: Veri kolon ve tablolarda tutulur. Veri ile ilişkiseldir. Veri manipülasyon dili kullanılır. o Select, Inset, Update & Delete Veri tanımlama dili kullanılır. o Schema, tablo, primary key, trigger Transaction tabanlıdır. o ACID özellikleri (Atomic, Consistent, Isolated, Durable) Fiziksel katmandan ayrıdır. o Index
Temel NoSQL Karakteristikleri: Non-Relational’dır. Veri dağıtık olarak saklanabilir. Yanal büyüyebilme (Horizintal Scalable) Schema-free tasarıma sahiptir. Kolay replikasyon yapılabilir. BASE yaklaşımına sahiptir o Basically Available Soft-state with Eventual Consistent Big Data yaklaşımı ile veri madenciliği yapılabilir.
Günümüzde 121 farklı NoSQL veritabanı bulunmaktadır. İlk NoSQL kullanımları Google ve Amazon’da yer bulmuştur. NoSQL veri tabanları potansiyel olarak binlerce makinede ve dünyanın çeşitli yerlerinde coğrafik bağımlılığı olmadan çalışabilirler. Asenkron insert ve update yetenekleri ile beraber RMDBS’lerden farklı olarak çok hızlı query yanıtı dönülebilmektedir. İlk türevleri daha çok okuma amaçlı kullanılsa da hızlı write özellikleri geliştirilmesiyle beraber günümüzde tam anlamıyla RMDBS veri tabanı alternatifi olarak kullanılmaktadır.
Milyonlarca kullanıcılara sahip sosyal ağ siteleri (Facebook, Twitter, Google vb.) RMDBS limitleri ve yüksek yatırım & operasyon maliyetleri nedeniyle NoSQL veri tabanları kullanmaktadır. Facebook aynı anda 100 milyon kullanıcıya ancak NoSQL ile servis verebilmektedir.
NoSQL veri tabanlarının en temel farklarından birisi veri tabanı tasarımı kolaylığıdır. Aynı amaçla tasarlanan bir RMDBS veri tabanı 198 ilişki ve 53 farklı bağımlılık içerirken NoSQL ile 18 ilişki ve 6 farklı bağımlılık içerebilmektedir. Bu yönüyle hata oranları NoSQL veri tabanlarında çok daha düşüktür.
NoSQL veri tabanları sundukları avantajları yanında RMDBS’lere göre 1/5 oranında ilk yatırım ve operasyonel maliyetlere sahiptir (CapEX ve OpEX).
NoSQL veri tabanları çeşitli amaçlara göre farklı türlere sahiptir. – Coloumn Store – Document Store – Key-Value Store – Graph Store
Her bir NoSQL türü belirli bir amaca hitap etmekte ve uygulama geliştirici tarafından özenle seçilmelidir.
NoSQL veri tabanları ACID transaction overhead olmaksızın, SQL karmaşasından uzak, schema tasarımı zorluğu olmadan geleneksel RMDBS veri tabanı zorluklarını aşabilmektedir. Bununla beraber uygulama geliştiriciler daha fazla uygulama seviyesinde veri tabanı kullanımı ve kontrolü ile sorumludur. Uygulama geliştiriciler daha fazla veri tabanı prensiplerine hakim olmak zorundadırlar.
NoSQL bakış açısı dünya genelinde kabul edilmiş CAP Teorisi (Brewer’s konjoktürü) ile açıklanabilir. Bu teoreme göre; “Ortak veri paylaşan sistemlerde ancak ikisi elde edilebilir; Consistency, Availability ve Partition Tolerence”. – Consistency: Veri yazıldığı anda gelecektir, tüm okumalar veriyi içerir. – Availability: Veritabanı her zaman oradadır ve istenen ölçüde cevap verir. – Partition Tolerance: Veri tabanı kısımların birisi ayakta değilse diğer kısımları etkilenmez.
Dünyada kullanım örnekleri
Dünyada asenkron kodlama ve NoSQL veri barındırma yüksek performans, yüksek kapasite, yüksek devamlılık ve gerçek zamanlı web uygulamaları gerektiren alanlarda kullanılmaktadır.
Google, Facebook, Linkedin ve Amazon en büyük örnekleridir. Google petabytelarca veri işlemesini bir kaç sn’de asenkron kodlama ve NoSQL veritabanı ile gerçekleştirebilmektedir.
Facebook aynı 100 milyon kullanıcıyı asenkron kodlama ve NoSQL veritabanı ile çalıştırabilmektedir.
300 milyondan fazla profesyonele sosyal paylaşım hizmeti veren Linkedin’in geçtiğimiz yıllarda 225 sunucu ile sorunlu çalıştırdığı mobil uygulamasının yeni nesil asenkron kodlama ve NoSQL alt yapısı ise sadece 4 adet sunucuda çalıştırabilmesi çok çarpıcı bir örnek olarak öne çıkmaktadır.
Günümüzde hızla gelişen bulut bilişim dünyasında NoSQL veri tabanları muazzam genişleme imkanı, hızlı çalışma prensipleri ile BigData ve Cloud Computing veri tabanları olarak yerini almıştır.