2PC (Two Phase Commit) Pattern Nedir?

Sefik Can Kanber
4 min readFeb 9, 2021

Merhaba arkadaşlar,

Bu makalemde günümüzde son derece popüler olan microservice mimarisindeki distributed transaction sorunlarına çözüm getiren 2PC (Two Phase Commit) Pattern’inden bahsedeceğim.

Distributed Transaction Nedir?

Microservice mimarisinde, monolithic sistemlerden ayrı olarak servisler ve veritabanları birbirinden ayrıştırılmıştır. Yani, transaction yönetimi monolithic uygulamalardakinden farklı olarak servis ve veritabanları dağıtıldığı için basit şekilde transaction açıp yönetmek pek mümkün değildir.

Transaction yönetimini monolith bir uygulamada şemaya dökersek;

Örneğimizde;

Bir kullanıcı monolithic bir sistemde bir Put Order işlemini gerçekleştirirse; sistem birden çok veritabanı tablosu üzerinde çalışan tek transaction oluşturur ve işlem başarılı ise commit ile akış tamamlanır. Herhangi bir adım başarısız olursa; işlem geri alınabilir (rollback). Bu işlem ile ACID prensiplerini veritabanı sisteminizde garanti altına alırsınız.

Veritabanı türlerine göre transaction isolation seviyeleri için bknz.

ACID Prensipleri

ACID, transactional işlemlerin veritabanına nasıl uygulanacağını yöneten 4 prensip sunar.

Transaction: Veritabanı üzerindeki her işleme denir. Kullanıcı ekleme, stok güncelleme vb.

Atomicity: İşlemler sırasında bir veya daha fazla tablodaki veriler güncelleniyorsa bu işlemlerin ya hepsi birden başarılı olacaktır ya da hepsi başarısız olacaktır. Kısaca, veri bütünlüğüdür.

Consistency: Transaction tamamlanana kadar işlemden etkilenen verilerin değerlerinin transaction işlemine başlamadan önceki geçerli değeri vermesidir. Kısaca, veri bütünlüğü diyebiliriz.

Isolation: Transaction’ların bağımsız şekilde işletilmesidir.

Durability: Transaction işlemi/işlemleri sırasında bir hata olması durumunda sistemin kendisini bir önceki geçerli veri durumuna döndürebilme kabiliyetidir.

Microservice Mimarisi’nde Transaction Yönetimi

Madalyonun diğer tarafı olan microservice mimarisinde transaction yönetimine baktığımızda; microservice mimarisi distributed (dağıtık) yapıya sahip olduğundan ACID prensiplerini yönetmek monolithic yapılara göre daha zordur.

Yukarıdaki örneğimizi microservice mimarisine göre düzenlersek; elimizde veritabanları farklı olan 2 adet microservice olacaktır. Bunlar, Order ve Customer Service’tir. Örneğimizi şemaya dökersek;

Örneğimizde, kullanıcı Put Order işlemini gerçekleştirdiğinde her microservice işlemi birbirinden bağımsız olarak yürütülmek için çağrılacaktır.

Peki bu yapıda ana sorun nedir ?

Akışa baktığınızda ACID’in bütünlük (Atomicity) ilkesini es geçtiğimizi görebilirsiniz. Peki burada veri bütünlüğünü nasıl sağlayabiliriz?

Örneğimizdeki şemadan yola çıkarsak; UpdateCustomerFund başarılı şekilde işlenmişken, Create Order işleminden dönen response’u beklemelidir. Bu durumda olası hata senaryolarını nasıl yönetebiliriz? Basit şekilde bir geri alma işlemi mi gerçekleştirmeliyiz yoksa bir pattern ile mi yönetmeliyiz? (Size kalmış 😀)

Microservice mimarisinde Transaction İşlemlerinde ACID prensiplerini yönetebilmek için 2 çözüm vardır:

  • 2PC Pattern
  • Saga Pattern

2PC (Two Phase Commit) Pattern

İsminden de anlaşılacağı üzere 2 aşamadan oluşur:

  • Hazırlık aşamasında ana servisimiz (Süreci başlatıp yöneten servise coordinator denir.) kendisine subscribe (abone) olmuş tüm servislere işlemi gerçekleştirmeye hazır olup olmadıklarıyla ilgili commit gönderir. Eğer servislere erişilemez ya da hata ile karşılaşılırsa akış iptal edilir.
  • Eğer microservice’ler hazır ise ana servis (coordinator) işlem için gerekli aksiyonu gerçekleştirir ve son onay için beklemeye geçer.
2PC Örnek Transaction Yönetimi

Yukarıdaki örneğimizi 2PC ile şemaya dökersek;

Kullanıcı Put Order isteğini gönderdiğinde; Coordinator global bir transaction yaratacaktır. Daha sonra, Customer Microservice’ine hazır ol komutunu gönderecektir. Burada, Customer Microservice’den gelecek başarılı response’una göre diğer step ile aynı sonucu bekleyeceği için Order Microservice’inden başarılı yanıtını bekleyecektir. Akışta, Coordinator işlem yapacağı tüm servislerden hazır yanıtını aldıktan sonra değişiklikleri uygulayacak ve kitlenen işlemleri unlocked durumuna getirecektir.

Herhangi bir servisten hata alınması durumunda Coordinator işlemi iptal edecek ve transaction işlemi rollback edilecektir. Aşağıda, bu senaryonun şemaya dökülmüş halini görebilirsiniz;

2PC Avantajları

  • Data tutarlılığını garanti eder.
  • Merkezi yönetim sağlar ve anlaması kolaydır.

2PC Dezavantajları

  • İlgili akışta subscribe (abone) olan tüm servisleri bekleyeceğimiz için performans sorunu yaşayabiliriz.
  • İlgili akış dışındaki diğer transaction’ların tüm süreçleri tamamlanana kadar bekletilmesi de sistemde genel performans sorunlarına yol açabilir.
  • Ana servisimiz beklenmedik şekilde hataya düşerse diğer tüm servisler belirsiz (Limbo-state) durumuna geçer.

--

--