Bir Taşınma Hikayesi — MySQL -> MongoDB

Beytullah Gurpinar
Teknasyon Engineering

--

Bu yazıda, geliştirici olacak çalıştığım ve sürekli büyümeye devam eden, kategorisinde 5'den fazla ülkede 1. olan projemizde kullandığımız veritabanları ve bunlara ek yeni veritabanları entegrasyonlarını, bu entegrasyonlar sırasında elde ettiğimiz deneyimleri anlatmaya çalışacağım.

Günümüzde Start-up projeler, genellikle daha hızlı ortaya çıkması ve ürüne dönüştürülmesi için genellikle en çok kullanılan teknolojiler ve veritabanları ile başlamaktadır. Çünkü projenin amacı bir an önce yayına çıkıp yaratacağı etkiyi görmektir. Bundan dolayı da projenin mimari altyapısı, çok fazla kullanıcı geldiğinde scale edilebilir olup olmaması çoğunlukla dikkate alınmaz. Bugün Unicorn olan bir çok proje de bu şekilde başlamış ve sonradan mümkün olduğu kadar altyapısını iyileştirmiş, kimisi kendisine özel ürünler ortaya çıkarıp bunları open source olarak sektör ile paylaşmış, kimisi ise bir ürün haline getirip satmaya başlamıştır.

Varmak istediğim nokta, bizim projemiz de startup düşüncesi ile başlamış, sonra sektöründe birinci olmuş ve veritabanı olarak da kullandığı platformun izin verdiği ölçüde scale edilebilmiştir. MySQL veritabanı kullandığımızdan ve projenin büyüme hedeflerine oranla artık daha fazla scale edilemeyeceğini düşündüğümüzden dolayı farklı veritabanları arayışına girilmiştir. Bu süreç içerisinde yatay olarak daha kolay büyütülebileceği için özellikle NoSQL veritabanları ve opensource projeler incelenmiştir.

Araştırdığımız Veritabanları

Cassandra

Cassandra, Java ile geliştirilmiş, açık kaynak kodlu, dağıtık bir NoSQL veritabanıdır. Facebook tarafından geliştirilmiştir. 2009 yılında Apache’ye devredilmiştir. İlk çıkış amacı Mysql üzerinde datanın hızlıca aktarılabileceği ve sql sorgularının da çalışabileceği bir NoSql veritabanı oluşturmaktır.

Neden Cassandra Seçmedik: Cassandra altyapı olarak ihtiyaçlarımızın çoğunu karşılıyordu. Ancak Devops süreçleri ve monitoring işlemleri için çok fazla deneyim gerektiğinden bunu tercih etmedik.

DynamoDB

Amazon DynamoDB, bulut tabanlı bir NoSQL key/value veritabanıdır. Amazon tarafından geliştirilmekte ve AWS içerisinde kullanılmaktadır. Yapı olarak Cassandra’ya benzemektedir.

Neden DynamoDB Seçmedik : DynamoDB kullanmamız durumunda AWS bağımlığı yaratacağından ve data büyüdükçe maliyet yönetimini zor olacağından dolayı DynamoDB kullanmayı tercih etmedik.

MongoDB

MongoDB, MongoDB Inc. tarafından C++ programlama dili kullanılarak 2009 yılında geliştirilmeye başlanmış , doküman tabanlı ve ölçeklenebilir bir NoSQL veritabanıdır. Günümüzde bir çok büyük projenin altyapısını oluşturmaktadir. ReplicaSet ve Sharding olmak üzere 2 farklı türde yatayda büyümeyi desteklemektedir.

Biz data yapımıza daha uygun olduğunu düşündüğümüz için MongoDB’de kullanmaya karar verdik. Ayrıca DevOps süreçlerinin diğer veritabanlarına oranla daha kolay ve yönetilebilir olması seçmemizi arttıran en büyük nedenlerden birisi oldu.

Biz projemizde kullanıcılara ait bilgiler ve kullanıcılara uygulama içinde verdiğimiz istatistik datasını MySQL’den MongoDB üzerinde tutmaya ve cevap dönmeye karar verdik. Sayı olarak kullanıcı datası 5 milyar document, istatistik datası da 10 milyar döküman civarı yer tutmaktadır.

Taşıma için Python ile yazdığımız bir migration kütüphanesi kullanarak paralelde çalışan ortalama 200 worker ile bu dataları 2 gün içerisinde realtime olacak şekilde MongoDB’ye taşıdık. Taşıma işlemi bittikten sonra da uygulamaya ait API üzerinden cevapları MongoDB üzerinden dönmeye başladık. Bu işlemler sırasında projeyi hiç kapatmadan arka planda geçiş işlemini sorunsuz tanımladık.

Biz MongoDB büyüme metodu olarak Replica Set kullanmaya karar verdik. Bu şekilde 1 Master N Slave makineyi yönetebiliyoruz. okuma yükünü tamamen slave üzerine vererek master sunucunun sadece yazma işlemini sağladık. Böylece trafik durumunda master’ın sadece kendi işini yapmasını sağladık.

Bir ülkeye açılacağımız zaman ya da farklı bir trafik beklentisi durumunda slave makineleri istediğimiz kadar arttırabiliyoruz ya da ihtiyaç olmadığında kapatabiliyoruz. Böylece hem kaynak hem de maliyet yönetimi konusunda elimizi çok güçlendiriyor.

Geçiş Bize Neler Kazandırdı

  1. Kaynak yönetimi konusunda artık daha esneğin ve istediğimiz kadar ve istediğimiz zamanda büyüyüp küçülebiliyoruz. Böylece veritabanı ile ilgili olan kaygılarımız azaldı, devops ve development ekiplerinin veritabanını düşünerek geliştirme yapma kaygısı büyük ölçüde azaldı. (Tamamen azalması hiç bir zaman ve hiç bir yapıda mümkün olmayacak :) )
  2. MySQL’e harcadığımız kaynağın üçte birini kullanarak, MySQL zamanı gelen kullanıcının 4 katından fazlasına cevap verebilir olduk. Kullanıcı sayımız artmasına rağmen kaynaklarımız küçüldü ve bu bize hem maliyet olarak hem de sunucu yönetimi olarak büyük avantajlar sağladı.
Hiç Kaynak Arttırmadan Artan Kullanıcısı Sayısına Rağmen Sorunsuz Cevap Vermeye Devam Ettik

3. Daha hızlı response time değerine ulaştık. Böylece uygulama açılış hızımız ve uygulama içinde ekran geçişlerimiz 5 kata yakında daha hızlandı. Kullanıcılara daha iyi bir deneyim sunarak,ürünümüzü daha çok kullanmalarını sağladık.

4. Birden fazla veritabanına bağımlılıktan kurtulduk. Projemizde yer alan MySQL ve ElasticSearch içerisinde yer alan tüm dataları MongoDB’ye taşıyarak ilgili servislerin cevaplarını MongoDB üzerinden sorunsuz vermeye başladık. Böylece sadece MongoDB yönetimi ve monitoringi yaptığımızdan diğer işlerimize daha fazla vakit ayırabilir olduk.

Peki Geçiş Aşamasında Neler Öğrendik, Ne Gibi Sorunlar Yaşadık

Örnek Bir Data Yapısı

Doğru Döküman Yapısı Kullanma

MongoDB yapısı gereği json olarak verileri saklamaktadır. RDBMS’ler gibi kayıtlar satır satır değil sizin belirleyeceğiniz bir json datası halinde saklanmaktadır. O yüzden bir MongoDB collection oluştururken sağladığı data serbestliğine çok kapılmadan, MySQl kullanırmış gibi data yapınızı baştan belirlemek ve buna bağlı kalmak işinizi ileride çok kolaylaştıracaktır.

MongoDB Aggregation operatörü ile sum, distinct, avg gibi sorguları desteklemektedir. Ancak yüksek yük altında bu sorgular çok ciddi kaynak kullanımına yol açmaktadır. O yüzden mümkün olduğunca son kullanıcıya verilen sonuçlarda Aggregation kullanmaktan kaçınılmalı, bu gibi ihtiyaçlar veritabanı dizayn aşamasında planlanmalıdır.

Biz istatistik collection’larında datayı kaydederken MongoDB’nin matematik komutları ile inc işlemi yaparak datayı sakladık. Böylece sorgu ile sum yapmaya hiç ihtiyacımız kalmadı. İstediğimiz kullanıcıya ait verilari tek sorgu ve döküman ile alabilir olduk. Bu işlem bize MySQL’de 1000 satırda yapabileceğimiz işlemi tek döküman ile yapma avantajı sağladı.

Doğru Kaynak Kullanımı

MongoDB dataları kendi oluşturduğu bson formatında dosyalarda saklamaktadır. Oluşturulan index’ler de aynı formatta dosyalarda ayrı şekilde tutulmakta, sonuçlar onlar üzerinden verilmektedir.

Her bir collection ve index’in ayrı bson dosyalarında olduğundan ve sorgulamaları bu dosyalardan yaptığından MySQL’e göre daha fazla disk üzerinde okuma — yazma işlemi yapmaktadır. Eğer sunucuya ait disk’te bir IOPS kısıtlaması varsa, bu sorgu performanslarınızı etkilemektedir.

MongoDB, kendi içinde kullandığı bir cache mimarisi ile çok kullanılan sorguları ya da dataları ram üzerinde tutmaktadır ve bu kayıtlarla ilgili bir sorgu geldiğinde ram’den vermektedir. Bu nedenle sunucuya ait ram özellikleri de sorguları etkileyebilmektedir.

MongoDB, tüm işlemleri disk üzerindeki dosyalarda yaptığından, kullanılan diskin read-write özelliklerinin iyi olması gerekmektedir. Buradaki özellikler proje trafiği ve data boyutuna göre değişkenlik gösterebilir.

Bizim MongoDB geçişinden sonra yaşadığımız en büyük sorun IOPS limitlerinin sorgu performanslarına çok ciddi etki ettiğini farkedememek oldu. MongoDB yapısı gereği disk üzerinden çok fazla okuma işlemi yaptığından mümkün olan en hızlı okuma yazma desteği sunan disk yanında mümkün olan en yüksek IOPS limiti kullanılması performansınızı ciddi etkileyecektir.

Doğru Index Kullanımı

Tüm veritabanlarında olduğu gibi MongoDB’de de indexler sorgu performanlarında çok önemli yer tutmaktadır. O yüzden döküman dizaynı ile birlikte kullanılacak index’ler ve index yöntemlerinin de dizayn aşamasında belirlenmesi gerekmektedir.

MongoDB’de birden fazla index türü bulunmaktadır. Data yapısına göre bunlardan en uygunu seçilmelidir.

MongoDB’de kullanılan index sayısı arttıkça sorgu performanları da buna oranla düşecektir. Bu nedenle en çok ihtiyaç duyulan field’lara index atılması önerilmektedir.

MongoDB yük altında da index eklemeye izin vermektedir. Bu datanın büyüklüğüne göre değişen sürelerde tamamlanabilmektedir. O yüzden trafik ve data büyüklüğü dikkate alınarak sonradan da index eklenebilmektedir. Varolan bir indexi silme işlemi çok kısa sürmektedir.

Biz proda çıktıkdan sonra sorgularımızı analiz ederek daha önce ihtiyaç olabileceğini düşündüğümüz için eklediğimiz, ancak olmasa da olur dediğimiz indexleri silerek %30'a yakın performans artışı sağladık. O yüzden MongoDB’de mümkün olduğu kadar az ve düzgün index kullanmak data ve trafik büyüdükçe çok büyük önem kazanmaktadır..

Sonuç

Biz MongoDB kullanmakla doğru karar verdiğimizi düşünüyoruz. Artık veritabanı tarafında daha kolay hareket edebiliyor, projenin büyüme potansiyeline daha uygun olduğunu düşünüyoruz. Kullandıkça da daha çok sevmeye devam ediyoruz. Tabi her veritabanı her projeye uygun olmayabilir. O yüzden projenin yapısına göre doğru veritabanı seçmeye dikkat edilmelidir.

Bu yazıdaki konuların daha fazlasını Teknasyon Tech etkinliğinde anlattım. Videoyu izlemek isterseniz:

Yine etkinlikte destek aldığım sunuma göz atmak isterseniz:

https://www.canva.com/design/DAEkijqrmfk/VGpr_WeKXTK4pFUvJmTokQ/view?utm_content=DAEkijqrmfk&utm_campaign=designshare&utm_medium=link&utm_source=publishpresent#3

Buraya kadar sabırla okuduğunuz için teşekkür ederim. Soru ve farklı durumlar için bana aşağıdaki linklerden ulaşabilirsiniz.

Linkedin: https://www.linkedin.com/in/beytullah/
Twitter: https://twitter.com/beytullah

--

--

FinTech, Startup, Payment Gateway, Payment Orchestration, Subscription Management