AWS: DynamoDB Nedir? | Bahadır AKIN
DynamoDB, Amazon Web Servislerinin sağladığı bir NoSQL veritabanı. Bildiğim kadarıyla, AWS ile son kullanıcıya sağlanmadan önce, yıllarca Amazon içerisinde kullanılmış ve kendini ispat etmiş bir veritabanı. NoSQL veritabanı türlerinden Key-Value olduğunu söyleyebiliriz. Yani büyük bir tabloda hash’lere karşılık değerler tutuluyor.
Şemasız veritabanı olarak geçiyor. Aslında bakarsanız bu tüm Key-Value tipindeki NoSQL veritabanları için geçerli. Bu saye de aynı şekilde Hash’leye bileceğiniz bilgileri aynı tabloda saklayabiliyorsunuz. Örneğin ürün kataloğu oluşturduğunuzu düşünün. Hangi kategoriden olursa olsun ürünlerinize şirket genelinde bir seri numarası atadığınızı düşünelim. Ürünleriniz tamamen farklı kategoride olabilir. Farklı kategorilerdeki ürünlerinizin de tabi ki farklı özellikleri olacaktır. Örneğin, kitap ürünlerinizde yazar, sayfa sayısı yayın evi gibi bilgileri tutarken, ayakkabı ürünlerinizde, ayakkabı numarası, rengi, modeli gibi bilgiler bulunacaktır. Aynı şekilde (ürün seri numaranızla) hash’lediğiniz için tüm bu bilgileri aynı tabloda tutabilirsiniz. Hatta isterseniz bu bilgileri kategorisine göre de sıralayabilirsiniz.
Bildiğiniz üzere NoSQL veritabanlarının çoğu ACID (Atomicity, Consistency, Isolation, Durability)’i desteklemiyor. Bende zaten bir NoSQL veritabanından hepsini desteklemesini beklemiyorum. Fakat tutarlılık konusunda çekincelerim oluyor. Bu sebepten bir NoSQL veritabanını incelerken ilk baktığım şeylerden biri oluyor. DynamoDB ise, tutarlılık için iki farklı çözüm öneriyor. Neticede tutarlı ve Kesin Tutarlı (Eventually Consistent ve Strongly Consistent)…
Neticede tutarlı, verilerinizi okurken yeni yapılan güncellemeleri almama ihtimaliniz var. Burada “yeni” çok göreceli bir kavram. Eğer DynamoDB dokümantasyonuna bakacak olursanız, yeni den kastının 1 sn içerisinde yapılan güncellemeler olduğunu göreceksiniz. Bir örnek üzerinden anlatmaya çalışayım. Bir tablonuzda kullanıcı adı ile kullanıcı bilgilerini tutuyorsunuz. Eğer kullanıcı bilgileri, siz okumadan 1 sn içerisinde güncellendiyse, siz hala eski veriyi alıyorsunuz. Kesin tutarlı ise tahmin edebileceğiniz gibi her okumanızda verinizin son halini alıyorsunuz. Tabi bunun bir bedeli oluyor. Kesin tutarlı yaptığınız okumalar, neticede tutarlıya göre daha maliyetli oluyor.
Bu fark size API düzeyinde sunuluyor. Yani okuma taleplerinizi yaparken ne şekilde okuyacağınıza siz karar veriyorsunuz.
DynamoDB’nin ölçeklendirilmesi, bana göre, alışılmışın biraz dışında. Bir AWS servisinden benim beklediğim otomatik olarak kendini ölçeklendirmesi. DynamoDB’de bunu bu şekilde yapıyor ama bunu yapmadan önce sizden öngördüğünüz saniyelik okuma ve yazma sayılarınızı istiyor. Bu bilgilere dayanarak, ne kadar kaynak kullanması gerektiğine, DynamoDB tablolarınızı sunuculara ne şekilde dağıtacağına falan karar veriyor. Tabi aynı zamanda da bu bilgiler üzerinden ücretlendiriliyorsunuz.
Burada insanın aklına hemen, “Peki ön gördüğümden daha fazla okuma/yazma yaparsam ne olacak?“, sorusu geliyor. Bunu bir örnek üzerinden anlatmaya çalışayım. Örneğin siz saniyede 10 okuma ve 10 yazma olacak şekilde ön görünü belirttiniz. Fakat sürekli olarak 11 okuma yapmaya çalışırsanız sistem yapmanızı engelleyecek ve ThrottlingException tadında bir exception ile karşılaşacaksınız. Ama diyelimki, anlık olarak 11 okuma yaptınız. O zaman bir exception ile karşılaşmazsınız. Sisteminizin yaşıyacağı anlık yoğunluklarda (pike vs) DynamoDB sizin lehinizde çalışacaktır. Her iki durumdada size aylık öngördüğünüz okuma ve yazma üzerinden fatura kesilecektir. Tabi isterseniz, saniyede 10 okuma ve 10 yazma olan değerinizi istediğiniz gibi değiştirebilirsiniz. Yani baktınız ki 11 okuma alıyorsunuz ve bu hep böyle devam ediyor değerlerinizi 11 okuma ve 10 yazma olarak değiştirmeniz mümkün. Bunu isterse AWS arayüzünden isterseniz size sağladığı API üzerinden yapabilirsiniz. Bu değerlerin nasıl hesaplandığının detayına dynamodb dokümantasyonundan erişebilirsiniz. Bu konuya ücretlendirme bölümünde tekrar döneceğiz.
Ücretlendirmenin nasıl olduğuna geçmeden önce terminoloji kısmına değinelim.
PartitionKey (a.k.a HashKey)
Tablonuzun olmazsa olması. Her ne kadar DynamoDB için Key-Value store dediysekte, şemasız olmasından ileri gelen Document Store benzeri özellikleri de bünyesinde barındırmaktadır. Bu sebepten internette arama yaptığınızda sıkça MongoDB ile karşılaştırıldığını göreceksiniz. Eğer DynamoDB’yi bir Document Store olarak düşünecek olursanız, HashKey’iniz dokümanınızın Id’si olarak düşünebilirsiniz.
PartitionKey denilmesinin sebebi ise, bu bilginin aynı zamanda bilgilerinizin nasıl dağıtılacağını belirlemesidir. İlk bölümde DynamoDB’nin ölçeklendirilebilirlik konusunda iyi olduğundan ve ölçeklendirmeyi sizin belirlediğiniz okuma ve yazma oranları üzerinden yaptığını belirtmiştik. DynamoDB ölçeklendirme kapsamında, sharding’de yapıyor. Sharding’yaparken hangi veriyi hangi sunucuya dağıtacağına yine bu key üzerinden karar veriyor.
Her ne kadar tablonuzun her alanı üzerinden arama işlemi yapabilsenizde, hızlı bir arama yapabilmek için HashKey’in yanında SortKey’e de ihtiyacınız olacak. SortKey yaratıp yaratmamak tamamen sizin tasarımınıza kalmış bir şey.
PrimaryKey (PK), RDB dünyasındaki gibi tekil bilgileri ifade etmektedir. Aslında, DynamoDB’de doğrudan PK tanımlamanız mümkün değil. Aynı şekilde AWS konsolu üzerinden baktığınızda PK olarak tanımlayabileceğiniz bir alan da bulamayacaksınız. Fakat Java API’sini kullandığınızda, aramalarınızı PK üzerinden yapabildiğinizi göreceksiniz. Bir DynamoDB tablosunda PK iki türlü olabilir:
PartitionKey + SortKey
PartitionKey tanımlamanızın zaten zorunlu olduğundan bahsettim. Eğer SortKey’de tanımladıysanız PK’iniz otomatik olarak PartitionKey + SortKey halini alıyor. Yani herşey PK doğrultusunda tekil olmak durumunda.
Adından da anlayabileceğiniz üzere ikincil index’ler. Yani hızlı arama yapmanızı sağlayan ek alanlar eklemeniz mümkün. Fakat bunu yaparken dikkatli olmalısınız, tanımladığınız index’in türüne göre, index’iniz için ek tablolar oluşuyor. Bu durumda da ücretlendirmenizde değişimler olabiliyor. Detaylarına DynamoDB’nin dokümantasyonu üzerinden ulaşabilirsiniz. Daha önce söyledim ama yeri gelmişken tekrar belirteyim, veritabanı üzerinde arama yapmak için ikincil index tanımlama gibi bir zorunluluğunuz yok.
Provisioned Throughput ve Capacity Units
Bu benim gözümde DynamoDB’nin en alengirli bölümü. Tüm ücretlendirme ve ölçeklendirme bu bilgiler üzerinden hesaplandığından, insan birazcık bile şüpheye düşse kazıklanıyormuş hissine kapılıyor. Sıradan bir kullanıcı olarak AWS’in böyle bir amacı olmadığına eminim ama, Türk aklı işte hemen gardımı alıyorum.
Provisioned Throughput, yani ön gördüğünüz yük miktarı, hem ölçeklendirmede hem fiyatlandırmada hem de yazılımınızı geliştirirken sık sık karşınıza çıkacak bir konu. Bunu iyi ölçüp biçmelisiniz. Eğer hiç bir değerinizi ölçmüyorsanız ilk başta hesaplamanız zor olabilir. Eğer fazla düşük verirseniz, hem sık sık yük miktarını aştığınızla ilgili Exception’lar alabilirsiniz hem de DynamoDB’nin tüm hızından yararlanamamış olursunuz. Gereğinden yüksek ayarlarsanız da tahmin edebileceğiniz gibi kullanmadığınız şeyler için ücretlendirilmiş olacaksınız. Peki ön gördüğümüz kapasiteyi nasıl hesaplayacağız? Ön gördüğünüz yük miktarını saniyede yaptığınız okuma ve yazma işlemlerini Capacity Units üzerinden hesaplamanız gerekiyor.
Şimdi gelelim Capacity Units kısmına. Capacity Units tahmin edebileceğiniz gibi bir ölçüm şekli. DynamoDB’de sakladığınız bilginin boyuna göre hesaplanıyor. Okuma ve yazma işlemine göre kullandığınız boyutlar değişiyor. En iyisi doğrudan örnekler üzerinden anlatmaya çalışayım.
Eğer okuyacağınız satır 4KB’tan küçükse: Saniyede yapacağınız her kararlı (Strongly Consistent) ya da her 2 neticede kararlı (Eventually Consistent) okumanız için 1 RCU (Read Capacity Unit).
Eğer okuyacağınız satır 4KB’tan büyükse: Örneğin okuyacağınız satır ya da veri 8.1 KB ise 3 RCU harcamanız gerekiyor.
Okuma işlemlerini sadece satır okumaları olarak düşünmeyin. Her türlü veritabanından yapacağınız okuma için geçerli bu durum.
Eğer yazacağınız bilgi 1KB’tan küçükse: Saniyede yapacağınız her 1KB’lık yazma işlemi 1 WCU (Write Capacity Unit) olarak hesaplanmaktadır.
Eğeryazacağınız bilgi 1KB’tan büyükse: Örneğin yazacağınız satır ya da veri 8.1 KB ise 9 WCU harcamanız gerekiyor.
Daha önce de dediğim gibi eğer ölçüm yapmıyorsanız bu değerleri bulmakta zorlanabilirsiniz.
En eğlenceli bölüme geldik, Ücretlendirme. Heralde en çok farkedecek kısım bu. Bu sebepten de sona sakladım. Ücretlendirmeyi hesaplarken her zaman alternatifini düşünmeniz de fayda var. Örneğin MongoDB mi düşünüyorsunuz alternatifi olarak. Oturun size gerekecek sunucuları, bu sunucların bakımları için harcanacak zamanları, kabataslakta olsa bir hesaplayın. Eminim takımınızda ki arkadaşlardan biri sunucular konusunda bilgi sahibidir hızlıca kuracaktır falan. Ama yine de oturup bir hesaplamaya çalışın.
FreeTier’da Amazon DynamoDB size 25 GB, 25 RCU ve 25 WCU sunuyor. Bu 1 yılın sonunda da kesilmiyor. Ondan istediğiniz gibi kullanabilir, test edebilirsiniz. Bence uygulamanızın maliyetini hesaplamak, en azınan bir POC çıkarmak için yeter de artar bile.
Öncelikle S3’te olduğu gibi rahat rahat ucuz demek isterdim. Ama ne yazık ki değil. Fakat, güzel tarafı, pahalı da değil. Yine online hesaplama aracını kullanarak istediğiniz gibi fiyatlandırmasına bakabilirsiniz ama ben bir kaç değerle size ne kadar olduğunu anlatmaya çalışayım.
Tablo sayısından bağımsız olarak:
100 GB’lık veri için 100 RCU ve 50 WCU kullanacak olursanız aylık ~40$.
100 GB’lık veri için 500 RCU ve 100 WCU kullanacak olursanız aylık ~100$.
250 GB’lık veri için 500 RCU ve 100 WCU kullanacak olursanız aylık ~150$.
100 GB’lık veri için 2500 RCU ve 500 WCU kullanacak olursanız aylık ~480$.
250 GB’lık veri için 2500 RCU ve 500 WCU kullanacak olursanız aylık ~525$.
Gördüğünüz üzere çok ucuz değil. (Değerleri özellikle büyük seçtim. Küçük uygulamalar için hala ucuz bence). Fakat yine de sırf veritabanlarınızın bakımını yapması, yedeğini alması, sunucularla ilgilenmesi için birini çalıştırıyorsanız 525$ hiç birşey (kaldı ki kaç uygulama saniyede 2500 okuma yapıyor, 500 yazma yapıyor).
DynamoDB tabiki de bu kadar değil. Daha DynamoDB Stream’lerinden, trigger mekanizmalarından vs. bahsetmedim. Daha bir kaç yazı daha o konulara değinmek istemiyorum. AWS ile ilgili bir sonraki yazıda planım Java API’lerini tanıtmak. Büyük ihtimalle ilk başta normal API’si sonrasında Mapper API’sine değineceğim.
Ek olarak ilginizi çekerse, güzel bir karşılaştırma