AWS: DynamoDB Nedir?

Bu yazıda AWS’in sağladığı başka bir veri saklama yönteminden, DynamoDB’den bahsedeceğim. Genel olarak, terminolojisine ve ücretlendirmesine değineceğim. Uzun bir yazı olmasını istemediğimden Java ile nasıl uygulama geliştirilir gibi konulara değinmeyeceğim.

DynamoDB Nedir?

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

Ş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.

Tutarlılık (Consistency)

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.

Ölçeklendirilebilirlik

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.

Terminoloji

Ü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.

Sort Key

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.

Primary Key

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:

  1. PartitionKey
  2. 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.

Secondary Indexes

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.

Okuma

  • 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.

Yazma

  • 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.

Ücretlendirme

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.

Free Tier

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.

Paralı Tier

Ö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).

Son

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

  • Mesut Özen

    Türkçe yazılmış en iyi DynamoDB yazısı için teşekkürler.
    ThrottlingException hatasını manuel handle etmek yerine otomatik handle edemez miyim? Yani bir policy ya da bir rule tanımlasam,desem ki read şu periyotta read 10’u geçerse otomatik olarak read sayısını artır.

    • bhdrkn

      Merhaba Mesut Bey,

      Gerçek olduğunu bilsem bile böyle bir yorum almak çok güzel.

      “ThrottlingException” hatasını handle etmek için bir kaç farklı yönteminiz var.
      Birincisi, “Backoff and Retry” yapmak. Yani bir süre bekleyip işleminizi tekrar etmeniz. Bunu için ek bir şey yapmanıza gerek yok. AWS DynamoDB SDK’yi bunu otomatik olarak yapıyor. Bu özelliği istediğiniz gibi ayarlamanız ya da kendi “Backoff and Retry” stratejinizi belirlemeniz mümkün. Önceden tanımlı stratejiler için http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/retry/PredefinedRetryPolicies.html sınıfını inceleyebilirsiniz. Bu konuya, Java ile DDB erişimini anlattığım yazımda detaylı olarak değineceğim.

      İkinci alternatif ise sizin dediğiniz gibi RCU ve WCU değerlerini dinamik olarak arttırıp azaltmak. Bunu yapan bir uygulama geliştirmişler, https://github.com/sebdah/dynamic-dynamodb adresinden erişebilirsiniz. Sizin RCU ve WCU kullanımlarınıza bakarak değerlerinizi tekrardan ayarlıyor. Yanlız şöyle bir durum var. AWS sizin günde 4 kereden fazla RCU ve WCU değerlerinizi azaltmanıza izin vermiyor. AWS izin verse bile böyle bir yöntemin ne kadar sağlıklı olacağını bilmiyorum. Bence çok sağlıklı olsaydı zaten AWS kendi böyle bir özellik sunardı ya da en azından limit koymazdı. Ama yine de bu tip bir işlemi Java üzerinden de yapmanız mümkün.

      Diğer DynamoDB limitlerine http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html adresinden erişebilirsiniz.

      Tekrardan çok teşekkür ederim
      İyi çalışmalar

      • Mesut Özen

        RCU ve WCU değerlerini sürekli değiştirmek durumunda kalmak bence de çok mantıklı değil.Backoff and Retry stratejisini kendim belirleyebilmem hoşmuş.
        Amazon ile ilgili ec2,vpc yazılarınızı da heyecanla bekliyorum 🙂

        Ben teşekkür ederim asıl 🙂

  • Yasin Kaya

    Gerçekten sade, güzel bir yazı olmuş. Ellerinize sağlık…