Kategori: Bilgi Bankası

  • Son ürünü iki kişinin aynı anda satın alması nasıl engellenir?

    Son ürünü iki kişinin aynı anda satın alması nasıl engellenir?

    Bir e-ticaret sitesi geliştirdiğinizi düşünelim, hangi dilde olduğu fark etmez, güncel teknolojiler kullandığınızı varsayalım.

    Trafik artmaya başladı ve ürün satışları da doğal olarak artıyor, ve zaman zaman özellikle düşük stoklu ürünlerde olmayan stokların satışını fark ettiniz.

    Stok’da son ürün kaldığında birden fazla kişinin bu ürünü satın aldığını fark ettiniz.

    Bunun literatürdeki adı race condition ve overselling şeklinde.

    Bu yazıda bu tarz bir durumda neler yapılabilir bundan bahsedeceğim, özellikle veritabanı seviyesine odaklanacağız. Bu operasyonları güvenli şekilde gerçekleştirmemiz için aşağıdaki veritabanlarından birini kullandığınızı varsayıyorum.

    Önerilen veritabanları

    • MSSQL
    • MYSQL
    • POSTGRESQL

    Bu veritabanlarının hepsi bu yazıda işleyeceğimiz özellikleri destekleyen SQL veritabanı yazılımlarıdır.

    Tüm yöntemlerde transaction açmanız ve başarılı olursa commit etmeniz gerektiğini hatırlatmak isterim, her maddede bunu tekrar etmemek için baştan söylüyorum.

    Hemen yöntemlere geçelim.

    Database Transaction + Lock

    Bu yöntem, çözümlerimiz arasında en çok kullanılan ve klasik bir yöntem diyebiliriz.

    Bu yöntemin temel mantığı veritabanında işlem yapmadan önce bu işlemi yaptığımız satırlarda başkası işlem yapmasın demek oluyor.

    Örnek SQL

    SQL
    SELECT * FROM products WHERE id = 1 FOR UPDATE;

    İşlemin başında satır kilitlenir.

    Diğer kullanıcılar işlemin bitmesini beklerler.

    İlk işlem bitince sıradaki işlem ile devam edilir.

    Yoğun trafikte yavaşlatır.

    Deadlock riski yaratır.

    Kullanım örneği ( Temsili kod SQL)

    SQL
    BEGIN TRANSACTION
    
    SELECT stock FROM products WHERE id=1 FOR UPDATE
    
    IF stock > 0:
        UPDATE products SET stock = stock - 1
        COMMIT
    ELSE:
        ROLLBACK

    Optimistic Lock

    Bu yöntem benim de en sevdiğim ve bir çok noktada bolca kullandığım bir yöntem, Optimistic Lock yöntemi yani versiyon sütunu eklemek.

    Ben sadece stok değil şifre değiştirme gibi durumlarda da bu sistemi kullanıyorum, veri tutarlılığını özellikle JWT üzerinden kontrol etmek için en garanti yöntem ama tabi bu yazının konusu JWT değil.

    Burada kullanacağımız mantık çok basit, bir version ve updated_at sütunu ile verinin sorguladığımız andaki ve güncellediğimiz andaki tutarlılığını kontrol ediyoruz.

    SQL
    UPDATE products
    SET stock = stock - 1, version = version + 1
    WHERE id = 1 AND version = 5;

    Dediğim gibi bir çok noktada kullanılabilecek bir yöntem. Farklı senaryolarda da ilaç gibi geliyor.

    Tek sıkıntısı çakışma durumunda işlemi iptal etmekden başka çaremiz yok.

    Atomic Update

    SQL
    UPDATE products
    SET stock = stock - 1
    WHERE id = 1 AND stock > 0;

    Burada da aslında benzer bir mantık, stok sıfır olmadığı sürece bir azaltmasını rica ediyoruz veritabanından. Bu çok da basit bir yöntem ben çok tercih etmiyorum ama tabi siz bilirsiniz.

    Yazımızın genelinden de anlayabileceğiniz gibi amacımız veritabanımızın sağladığı özelliklere öncelik vermek.

    Şimdi sırada ise farklı bir yöntem var, ek bir yazılımdan destek alacağız.

    Queue / Message Queue (RabbitMQ vb.)

    Bankacılık uygulamalarına kadar yüksek trafikli tüm işlemlerde bu yöntem kullanılır, Siparişler sıraya alınır ve arkaplanda kullanıcıyı da bekletmeden işlenir. Sonrasında kullanıcıya gerekli bildirimler yapılır.

    • Sipariş bekleme listesine alınır
    • Kulalnıcıya siparişinin onay beklediği ekran gösterilir
    • Arkaplanda sipariş işlenir (QUEUE)
    • Kullanici tarayici veya mail yoluyla bilgilendirilir/yönlendirilir

    Rezervasyon Sistemi

    Bir başka yöntem de kullanıcılar için sepete eklendiğinde rezerve stoklar atamaktır, bunun örneği bu yazımız için çok uzun olacak o yüzden çok ayrıntıya girmiyorum.

    • Kullanıcı sepete ekler
    • Sepete ekleme ile birlikte bir stok tutucu oluşturulur ve ürün bu kullancıya rezerve edilir bir süreliğine.
    • kullanıcı satın alma sırasında yine stok kontrolü ile birlikte satın alır
    • kullanıcı belli bir süre satın almazsa stok serbest bırakılır.

    Sonuç

    Benim önerim kesinlikle QUEUE sistemleri de içinde barındıran hibrit bir sistem.

    Örneğin Rabbit MQ + Database Transaction + Lock

    • Önce sipariş queue ye atılır.
    • Kullanıcı bekleme ekranına gönderilir.
    • Optimistik Lock + Database Transaction Lock ile birlikte sipariş işlenir.
    • Kullanıcı bilgilendirir.

  • RabbitMQ Nedir? Hangi Problemi Çözüyor?

    RabbitMQ Nedir? Hangi Problemi Çözüyor?

    RabbitMQ nedir sorusunu sormadan önce Event-driven architecture nedir sorusu ile yazıma başlamak istiyorum. RabbitMQ bu sistemde kullandığımız bir araçtır çünkü.

    Event Driven Architecture Nedir?

    EDA bir yazılım dizayn pattern’i dir ve yazılımımızın event yani olaylara vereceği reaction yani tepkileri vurgulayan ve bu şekilde ölçeklenebilir sistemler dizayn etmemizi sağlar.

    Bu yöntem çok popüler bir yöntemdir ve yazılımınızı alt bölümlere ayırmanızı birbirine bağlı olmadan bu bölümlerin çalışmasını sağlar.

    Projemiz büyüdüğünde bu sistemi geleneksel yazılım tasarımlarından daha iyi yönetilebilir projeler oluşturmamızı sağlar.

    Kısaca yazılımımızdaki olaylara verilecek tepkiler üzerinden sistemimizi tasarlamamıza verilen isimdir.

    Yazılımımızın başka başka parçaları farklı cihazlarda bile çalışabilir ve birbirlerinden haberdar olmalarına çok da gerek kalmaz, örneğin tek bilmeleri gereken yeni bir kullanıcının kaydoluğudur ve burumda gereken işlemi birbirlerinden haberleri olmadan gerçekleştirirler.

    Biz yazılımımızda üye kaydolma event’i gerçekleştiğinde trigger’lanacak sistemleri kaydederiz ve onlar da ayrı ayrı çalışır!

    Bu sistemlerden biri fail olursa diğeri zarar görmeden hayatına devam eder!

    Aynı kaynakları paylaşmadıkları için de birbirlerini bloklamazlar!

    Kullanıcı bir butona bastı ve bu butonun yapması gereken diyelim ki sipariş oluşturmak, fatura oluşturmak, stok düşmek ve aynı zamanda bunları gerekli yerlere mail göndermek diyelim. Bu durumda normal geleneksel uygulamalarda bunları sırayla yapar ve ziyaretçilerimizi bekletiriz. Ama event-driven architecture’da “order.created” event’i order bilgisi ile birlikte bu işlemleri yapan ayrı ayrı sistemlere mesaj gönderir, yeni sipariş oluştu her biriniz üzerinize düşenleri gerçekleştirin der ve kullanıcıya da siparişşin oluşturulduğu cevabını döner, kullanıcı bilgisayarını kapatır arkaplanda sistem faturayı, stok düşme işlemini, email ile bilgilendirme işlemlerini yapar ve ziyaretçinin bundan haberi bile olmaz!

    Evet bu sistemler birbiri ile nasıl haberleşecek sorusu aklına gelmiştir diye düşünüyorum, hemen burada çevreye neredeyse piyasa standartı olmuş bir sistem giriyor. RabbitMQ!

    RabbitMQ Nedir?

    RabbitMQ açık kaynak kodlu bir message broker yazılımıdır, bu event-driven architecture içerisinde sistemlerin birbiri ile iletişim kurmasını sağlar, bir event gerçekleştiğinde bu event’den haberdar olması gereken, o event’e abone olmuş consumer yani tüketicileri haberdar eder.

    RabbitMQ mesajları öncelikle “exchange” dediğimiz depolara gönderir ve ondan sonra da route key lerine göre abonelerine ulaştırır!

    RabbitMQ “First-in, First-out algoritmasına göre çalışır, ilk giren event ilk işlenir,

    RabbitMQ özellikle micro-servis mimarisinde oldukça popülerdir!