﻿
{"id":26623,"date":"2023-10-10T19:49:58","date_gmt":"2023-10-10T19:49:58","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=26623"},"modified":"2023-10-10T19:49:58","modified_gmt":"2023-10-10T19:49:58","slug":"microservice-mimarisinde-two-phase-commit2pc-pattern-ile-transaction-yonetimi-nedir-nasil-uygulanir-sagadan-farki-nedir","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/microservice-mimarisinde-two-phase-commit2pc-pattern-ile-transaction-yonetimi-nedir-nasil-uygulanir-sagadan-farki-nedir\/","title":{"rendered":"Microservice Mimarisinde Two-Phase Commit(2PC) Pattern \u0130le Transaction Y\u00f6netimi &#8211; Nedir? Nas\u0131l Uygulan\u0131r? Saga&#8217;dan Fark\u0131 Nedir?"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Bu i\u00e7eri\u011fimizde microservice yakla\u015f\u0131m\u0131n\u0131 uygulad\u0131\u011f\u0131m\u0131z mimarilerde veri tutarl\u0131l\u0131\u011f\u0131n\u0131 sa\u011flaman\u0131n davran\u0131\u015flar\u0131ndan biri olan <em>Two-Phase Commit(2PC)<\/em> modelini ele alacak, nas\u0131l ve hangi durumlarda kullan\u0131ld\u0131\u011f\u0131n\u0131 de\u011ferlendiriyor olaca\u011f\u0131z. Ayr\u0131ca neden Saga pattern&#8217;\u0131na nazaran daha az tercih edilmesi gerekti\u011fine dair gerekli isti\u015farede bulunacak ve i\u00e7eri\u011fimizin en \u00f6nemli b\u00f6l\u00fcm\u00fc olarak pratiksel olarak ilgili konuyu bir senaryo \u00fczerinden tecr\u00fcbe ediyor olaca\u011f\u0131z. O halde buyurun ba\u015flayal\u0131m&#8230;<\/p>\n<p>\u00d6ncelikle microservice mimarisinde transaction y\u00f6netimi i\u00e7in uygulad\u0131\u011f\u0131m\u0131z Saga pattern&#8217;\u0131na dair \u00f6nceden klavyeye ald\u0131\u011f\u0131m\u0131z makaleleri \u015f\u00f6yle okunma s\u0131ras\u0131na g\u00f6re a\u015fa\u011f\u0131da listeleyelim;<\/p>\n<ul style=\"font-size:12px;\">\n<li><a href=\"https:\/\/www.gencayyildiz.com\/blog\/microservice-mimarilerde-saga-pattern-ile-transaction-yonetimi\/\" rel=\"noopener\" target=\"_blank\">Microservice Mimarilerde Saga Pattern \u0130le Transaction Y\u00f6netimi<\/a><\/li>\n<li><a href=\"https:\/\/www.gencayyildiz.com\/blog\/microservice-saga-commands-orchestration-implemantasyonu-ile-transaction-yonetimi\/\" rel=\"noopener\" target=\"_blank\">Microservice \u2013 Saga \u2013 Commands\/Orchestration Implemantasyonu \u0130le Transaction Y\u00f6netimi<\/a><\/li>\n<li><a href=\"https:\/\/www.gencayyildiz.com\/blog\/microservice-saga-commands-orchestration-implemantasyonu-ile-transaction-yonetimi\/\" rel=\"noopener\" target=\"_blank\">Microservice \u2013 Saga \u2013 Commands\/Orchestration Implemantasyonu \u0130le Transaction Y\u00f6netimi<\/a><\/li>\n<\/ul>\n<h3>Two-Phase Commit(2PC) Modeli Nedir?<\/h3>\n<p>Two-Phase Commit(2PC) modeli, t\u0131pk\u0131 Saga gibi distributed sistemlerdeki transaction y\u00f6netimini sa\u011flayabilmek ya da verisel tutars\u0131zl\u0131\u011fa kar\u015f\u0131n \u00e7\u00f6z\u00fcm getirebilmek i\u00e7in kullan\u0131lan bir <u>senkronizasyon protokol\u00fcd\u00fcr<\/u>. Bu protokol sayesinde da\u011f\u0131t\u0131k sistemde rol oynayacak olan t\u00fcm d\u00fc\u011f\u00fcmlerin(node) yani servislerin, bir i\u015flemi atomik olarak ger\u00e7ekle\u015ftirmesini veyahut o i\u015flemin komple iptal edilmesini sa\u011flamak i\u00e7in kullan\u0131lan bir b\u00fct\u00fcnsel algoritma g\u00f6revi g\u00f6rmektedir.<\/p>\n<blockquote><p><em>Two-Phase Commit pattern&#8217;\u0131nda, davran\u0131\u015fsal olarak bir rol\u00fc ifade eden, s\u00fcrecin bir par\u00e7as\u0131 olarak kat\u0131l\u0131m g\u00f6steren ve protokol\u00fcn gerektirdi\u011fi g\u00f6revleri yerine getiren kat\u0131l\u0131mc\u0131lara(yani servislere) <strong><em>node<\/em><\/strong> denmektedir.<\/em><\/p><\/blockquote>\n<p>Atomik olarak diyoruz \u00e7\u00fcnk\u00fc Two-Phase Commit modeli ile ya i\u015flem tamamen ba\u015far\u0131l\u0131 olacakt\u0131r ya da hi\u00e7bir \u015fey yap\u0131lmam\u0131\u015f gibi esas\u0131nda geri al\u0131nacakt\u0131r. B\u00f6ylece bu protokol sayesinde, distributed yap\u0131lanman\u0131n gere\u011fi olarak birden fazla serviste s\u00f6z konusu olan veritaban\u0131 i\u015flemleri sanki tek bir b\u00fct\u00fcnm\u00fc\u015f gibi ba\u015far\u0131l\u0131 bir \u015fekilde tamamlanm\u0131\u015f olacakt\u0131r.<\/p>\n<h3>2PC Modelinin Temel \u0130lkeleri<\/h3>\n<p>Two-Phase Commit pattern&#8217;\u0131n\u0131n temel ilkesi a\u015fa\u011f\u0131daki gibi iki a\u015famaya dayanmaktad\u0131r.<\/p>\n<ul>\n<li><strong><em>Phase 1 &#8211; Prepare (Haz\u0131rl\u0131k A\u015famas\u0131)<\/em><\/strong><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-300x196.png\" alt=\"Microservice Mimarisinde Two-Phase Commit(2PC) Pattern \u0130le Transaction Y\u00f6netimi - Nedir? Nas\u0131l Uygulan\u0131r? Saga&#039;dan Fark\u0131 Nedir?\" width=\"300\" height=\"196\" class=\"alignleft size-medium wp-image-26635\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-300x196.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir.png 548w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>Yap\u0131lmas\u0131 gereken i\u015flem do\u011frultusunda, i\u015f\/sorumluluk y\u00fcr\u00fctecek olan her bir microservice&#8217;in \u00f6ncelikle i\u015flemi yapmak i\u00e7in haz\u0131r oldu\u011funu belirtece\u011fi a\u015famad\u0131r.<\/p>\n<p>Bu a\u015famada, yandaki g\u00f6rselde de g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere bu koordinat\u00f6r sorumlulu\u011funu \u00fcstlenecek olan y\u00f6netici bir servis \u00fczerinden koordinasyon sa\u011flanacakt\u0131r.<\/p>\n<p>Koordinat\u00f6r; servislere haz\u0131r olup olmad\u0131klar\u0131na dair bir talepte bulunacak, servisler de bu talep neticesinde durumlar\u0131n\u0131 koordinat\u00f6re bildirecektirler. Bu durumda t\u00fcm servisler haz\u0131rsa e\u011fer ikinci a\u015famaya ge\u00e7ilecek, yok e\u011fer herhangi bir servis haz\u0131r olmad\u0131\u011f\u0131n\u0131 s\u00f6yler ya da talebe kar\u015f\u0131l\u0131k vermezse 2PC&#8217;nin atomik mant\u0131\u011f\u0131 gere\u011fi t\u00fcm i\u015flemler iptal edilecek ve ba\u015far\u0131s\u0131z olarak de\u011ferlendirilecektir.<\/p>\n<p>Anlayaca\u011f\u0131n\u0131z bu a\u015famada sistemin b\u00fct\u00fcnsel yani atomik hareket edebilmesi i\u00e7in bir haz\u0131rl\u0131k s\u00fcreci s\u00f6z konusudur diyebiliriz. Normalde bu a\u015fama olmaks\u0131z\u0131n direkt ikinci a\u015famay\u0131 uygulamaya kalkarsan\u0131z sistemin b\u00fct\u00fcnselli\u011fi ve 2PC modelinin uygulanabilirli\u011fi zaafa u\u011frayacakt\u0131r ve eri\u015filemeyen ya da hata veren servislere, operasyonun yap\u0131lmas\u0131 talimat\u0131n\u0131n verilerek olas\u0131 problemlere kap\u0131 aralanm\u0131\u015f olacakt\u0131r. Bu sebeple bu a\u015fama olduk\u00e7a \u00f6nem arz etmektedir.<\/p>\n<p>Haliyle bu a\u015famay\u0131 ad\u0131msal olarak a\u015fa\u011f\u0131daki gibi \u00f6zetleyebiliriz;<\/p>\n<ol>\n<li>Koordinat\u00f6r kullan\u0131c\u0131dan talebi al\u0131r.<\/li>\n<li>Koordinat\u00f6r ald\u0131\u011f\u0131 talep do\u011frultusunda, yapaca\u011f\u0131 i\u015flemi ilgilendirecek olan t\u00fcm node&#8217;lara haz\u0131r olup olmad\u0131klar\u0131na dair mesaj g\u00f6nderir ve t\u00fcm kat\u0131l\u0131mc\u0131lardan d\u00f6n\u00fc\u015f bekler.<\/li>\n<li>\n<ol>\n<li style=\"color:green;\">Kat\u0131l\u0131mc\u0131lar\u0131n hepsinden &#8216;Ok&#8217;, &#8216;Yes&#8217;, &#8216;he la haz\u0131r\u0131z&#8217; vs. gibisinden mesajlar\u0131n gelmesi neticesinde koordinat\u00f6r ikinci a\u015famay\u0131 ba\u015flat\u0131r.<\/li>\n<li style=\"color:red;\">Kat\u0131l\u0131mc\u0131lar\u0131n en az birinden &#8216;Abort&#8217;, &#8216;No&#8217;, &#8216;ben haz\u0131r de\u011filim aga&#8217; vs. \u015feklinde mesaj al\u0131nd\u0131\u011f\u0131 ya da hi\u00e7 cevap gelmedi\u011fi taktirde ikinci a\u015famaya ge\u00e7ilmeksizin kullan\u0131c\u0131dan gelen talep iptal edilir.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<li><strong><em>Phase 2 &#8211; Commit (Taahh\u00fct A\u015famas\u0131)<\/em><\/strong><br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-1.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-1-300x199.png\" alt=\"Microservice Mimarisinde Two-Phase Commit(2PC) Pattern \u0130le Transaction Y\u00f6netimi - Nedir Nas\u0131l Uygulan\u0131r Sagadan Fark\u0131 Nedir\" width=\"300\" height=\"199\" class=\"alignleft size-medium wp-image-26637\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-1-300x199.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-1.png 536w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>Bu a\u015fama ise koordinat\u00f6r\u00fcn t\u00fcm microservice&#8217;lerin haz\u0131r oldu\u011funu do\u011frulamas\u0131 neticesinde hi\u00e7bir sorunun olmad\u0131\u011f\u0131na kanaat getirmesiyle, t\u00fcm servislere, t\u00fcm i\u015flemlerin kesin olarak ger\u00e7ekle\u015ftirilmesi i\u00e7in <code>commit<\/code> talimat\u0131n\u0131 verdi\u011fi a\u015famad\u0131r.<\/p>\n<p>Yani anla\u015f\u0131lan bu a\u015fama art\u0131k servislerin operatif harekat\u0131 fiili olarak y\u00fcr\u00fctt\u00fc\u011f\u00fc a\u015famad\u0131r. Dolay\u0131s\u0131yla bu a\u015faman\u0131n da ad\u0131msal olarak \u00f6zeti a\u015fa\u011f\u0131daki gibi olacakt\u0131r;<\/p>\n<ol>\n<li>Koordinat\u00f6r t\u00fcm kat\u0131l\u0131mc\u0131lar\u0131n haz\u0131r oldu\u011funa kanaat getirdikten sonra t\u00fcm servislerin sorumluluklar\u0131 gere\u011fi operasyonlar\u0131n\u0131 ba\u015flatmas\u0131 i\u00e7in <code>commit<\/code> mesaj\u0131n\u0131 g\u00f6nderir.<\/li>\n<li>Koordinat\u00f6r, kat\u0131l\u0131mc\u0131lar\u0131n i\u015flemlerini tamamlamas\u0131 \u00fczerine onlardan &#8216;Ack&#8217;, &#8216;Ok&#8217;, &#8216;ben tamam\u0131m m\u00fcd\u00fcr&#8217; vs. \u015feklinde yan\u0131t bekler.<\/li>\n<li>\n<ol>\n<li style=\"color:green;\">\nKat\u0131l\u0131mc\u0131lar\u0131n hepsinden beklenen yan\u0131t al\u0131nd\u0131\u011f\u0131 taktirde kullan\u0131c\u0131 talebi ba\u015far\u0131yla tamamlanm\u0131\u015f olur.\n<\/li>\n<li style=\"color:red;\">Kat\u0131l\u0131mc\u0131lardan en az birinden beklenen cevab\u0131 alamazsa ya da hi\u00e7 cevap gelmezse i\u015flem iptal edilecek ve t\u00fcm servislerden yapt\u0131klar\u0131n\u0131n geri al\u0131nmas\u0131 i\u00e7in <code>abort<\/code> mesaj\u0131n\u0131 g\u00f6nderir.<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<p>Bu ilkeler do\u011frultusunda 2PC davran\u0131\u015f\u0131n\u0131 atomik olarak sa\u011flam\u0131\u015f olacakt\u0131r.<\/p>\n<h3>2PC&#8217;nin Terminolojik Akt\u00f6rleri<\/h3>\n<p>Yukar\u0131daki sat\u0131rlarda 2PC modelinin tasar\u0131m s\u00fcrecinde &#8216;Koordinat\u00f6r&#8217;, &#8216;Kat\u0131l\u0131mc\u0131&#8217; vs. gibi terminolojik akt\u00f6rlerin oldu\u011funu g\u00f6r\u00fcyoruz. Ee haliyle i\u00e7eri\u011fi rahat\u00e7a takip edebilmek ve ortak bir dil ortaya koyabilmek i\u00e7in bu protokol s\u00fcrecinde kullan\u0131lan akt\u00f6rleri tam olarak tan\u0131mlamakta fayda vard\u0131r;<\/p>\n<ul>\n<li><em><strong>Koordinat\u00f6r (Coordinator)<\/strong><\/em><br \/>\n2PC protokol\u00fcn\u00fcn merkezi y\u00f6netici konumunda olan servistir. Koordinat\u00f6r, i\u015flemin ba\u015flat\u0131lmas\u0131ndan sonuna kadar t\u00fcm ad\u0131mlar\u0131 kontrol etmekte, s\u00fcre\u00e7te her microservice&#8217;in haz\u0131rl\u0131k a\u015famas\u0131ndaki onay\u0131n\u0131 beklemekte ve ard\u0131ndan i\u015flemi tamamlamak yahut geri almak i\u00e7in <code>commit<\/code> veya <code>abort<\/code> mesajlar\u0131n\u0131 g\u00f6ndererek kat\u0131l\u0131mc\u0131larla gerekli ileti\u015fimi kurmaktad\u0131r.\n<\/li>\n<li><em><strong>Kat\u0131l\u0131mc\u0131lar (Participants)<\/strong><\/em><br \/>\n2PC protokol\u00fc s\u00fcrecinde, kullan\u0131c\u0131dan gelen talep do\u011frultusunda i\u015flem\/operasyon y\u00fcr\u00fctecek olan microservice&#8217;lerin ta kendileridir. Her bir kat\u0131l\u0131mc\u0131 yap\u0131lacak i\u015flem i\u00e7in haz\u0131r oldu\u011funa dair koordinat\u00f6re bilgi vermekte ve koordinat\u00f6rden gelecek olan <code>commit<\/code> ve <code>abort<\/code> talimatlar\u0131na g\u00f6re i\u015flevlerini y\u00fcr\u00fctmektedir.\n<\/li>\n<li><em><strong>Veritabanlar\u0131<\/strong><\/em><br \/>\nHer bir kat\u0131l\u0131mc\u0131, genellikle kendine \u00f6zg\u00fc bir veritaban\u0131na eri\u015fim sa\u011flayarak i\u015flem ger\u00e7ekle\u015ftirmektedir.\n<\/li>\n<li><em><strong>G\u00f6zlemciler (Observers)<\/strong><\/em><br \/>\nG\u00f6zlemciler ise 2PC protokol s\u00fcrecini izleyen ancak do\u011frudan i\u015fleme kat\u0131lmayan akt\u00f6rlerdir.\n<\/li>\n<\/ul>\n<h3>2PC Protokol\u00fc Ne Ama\u00e7la Kullan\u0131lmal\u0131d\u0131r?<\/h3>\n<p>Two-Phase Commit protokol\u00fc, yukar\u0131daki sat\u0131rlardan anla\u015f\u0131laca\u011f\u0131 \u00fczere da\u011f\u0131t\u0131k sistemlerdeki veritaban\u0131 i\u015flemlerini ya k\u00fcm\u00fclatif olarak ba\u015far\u0131l\u0131 k\u0131lacak ya da hi\u00e7biri ger\u00e7ekle\u015fmeyecek \u015fekilde yani atomik bir yakla\u015f\u0131mla koordine etmek i\u00e7in kullan\u0131lmaktad\u0131r. Haliyle buradaki en b\u00fcy\u00fck gayenin, microservice&#8217;lerin aralar\u0131ndaki verisel tutarl\u0131l\u0131\u011f\u0131n b\u00fct\u00fcnsel olarak sa\u011flanmas\u0131 veyahut korunmas\u0131 oldu\u011funu s\u00f6yleyebiliriz. Ayr\u0131ca microservice mimarisinin s\u00f6z konusu oldu\u011fu senaryolarda, servisler aras\u0131 i\u015flem koordinasyonunun 2PC ile merkezi bir nokta \u00fczerinden ger\u00e7ekle\u015ftirilmesi ve b\u00f6ylece s\u00fcre\u00e7 y\u00f6netiminin de kolayla\u015ft\u0131r\u0131lmas\u0131 ama\u00e7lanmaktad\u0131r diyebiliriz.<\/p>\n<h3>Ne Zaman Saga &#038; Ne Zaman 2PC Kullan\u0131lmal\u0131d\u0131r?<\/h3>\n<p>E\u011fer ki, distributed transaction&#8217;\u0131n t\u00fcm kat\u0131l\u0131mc\u0131lar a\u00e7\u0131s\u0131ndan b\u00fct\u00fcnsel olarak commit edilmesi ve gerekti\u011fi taktirde de rollback edilmesi durumlar\u0131 s\u00f6z konusuysa tabi ki de buradaki ihtiyac\u0131n g\u00fcvenli\u011fini sa\u011flayabilmek i\u00e7in 2PC protokol\u00fcnden istifade edilebilir. Ancak i\u00e7eri\u011fimizin devam\u0131ndaki sat\u0131rlarda da g\u00f6rece\u011fimiz \u00fczere 2PC, kullan\u0131c\u0131dan gelen talebe kar\u015f\u0131n atomik bir tutarl\u0131l\u0131k sa\u011flayabilmek i\u00e7in servislerin k\u00fcm\u00fclatif hareket edebilmesi amac\u0131yla topyek\u00fcn bir kilitlenmeye mahal verecek ve bu durum da y\u00fcksek oranda performans sorunlar\u0131na sebebiyet verecektir. Bu nedenle az say\u0131daki kat\u0131l\u0131mc\u0131n\u0131n oldu\u011fu ve bu protokol\u00fcn yarataca\u011f\u0131 kilitleme neticesindeki gecikmelerin ve bu gecikmelerin de yarataca\u011f\u0131 \u00f6l\u00e7eklenebilirlik s\u0131n\u0131rlar\u0131n\u0131n y\u00f6netilebilece\u011fi senaryolarda 2PC modelinin tercih edilmesi en do\u011frusu olacakt\u0131r.<\/p>\n<p>Saga ise yap\u0131lacak i\u015flemin tek bir 2PC protokol\u00fc taraf\u0131ndan y\u00f6netilemeyecek kadar b\u00fcy\u00fck oldu\u011fu durumlarda tercih edilebilir. Saga, kullan\u0131c\u0131 taraf\u0131ndan talep edilen i\u015flem her ne ise, bu i\u015flemi her bir microservice taraf\u0131ndan ba\u011f\u0131ms\u0131z olarak y\u00f6netilebilecek ve i\u015flenebilecek k\u00fc\u00e7\u00fck local i\u015flemlere b\u00f6lecektir. B\u00f6ylece her bir service ihtiya\u00e7 do\u011frultusunda daha rahat \u00f6l\u00e7eklendirilebilecek ve herhangi bir gecikme vs. olmaks\u0131z\u0131n, y\u00fcksek hata tolerans\u0131 e\u015fli\u011finde gayet performansl\u0131 bir s\u00fcre\u00e7 sonucu beklenen netice elde edilebilecektir. Ayr\u0131ca \u00f6zellikle 2PC protokol\u00fc ile i\u015flemin geri al\u0131nma durumunun olduk\u00e7a maliyetli olabilece\u011fi karma\u015f\u0131k senaryolarda, Saga pattern&#8217;\u0131 ile daha basit ama etkili \u00e7\u00f6z\u00fcmler getirilebilecektir.<\/p>\n<h3>2PC&#8217;nin Pratiksel \u00d6rneklendirilmesi<\/h3>\n<p>\u015eimdi 2PC protokol\u00fcn\u00fc pratiksel olarak ba\u015ftan sona bir \u00f6rnek senaryo \u00fczerinden tecr\u00fcbe edelim istiyorum. Bunun i\u00e7in bir e-ticaret sisteminin klasik &#8216;Order.API&#8217;, &#8216;Stock.API&#8217; ve &#8216;Payment.API&#8217; servislerinden olu\u015fan sipari\u015f s\u00fcrecini senaryo olarak de\u011ferlendiriyor olaca\u011f\u0131z. O halde vakit kaybetmeksizin ad\u0131m ad\u0131m \u00f6rne\u011fin geli\u015ftirilmesine ba\u015flayal\u0131m;<\/p>\n<ul>\n<li><strong>Ad\u0131m 1<\/strong> <em style=\"font-size:12px;color:green;\">(Participants &#038; Coordinator Servislerinin Olu\u015fturulmas\u0131)<\/em><br \/>\n\u0130lk olarak kat\u0131l\u0131mc\u0131 servislerini ve bu servisler aras\u0131ndaki koordinasyonu sa\u011flayacak olan koordinat\u00f6r servisini olu\u015ftural\u0131m.<\/p>\n<div style=\"text-align:center;\">\n<code><strong><span style=\"color:red;font-size:9px;\">(Participant)<\/span> dotnet new webapi --name Order.API<\/strong><\/code><br \/>\n<code><strong><span style=\"color:red;font-size:9px;\">(Participant)<\/span> dotnet new webapi --name Stock.API<\/strong><\/code><br \/>\n<code><strong><span style=\"color:red;font-size:9px;\">(Participant)<\/span> dotnet new webapi --name Payment.API<\/strong><\/code><br \/>\n<code><strong><span style=\"color:red;font-size:9px;\">(Coordinator)<\/span> dotnet new webapi --name Coordinator<\/strong><\/code>\n<\/div>\n<\/li>\n<li><strong>Ad\u0131m 2<\/strong> <em style=\"font-size:12px;color:green;\">(Coordinator Veritaban\u0131n\u0131n Haz\u0131rlanmas\u0131)<\/em><br \/>\nKoordinat\u00f6r servisinin, kat\u0131l\u0131mc\u0131lar\u0131 y\u00f6netebilmesi i\u00e7in \u00f6ncelikle kat\u0131l\u0131mc\u0131 bilgilerini bar\u0131nd\u0131rd\u0131\u011f\u0131 veritaban\u0131n\u0131 tasarlamam\u0131z gerekmektedir. Bunun i\u00e7in a\u015fa\u011f\u0131daki entity&#8217;lerden istifade edebiliriz:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public record Node(string Name)\r\n    {\r\n        public Guid Id { get; set; }\r\n        public ICollection&lt;NodeState&gt; NodeStates { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public record NodeState(Guid TransactionId)\r\n    {\r\n        public Guid Id { get; set; }\r\n        public ReadyType IsReady { get; set; }\r\n        public TransactionState TransactionState { get; set; }\r\n        public Node Node { get; set; }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki entity&#8217;lere g\u00f6z atarsan\u0131z e\u011fer sistemdeki kat\u0131l\u0131mc\u0131lar &#8216;Node&#8217; entity&#8217;si ile, bu kat\u0131l\u0131mc\u0131lar\u0131n transaction kay\u0131tlar\u0131 ise &#8216;NodeState&#8217; ile bire \u00e7ok bir ili\u015fkiyle modellenmi\u015ftir. Her bir node i\u00e7in ba\u015flat\u0131lan transaction&#8217;\u0131 di\u011ferlerinden ay\u0131rt edebilmek i\u00e7in bir &#8216;TransactionId&#8217; e\u015fli\u011finde, 2PC protokol\u00fcn\u00fcn ilk a\u015famas\u0131ndaki haz\u0131rl\u0131k durumunu ifade eden &#8216;IsReady&#8217; ve nihai olarak da transaction&#8217;\u0131n neticesindeki durumu ifade eden &#8216;TransactionState&#8217; verilerini tuttu\u011fumuza dikkatinizi \u00e7ekerim.<\/p>\n<p>&#8216;NodeState&#8217; entity&#8217;sinde kulland\u0131\u011f\u0131m\u0131z enum de\u011ferlerin i\u00e7erikleri de a\u015fa\u011f\u0131daki gibi olacakt\u0131r:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public enum ReadyType\r\n    {\r\n        Ready,\r\n        Pending,\r\n        Unready\r\n    }\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public enum TransactionState\r\n    {\r\n        Done,\r\n        Pending,\r\n        Abort\r\n    }\r\n<\/pre>\n<\/div>\n<p>Bu tan\u0131mlamadan sonra context nesnesini a\u015fa\u011f\u0131daki gibi olu\u015ftural\u0131m:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TwoPhaseCommitContext : DbContext\r\n    {\r\n        public TwoPhaseCommitContext(DbContextOptions options) : base(options)\r\n        {\r\n        }\r\n\r\n        public DbSet&lt;Node&gt; Nodes { get; set; }\r\n        public DbSet&lt;NodeState&gt; NodeStates { get; set; }\r\n\r\n        protected override void OnModelCreating(ModelBuilder modelBuilder)\r\n        {\r\n            modelBuilder.Entity&lt;Node&gt;().HasData(\r\n                    new Node(&quot;Order.API&quot;) { Id = Guid.NewGuid() },\r\n                    new Node(&quot;Stock.API&quot;) { Id = Guid.NewGuid() },\r\n                    new Node(&quot;Payment.API&quot;) { Id = Guid.NewGuid() }\r\n                );\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Burada da context nesnesinin detay\u0131na g\u00f6z atarsan\u0131z e\u011fer sistemde kullan\u0131lacak t\u00fcm kat\u0131l\u0131mc\u0131lar seed data olarak veritaban\u0131na eklenmektedir. Tabi burada kat\u0131l\u0131mc\u0131lar\u0131 eklemek i\u00e7in farkl\u0131 davran\u0131\u015flar benimseyebilirdik amma velakin konuyu dalland\u0131r\u0131p budakland\u0131rmamak i\u00e7in bu \u015fekilde bir yakla\u015f\u0131m tercih ediyorum.<\/p>\n<p>Olu\u015fturulan bu context nesnesini de kullanabilmek i\u00e7in koordinat\u00f6r servisinin &#8216;Program.cs&#8217; dosyas\u0131nda a\u015fa\u011f\u0131daki gibi yap\u0131land\u0131rmada bulunal\u0131m:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n.\r\n.\r\n.\r\nbuilder.Services.AddDbContext&lt;TwoPhaseCommitContext&gt;(options =&gt; options.UseSqlServer(builder.Configuration.GetConnectionString(&quot;SQLServer&quot;)));\r\n.\r\n.\r\n.\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>Ve son olarak da <code>add-migration mig_1<\/code> talimat\u0131 e\u015fli\u011finde bir migration olu\u015ftural\u0131m ve ard\u0131ndan da <code>update-database<\/code> talimat\u0131 ile olu\u015fturulan bu migration&#8217;\u0131 migrate edelim.\n<\/li>\n<li><strong>Ad\u0131m 3<\/strong> <em style=\"font-size:12px;color:green;\">(Coordinator Servisinde &#8216;TransactionService&#8217;in Olu\u015fturulmas\u0131 ve Temel Participant Ayarlar\u0131n\u0131n Yap\u0131lmas\u0131)<\/em><br \/>\nArt\u0131k koordinat\u00f6r servisinde kat\u0131l\u0131mc\u0131lar\u0131n bilgilerini ve t\u00fcm transaction bilgilerini y\u00f6netebilecek veritaban\u0131 yap\u0131lanmas\u0131 olu\u015fturuldu\u011funa g\u00f6re, koordinat\u00f6r\u00fcn bu sorumlulu\u011funu \u00fcstlenecek olan &#8216;TransactionService&#8217; isimli s\u0131n\u0131f\u0131n\u0131 olu\u015fturabiliriz.<\/p>\n<p>\u00d6nce bu s\u0131n\u0131f\u0131n imzas\u0131 olan aray\u00fcz\u00fc a\u015fa\u011f\u0131daki gibi tasarlayal\u0131m:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public interface ITransactionService\r\n    {\r\n        public Task&lt;Guid&gt; CreateTransaction();\r\n        public Task PrepareServices(Guid transactionId);\r\n        public Task&lt;bool&gt; CheckReadyServices(Guid transactionId);\r\n        public Task&lt;bool&gt; CheckTransactionStateServices(Guid transactionId);\r\n        public Task Commit(Guid transactionId);\r\n        public Task Rollback(Guid transactionId);\r\n    }\r\n<\/pre>\n<\/div>\n<p>Ard\u0131ndan bu aray\u00fcz\u00fc uygulayan s\u0131n\u0131f\u0131n kendisini olu\u015ftural\u0131m:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TransactionService : ITransactionService\r\n    {\r\n        public Task&lt;bool&gt; CheckReadyServices(Guid transactionId)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public Task&lt;bool&gt; CheckTransactionStateServices(Guid transactionId)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public Task Commit(Guid transactionId)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public Task&lt;Guid&gt; CreateTransaction()\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public Task PrepareServices(Guid transactionId)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n\r\n        public Task Rollback(Guid transactionId)\r\n        {\r\n            throw new NotImplementedException();\r\n        }\r\n    }\r\n<\/pre>\n<\/div>\n<p>Evet, birazdan bu servis i\u00e7erisindeki metotlar\u0131 ad\u0131m ad\u0131m kodluyor olaca\u011f\u0131z. \u015eimdi koordinat\u00f6r uygulamas\u0131n\u0131n &#8216;Program.cs&#8217; dosyas\u0131 \u00fczerinden IoC container&#8217;a ilgili servisi ekleyelim ve biryandan da kat\u0131l\u0131mc\u0131lar\u0131n base address bilgilerini &#8216;HttpClient&#8217; konfig\u00fcrasyonuyla tan\u0131mlayarak yap\u0131land\u0131rmay\u0131 tamamlayal\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n.\r\n.\r\n.\r\nbuilder.Services.AddHttpClient(&quot;OrderAPI&quot;, client =&gt; client.BaseAddress = new(&quot;https:\/\/localhost:7287\/&quot;));\r\nbuilder.Services.AddHttpClient(&quot;StockAPI&quot;, client =&gt; client.BaseAddress = new(&quot;https:\/\/localhost:7033\/&quot;));\r\nbuilder.Services.AddHttpClient(&quot;PaymentAPI&quot;, client =&gt; client.BaseAddress = new(&quot;https:\/\/localhost:7121\/&quot;));\r\n\r\nbuilder.Services.AddTransient&lt;ITransactionService, TransactionService&gt;();\r\n\r\nbuilder.Services.AddDbContext&lt;TwoPhaseCommitContext&gt;(options =&gt; options.UseSqlServer(builder.Configuration.GetConnectionString(&quot;SQLServer&quot;)));\r\n.\r\n.\r\n.\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki kod blo\u011funa g\u00f6z atarsan\u0131z e\u011fer <strong><em>9.<\/em><\/strong> sat\u0131rda olu\u015fturdu\u011fumuz servisi IoC container&#8217;a eklerken biryandan da <strong><em>5<\/em><\/strong> ile <strong><em>7.<\/em><\/strong> sat\u0131r aral\u0131\u011f\u0131nda ise bahsi ge\u00e7en kat\u0131l\u0131mc\u0131 servislerin adresleri tan\u0131mlanmaktad\u0131r.<\/p>\n<p>Bu tan\u0131mlama neticesinde &#8216;TransactionService&#8217; s\u0131n\u0131f\u0131nda bu kat\u0131l\u0131mc\u0131lar\u0131n &#8216;HttpClient&#8217; bilgilerini a\u015fa\u011f\u0131daki gibi hali haz\u0131r hale getirelim.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TransactionService(IHttpClientFactory _httpClientFactory, TwoPhaseCommitContext _context) : ITransactionService\r\n    {\r\n        HttpClient _httpClientOrderAPI = _httpClientFactory.CreateClient(&quot;OrderAPI&quot;);\r\n        HttpClient _httpClientStockAPI = _httpClientFactory.CreateClient(&quot;StockAPI&quot;);\r\n        HttpClient _httpClientPaymentAPI = _httpClientFactory.CreateClient(&quot;PaymentAPI&quot;);\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Tabi biryandan da olu\u015fturdu\u011fumuz context nesnesini de inject etti\u011fime dikkatinizi \u00e7ekerim.\n<\/li>\n<li><strong>Ad\u0131m 4<\/strong> <em style=\"font-size:12px;color:green;\">(Coordinator&#8217;de CreateTransaction Metodunun Tasarlanmas\u0131)<\/em><br \/>\n\u015eimdi koordinat\u00f6r servisinde t\u00fcm altyap\u0131 haz\u0131rland\u0131\u011f\u0131na g\u00f6re kullan\u0131c\u0131 talebi do\u011frultusunda transaction&#8217;\u0131 ba\u015flatacak olan &#8216;CreateTransaction&#8217; metodunu geli\u015ftirebiliriz. Bunun i\u00e7in a\u015fa\u011f\u0131daki gibi bir \u00e7al\u0131\u015fma ger\u00e7ekle\u015ftirebiliriz:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TransactionService(IHttpClientFactory _httpClientFactory, TwoPhaseCommitContext _context) : ITransactionService\r\n    {\r\n        HttpClient _httpClientOrderAPI = _httpClientFactory.CreateClient(&quot;OrderAPI&quot;);\r\n        HttpClient _httpClientStockAPI = _httpClientFactory.CreateClient(&quot;StockAPI&quot;);\r\n        HttpClient _httpClientPaymentAPI = _httpClientFactory.CreateClient(&quot;PaymentAPI&quot;);\r\n        .\r\n        .\r\n        .\r\n        public async Task&lt;Guid&gt; CreateTransaction()\r\n        {\r\n            Guid transactionId = Guid.NewGuid();\r\n            var nodes = await _context.Nodes.ToListAsync();\r\n            nodes.ForEach(node =&gt; node.NodeStates = new List&lt;NodeState&gt;\r\n            {\r\n                new(TransactionId : transactionId)\r\n                {\r\n                    IsReady = ReadyType.Pending,\r\n                    TransactionState = TransactionState.Pending\r\n                },\r\n            });\r\n\r\n            await _context.SaveChangesAsync();\r\n            return transactionId;\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere gelen iste\u011fe kar\u015f\u0131n t\u00fcm node&#8217;lar i\u00e7in bir &#8216;NodeState&#8217; olu\u015fturulmakta ve \u00fcretilmi\u015f olan transaction id ile bu state sat\u0131rlar\u0131 e\u015fle\u015ftirilmektedir. Ayr\u0131ca hen\u00fcz bu servislerin haz\u0131r olup olmad\u0131klar\u0131 kontrol edilmedi\u011fi i\u00e7in ve hala transaction s\u00fcreci sona ermedi\u011fi i\u00e7in &#8216;IsReady&#8217; ve &#8216;TransactionState&#8217; property&#8217;lerine &#8216;pending&#8217; de\u011feri verilmektedir.\n<\/li>\n<li><strong>Ad\u0131m 5<\/strong> <em style=\"font-size:12px;color:green;\">(2PC Protokol\u00fcn\u00fcn 1. A\u015famas\u0131n\u0131n Kodlanmas\u0131 &#8211; PrepareServices Metodunun Tasarlanmas\u0131)<\/em><br \/>\nArt\u0131k transaction ba\u015flat\u0131ld\u0131\u011f\u0131na g\u00f6re 2PC protokol\u00fcn\u00fcn 1. a\u015famas\u0131 olan kat\u0131l\u0131mc\u0131lar\u0131n haz\u0131rlanmas\u0131 evresini tasarlayabiliriz. Bunun i\u00e7in &#8216;PrepareServices&#8217; metodunu a\u015fa\u011f\u0131daki gibi geli\u015ftirebiliriz.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TransactionService(IHttpClientFactory _httpClientFactory, TwoPhaseCommitContext _context) : ITransactionService\r\n    {\r\n        HttpClient _httpClientOrderAPI = _httpClientFactory.CreateClient(&quot;OrderAPI&quot;);\r\n        HttpClient _httpClientStockAPI = _httpClientFactory.CreateClient(&quot;StockAPI&quot;);\r\n        HttpClient _httpClientPaymentAPI = _httpClientFactory.CreateClient(&quot;PaymentAPI&quot;);\r\n        .\r\n        .\r\n        .\r\n        public async Task PrepareServices(Guid transactionId)\r\n        {\r\n            var transactionNodes = await _context.NodeStates\r\n                .Include(ns =&gt; ns.Node)\r\n                .Where(n =&gt; n.TransactionId == transactionId)\r\n                .ToListAsync();\r\n            foreach (var transactionNode in transactionNodes)\r\n            {\r\n                try\r\n                {\r\n                    var response = transactionNode.Node.Name switch\r\n                    {\r\n                        &quot;Order.API&quot; =&gt; await _httpClientOrderAPI.GetAsync(&quot;ready&quot;),\r\n                        &quot;Stock.API&quot; =&gt; await _httpClientStockAPI.GetAsync(&quot;ready&quot;),\r\n                        &quot;Payment.API&quot; =&gt; await _httpClientPaymentAPI.GetAsync(&quot;ready&quot;)\r\n                    };\r\n                    \/\/Kat\u0131l\u0131mc\u0131lar\u0131n ready endpoint'inden result olarak true ya da false d\u00f6nmesini bekliyoruz.\r\n                    var result = bool.Parse(await response.Content.ReadAsStringAsync());\r\n                    await Console.Out.WriteLineAsync(result.ToString());\r\n                    transactionNode.IsReady = result ? ReadyType.Ready : ReadyType.Unready;\r\n                }\r\n                catch\r\n                {\r\n\r\n                    transactionNode.IsReady = ReadyType.Unready;\r\n                }\r\n            }\r\n            await _context.SaveChangesAsync();\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki kod blo\u011funu incelerseniz e\u011fer parametreden gelen transaction id de\u011feriyle e\u015fle\u015fen &#8216;NodeStates&#8217;ler sorgulanmakta ve her bir node&#8217;un &#8216;ready&#8217; endpoint&#8217;ine haz\u0131r olup olmad\u0131klar\u0131na dair cevap alabilmek i\u00e7in istek g\u00f6nderilmektedir. Bu istekler neticesinde kod i\u00e7erisinde belirtildi\u011fi gibi gelecek olan result&#8217;lar bool t\u00fcrde beklenmekte ve ona g\u00f6re <strong><em>23.<\/em><\/strong> sat\u0131rda d\u00f6n\u00fc\u015f\u00fcm ger\u00e7ekle\u015ftirilmektedir. E\u011fer ki &#8216;true&#8217; sonucu al\u0131n\u0131yorsa e\u011fer &#8216;IsReady&#8217; property&#8217;sinin de\u011feri &#8216;ready&#8217; olarak de\u011fi\u015ftirilmekte, yok e\u011fer al\u0131nm\u0131yorsa veya herhangi bir hata durumu s\u00f6z konusuysa &#8216;unready&#8217; olarak de\u011fi\u015ftirilmektedir.\n<\/li>\n<li><strong>Ad\u0131m 6<\/strong> <em style=\"font-size:12px;color:green;\">(T\u00fcm Kat\u0131l\u0131mc\u0131lar\u0131n Uygun Olup Olmad\u0131\u011f\u0131n\u0131n Kontrol Edilmesi &#8211; CheckReadyServices Metodunun Tasarlanmas\u0131)<\/em><br \/>\n&#8216;PrepareServices&#8217; metodu ile t\u00fcm kat\u0131l\u0131mc\u0131lar\u0131n haz\u0131r olup olmad\u0131\u011f\u0131na dair cevap alabilmek i\u00e7in g\u00f6nderilen istek neticesindeki durumu b\u00fct\u00fcnsel olarak kontrol etmemiz gerekmektedir. Bunun i\u00e7in de &#8216;CheckReadyServices&#8217; metodunu a\u015fa\u011f\u0131daki gibi geli\u015ftirebiliriz:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TransactionService(IHttpClientFactory _httpClientFactory, TwoPhaseCommitContext _context) : ITransactionService\r\n    {\r\n        HttpClient _httpClientOrderAPI = _httpClientFactory.CreateClient(&quot;OrderAPI&quot;);\r\n        HttpClient _httpClientStockAPI = _httpClientFactory.CreateClient(&quot;StockAPI&quot;);\r\n        HttpClient _httpClientPaymentAPI = _httpClientFactory.CreateClient(&quot;PaymentAPI&quot;);\r\n        .\r\n        .\r\n        .\r\n        public async Task&lt;bool&gt; CheckReadyServices(Guid transactionId) =&gt;\r\n            (await _context.NodeStates\r\n                    .Where(ns =&gt; ns.TransactionId == transactionId)\r\n                    .ToListAsync())\r\n            .TrueForAll(n =&gt; n.IsReady == ReadyType.Ready);\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Evet, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere parametre \u00fczerinden gelen transaction id de\u011feriyle kar\u015f\u0131la\u015fan &#8216;NodeState&#8217; verilerinin hepsinin, &#8216;IsReady&#8217; de\u011ferinin true olup olmad\u0131\u011f\u0131 kontrol edilmektedir.\n<\/li>\n<li><strong>Ad\u0131m 7<\/strong> <em style=\"font-size:12px;color:green;\">(2PC Protokol\u00fcn\u00fcn 2. A\u015famas\u0131n\u0131n Kodlanmas\u0131 &#8211; Commit Metodunun Tasarlanmas\u0131)<\/em><br \/>\nE\u011fer ki &#8216;CheckReadyServices&#8217; metodu geriye &#8216;true&#8217; de\u011ferini d\u00f6nd\u00fcr\u00fcrse koordinat\u00f6r 2PC protokol\u00fcn\u00fcn ikinci a\u015famas\u0131na ge\u00e7ecektir ve t\u00fcm kat\u0131l\u0131mc\u0131lardan \u00fczerlerine d\u00fc\u015fen operasyonlar\u0131 yapmalar\u0131n\u0131n talimat\u0131n\u0131 verecektir. Bunun i\u00e7in &#8216;Commit&#8217; metodunda a\u015fa\u011f\u0131daki gibi \u00e7al\u0131\u015fma ger\u00e7ekle\u015ftirebiliriz:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TransactionService(IHttpClientFactory _httpClientFactory, TwoPhaseCommitContext _context) : ITransactionService\r\n    {\r\n        HttpClient _httpClientOrderAPI = _httpClientFactory.CreateClient(&quot;OrderAPI&quot;);\r\n        HttpClient _httpClientStockAPI = _httpClientFactory.CreateClient(&quot;StockAPI&quot;);\r\n        HttpClient _httpClientPaymentAPI = _httpClientFactory.CreateClient(&quot;PaymentAPI&quot;);\r\n        .\r\n        .\r\n        .\r\n        public async Task Commit(Guid transactionId)\r\n        {\r\n            var transactionNodes = await _context.NodeStates\r\n                .Include(ns =&gt; ns.Node)\r\n                .Where(ns =&gt; ns.TransactionId == transactionId)\r\n                .ToListAsync();\r\n            foreach (var transactionNode in transactionNodes)\r\n            {\r\n                try\r\n                {\r\n                    var response = transactionNode.Node.Name switch\r\n                    {\r\n                        &quot;Order.API&quot; =&gt; await _httpClientOrderAPI.GetAsync(&quot;commit&quot;),\r\n                        &quot;Stock.API&quot; =&gt; await _httpClientStockAPI.GetAsync(&quot;commit&quot;),\r\n                        &quot;Payment.API&quot; =&gt; await _httpClientPaymentAPI.GetAsync(&quot;commit&quot;)\r\n                    };\r\n                    \/\/Kat\u0131l\u0131mc\u0131lar\u0131n ready endpoint'inden result olarak true ya da false d\u00f6nmesini bekliyoruz.\r\n                    var result = bool.Parse(await response.Content.ReadAsStringAsync());\r\n                    transactionNode.TransactionState = result ? TransactionState.Done : TransactionState.Abort;\r\n                }\r\n                catch\r\n                {\r\n                    transactionNode.TransactionState = TransactionState.Abort;\r\n                }\r\n            }\r\n            await _context.SaveChangesAsync();\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki \u00e7al\u0131\u015fmay\u0131 g\u00f6zlemlersek e\u011fer yine parametre \u00fczerinden gelen transaction id de\u011ferine g\u00f6re state&#8217;ler elde edilmekte ve t\u00fcm node&#8217;lar\u0131n &#8216;commit&#8217; endpoint&#8217;ine istekler g\u00f6nderilerek ikinci a\u015fama kat\u0131l\u0131mc\u0131lar a\u00e7\u0131s\u0131ndan ba\u015flat\u0131lmaktad\u0131r. Ve yine koddan da anla\u015f\u0131laca\u011f\u0131 \u00fczere commit i\u015flemleri neticesinde servislerden boolean t\u00fcrde sonu\u00e7 beklenmekte ve <strong><em>23.<\/em><\/strong> sat\u0131rda bu sonu\u00e7 boolean&#8217;a d\u00f6n\u00fc\u015ft\u00fcr\u00fclerek, ard\u0131ndan &#8216;TransactionState&#8217; property&#8217;sinin de\u011feri belirlenmektedir.\n<\/li>\n<li><strong>Ad\u0131m 8<\/strong> <em style=\"font-size:12px;color:green;\">(T\u00fcm Kat\u0131l\u0131mc\u0131lar A\u00e7\u0131s\u0131ndan Transaction&#8217;\u0131n Ba\u015far\u0131l\u0131 Olup Olmad\u0131\u011f\u0131n\u0131n Kontrol Edilmesi \u2013 CheckTransactionStateServices Metodunun Tasarlanmas\u0131)<\/em><br \/>\nCommit i\u015flemi yap\u0131ld\u0131\u011f\u0131na g\u00f6re art\u0131k bu s\u00fcrecinde t\u00fcm kat\u0131l\u0131mc\u0131lar a\u00e7\u0131s\u0131ndan ba\u015far\u0131l\u0131 olup olmad\u0131\u011f\u0131n\u0131n de\u011ferlendirilmesi gerekmektedir. Bunun i\u00e7in &#8216;CheckTransactionStateServices&#8217; metodunun a\u015fa\u011f\u0131daki gibi geli\u015ftirilmesi yeterlidir:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TransactionService(IHttpClientFactory _httpClientFactory, TwoPhaseCommitContext _context) : ITransactionService\r\n    {\r\n        HttpClient _httpClientOrderAPI = _httpClientFactory.CreateClient(&quot;OrderAPI&quot;);\r\n        HttpClient _httpClientStockAPI = _httpClientFactory.CreateClient(&quot;StockAPI&quot;);\r\n        HttpClient _httpClientPaymentAPI = _httpClientFactory.CreateClient(&quot;PaymentAPI&quot;);\r\n        .\r\n        .\r\n        .\r\n        public async Task&lt;bool&gt; CheckTransactionStateServices(Guid transactionId) =&gt;\r\n            (await _context.NodeStates\r\n                    .Where(ns =&gt; ns.TransactionId == transactionId)\r\n                    .ToListAsync())\r\n            .TrueForAll(n =&gt; n.TransactionState == TransactionState.Done);\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<\/li>\n<li><strong>Ad\u0131m 9<\/strong> <em style=\"font-size:12px;color:green;\">(Rollback Metodunun Tasarlanmas\u0131)<\/em><br \/>\nE\u011fer ki commit s\u00fcrecinde herhangi bir hata s\u00f6z konusu olursa yap\u0131lan t\u00fcm \u00e7al\u0131\u015fmalar\u0131n geri al\u0131nmas\u0131 gerekmektedir. Bunun i\u00e7in de &#8216;Rollback&#8217; metodunun a\u015fa\u011f\u0131daki gibi geli\u015ftirilmesi gerekmektedir:<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class TransactionService(IHttpClientFactory _httpClientFactory, TwoPhaseCommitContext _context) : ITransactionService\r\n    {\r\n        HttpClient _httpClientOrderAPI = _httpClientFactory.CreateClient(&quot;OrderAPI&quot;);\r\n        HttpClient _httpClientStockAPI = _httpClientFactory.CreateClient(&quot;StockAPI&quot;);\r\n        HttpClient _httpClientPaymentAPI = _httpClientFactory.CreateClient(&quot;PaymentAPI&quot;);\r\n        .\r\n        .\r\n        .\r\n        public async Task Rollback(Guid transactionId)\r\n        {\r\n            var transactionNodes = await _context.NodeStates\r\n                .Include(ns =&gt; ns.Node)\r\n                .Where(n =&gt; n.TransactionId == transactionId)\r\n                .ToListAsync();\r\n            transactionNodes.ForEach(async transactionNode =&gt;\r\n            {\r\n                try\r\n                {\r\n                    if (transactionNode.TransactionState == TransactionState.Done)\r\n                        _ = transactionNode.Node.Name switch\r\n                        {\r\n                            &quot;Order.API&quot; =&gt; await _httpClientOrderAPI.GetAsync(&quot;rollback&quot;),\r\n                            &quot;Stock.API&quot; =&gt; await _httpClientStockAPI.GetAsync(&quot;rollback&quot;),\r\n                            &quot;Payment.API&quot; =&gt; await _httpClientPaymentAPI.GetAsync(&quot;rollback&quot;),\r\n                        };\r\n                    transactionNode.TransactionState = TransactionState.Abort;\r\n                }\r\n                catch\r\n                {\r\n                    transactionNode.TransactionState = TransactionState.Abort;\r\n                }\r\n            });\r\n            await _context.SaveChangesAsync();\r\n        }\r\n        .\r\n        .\r\n        .\r\n    }\r\n<\/pre>\n<\/div>\n<p>Burada <strong><em>16<\/em><\/strong> ile <strong><em>23.<\/em><\/strong> sat\u0131r aral\u0131\u011f\u0131na g\u00f6z atarsan\u0131z e\u011fer commit s\u00fcrecinde &#8216;TransactionState&#8217;i &#8216;Done&#8217;a \u00e7ekilen transaction&#8217;lar i\u00e7in rollback mekanizmas\u0131n\u0131n ba\u015flat\u0131ld\u0131\u011f\u0131na dikkatinizi \u00e7ekerim.\n<\/li>\n<li><strong>Ad\u0131m 10<\/strong> <em style=\"font-size:12px;color:green;\">(Kat\u0131l\u0131mc\u0131lar\u0131n Yap\u0131land\u0131r\u0131lmas\u0131)<\/em><br \/>\nArt\u0131k koordinat\u00f6r\u00fcn temel operasyonunu tamamlad\u0131\u011f\u0131m\u0131za g\u00f6re kat\u0131l\u0131mc\u0131lar\u0131n yap\u0131land\u0131r\u0131lmas\u0131na el atabiliriz. Bunun i\u00e7in &#8216;Order.API&#8217;, &#8216;Stock.API&#8217; ve &#8216;Payment.API&#8217; servislerinde s\u0131ras\u0131yla a\u015fa\u011f\u0131daki endpoint&#8217;leri olu\u015ftural\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nvar app = builder.Build();\r\n\r\napp.MapGet(&quot;\/ready&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Order service is ready.&quot;);\r\n    return true;\r\n});\r\n\r\napp.MapGet(&quot;\/commit&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Order service is commited.&quot;);\r\n    return true;\r\n});\r\n\r\napp.MapGet(&quot;\/rollback&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Order service is rollbacked.&quot;);\r\n});\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nvar app = builder.Build();\r\n\r\napp.MapGet(&quot;\/ready&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Stock service is ready.&quot;);\r\n    return true;\r\n});\r\n\r\napp.MapGet(&quot;\/commit&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Stock service is commited.&quot;);\r\n    return true;\r\n});\r\n\r\napp.MapGet(&quot;\/rollback&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Stock service is rollbacked.&quot;);\r\n});\r\n\r\napp.Run();\r\n\r\n<\/pre>\n<\/div>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n\r\nvar app = builder.Build();\r\n\r\napp.MapGet(&quot;\/ready&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Payment service is ready.&quot;);\r\n    return true;\r\n});\r\n\r\napp.MapGet(&quot;\/commit&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Payment service is commited.&quot;);\r\n    return true;\r\n});\r\n\r\napp.MapGet(&quot;\/rollback&quot;, () =&gt;\r\n{\r\n    Console.WriteLine(&quot;Payment service is rollbacked.&quot;);\r\n});\r\n\r\napp.Run();\r\n\r\n<\/pre>\n<\/div>\n<\/li>\n<li><strong>Ad\u0131m 11<\/strong> <em style=\"font-size:12px;color:green;\">(Coordinator&#8217;de &#8216;CreateOrderTransaction&#8217; Endpoint&#8217;inin Olu\u015fturulmas\u0131)<\/em><br \/>\nYapm\u0131\u015f oldu\u011fumuz t\u00fcm bu \u00e7al\u0131\u015fmalar\u0131n, kullan\u0131c\u0131lardan gelecek olan taleplerin koordinat\u00f6r taraf\u0131ndan kar\u015f\u0131lanmas\u0131 ve i\u015flem s\u00fcrecinin 2PC protokol\u00fc e\u015fli\u011finde distributed sistemde ba\u015flat\u0131lmas\u0131 i\u00e7in altyap\u0131 olarak kullan\u0131lmas\u0131 gerekmektedir. Bunun i\u00e7in de hem koordinat\u00f6r\u00fcn i\u015flevini ba\u015flatacak hem de bu yap\u0131lanmay\u0131 altyap\u0131 olarak kullanacak olan endpoint&#8217;i koordinat\u00f6r servisinde a\u015fa\u011f\u0131daki gibi olu\u015ftural\u0131m.<\/p>\n<div style=\"font-size:12px;\">\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar builder = WebApplication.CreateBuilder(args);\r\n.\r\n.\r\n.\r\nvar app = builder.Build();\r\n\r\nif (app.Environment.IsDevelopment())\r\n{\r\n    app.UseSwagger();\r\n    app.UseSwaggerUI();\r\n}\r\n\r\napp.UseHttpsRedirection();\r\n\r\napp.MapGet(&quot;\/create-order-transaction&quot;, async (ITransactionService transactionService) =&gt;\r\n{\r\n    \/\/Phase 1 - Prepare\r\n    var transactionId = await transactionService.CreateTransaction();\r\n    await transactionService.PrepareServices(transactionId);\r\n    bool transactionState = await transactionService.CheckReadyServices(transactionId);\r\n\r\n    if (transactionState)\r\n    {\r\n        \/\/Phase 2 - Commit\r\n        await transactionService.Commit(transactionId);\r\n        transactionState = await transactionService.CheckTransactionStateServices(transactionId);\r\n    }\r\n\r\n    if (!transactionState)\r\n        await transactionService.Rollback(transactionId);\r\n})\r\n.WithName(&quot;GetWeatherForecast&quot;)\r\n.WithOpenApi();\r\n\r\napp.Run();\r\n<\/pre>\n<\/div>\n<p>Yukar\u0131daki \u00e7al\u0131\u015fmaya g\u00f6z atarsan\u0131z e\u011fer <strong><em>15.<\/em><\/strong> sat\u0131rda olu\u015fturulan <code>\/create-order-transaction<\/code> endpoint&#8217;inin i\u00e7erisinde; <strong><em>18.<\/em><\/strong> sat\u0131rda olu\u015fturdu\u011fumuz <code>CreateTransaction<\/code> metodu ile transaction&#8217;\u0131 ba\u015flat\u0131yor ve elde etti\u011fimiz transaction id e\u015fli\u011finde <strong><em>19.<\/em><\/strong> sat\u0131rda <code>PrepareServices<\/code> metodu ile t\u00fcm kat\u0131l\u0131mc\u0131lar\u0131n haz\u0131r olup olmad\u0131klar\u0131na dair talepte bulunuyoruz. <strong><em>20.<\/em><\/strong> sat\u0131rda ise bu talep neticesinde servislerin haz\u0131rl\u0131k durumlar\u0131n\u0131 <code>CheckReadyServices<\/code> fonksiyonuyla de\u011ferlendiriyoruz. Bu de\u011ferlendirme neticesinde transaction durumu ge\u00e7erliyse ikinci a\u015famaya ge\u00e7erek <code>Commit<\/code> metoduyla t\u00fcm kat\u0131l\u0131mc\u0131lara operasyon talimat\u0131n\u0131 veriyoruz, yok e\u011fer de\u011filse ya da commit&#8217;ten sonra <strong><em>26.<\/em><\/strong> sat\u0131rdaki <code>CheckTransactionStateServices<\/code> metodunda kontrol edildi\u011fi \u00fczere t\u00fcm kat\u0131l\u0131mc\u0131lar\u0131n transaction durumlar\u0131 beklendi\u011fi gibi &#8216;done&#8217; de\u011filse her iki durum i\u00e7in transaction&#8217;\u0131 <strong><em>30.<\/em><\/strong> sat\u0131rda oldu\u011fu gibi rollback ediyoruz.\n<\/li>\n<li><strong>Ad\u0131m 12<\/strong> <em style=\"font-size:12px;color:green;\">(Test)<\/em><br \/>\nVe art\u0131k yapt\u0131\u011f\u0131m\u0131z bu \u00e7al\u0131\u015fmay\u0131 test edebiliriz. Bunun i\u00e7in koordinat\u00f6r e\u015fli\u011finde t\u00fcm servisleri birlikte derleyip, aya\u011fa kald\u0131ral\u0131m. Ve ard\u0131ndan a\u015fa\u011f\u0131daki gibi s\u00fcreci ad\u0131m ad\u0131m takip edelim.<\/p>\n<ol>\n<li><em style=\"color:purple;\">Transaction&#8217;\u0131n Ba\u015flat\u0131lmas\u0131 (CreateTransaction)<\/em><br \/>\n<code>CreateTransaction<\/code> metodu ile transaction ba\u015flat\u0131ld\u0131\u011f\u0131nda ilk etapta her bir kat\u0131l\u0131mc\u0131ya kar\u015f\u0131n &#8216;NodeStates&#8217; tablosuna kay\u0131t at\u0131lmakta ve <code>IsReady<\/code> ve <code>TransactionState<\/code> kolonlar\u0131na &#8216;Pending&#8217; de\u011ferine kar\u015f\u0131l\u0131k gelen &#8216;1&#8217; de\u011feri verilmektedir.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-2.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-2.png\" alt=\"Microservice Mimarisinde Two-Phase Commit(2PC) Pattern \u0130le Transaction Y\u00f6netimi - Nedir Nas\u0131l Uygulan\u0131r Sagadan Fark\u0131 Nedir\" width=\"886\" height=\"277\" class=\"aligncenter size-full wp-image-26641\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-2.png 886w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-2-300x94.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-2-768x240.png 768w\" sizes=\"auto, (max-width: 886px) 100vw, 886px\" \/><\/a>\n<\/li>\n<li><em style=\"color:purple;\">Kat\u0131l\u0131mc\u0131lar\u0131n Haz\u0131r Olup Olmad\u0131\u011f\u0131na Dair Bildirimde Bulunulmas\u0131 (CheckReadyServices)<\/em><br \/>\nTransaction&#8217;\u0131n i\u015flenebilmesi i\u00e7in kat\u0131l\u0131mc\u0131lara haz\u0131r olup olmad\u0131klar\u0131na dair yap\u0131lan talep neticesinde, t\u00fcm kat\u0131l\u0131mc\u0131lar haz\u0131r oldu\u011fu taktirde &#8216;NodeStates&#8217; tablosunun <code>IsReady<\/code> kolonuna &#8216;Ready&#8217; de\u011ferine kar\u015f\u0131l\u0131k &#8216;0&#8217; de\u011feri verilmektedir.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-3.png\" alt=\"Microservice Mimarisinde Two-Phase Commit(2PC) Pattern \u0130le Transaction Y\u00f6netimi - Nedir Nas\u0131l Uygulan\u0131r Sagadan Fark\u0131 Nedir\" width=\"885\" height=\"278\" class=\"aligncenter size-full wp-image-26642\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-3.png 885w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-3-300x94.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-3-768x241.png 768w\" sizes=\"auto, (max-width: 885px) 100vw, 885px\" \/><\/a>E\u011fer ki kat\u0131l\u0131mc\u0131lardan herhangi birinde problem, eri\u015fim hatas\u0131 yahut cevap al\u0131namamazl\u0131k olsayd\u0131 ilgili kolona &#8216;Unready&#8217; de\u011ferindeki &#8216;2&#8217; de\u011feri verilecekti.\n<\/li>\n<li><em style=\"color:purple;\">T\u00fcm Kat\u0131l\u0131mc\u0131lara Operasyon Talimat\u0131n\u0131n Verilmesi (Commit)<\/em><br \/>\nKat\u0131l\u0131mc\u0131lar haz\u0131r olup <code>CheckReadyServices<\/code> metodu ile transaction&#8217;\u0131n state&#8217;i de\u011ferlendirildikten sonra 2. a\u015famadaki <code>Commit<\/code> metodu ile t\u00fcm kat\u0131l\u0131mc\u0131lara operasyonun ba\u015flat\u0131lmas\u0131\/i\u015flenmesi\/taahh\u00fct edilmesi talimat\u0131 verilecektir. \u0130\u015fte bu s\u00fcre\u00e7te kat\u0131l\u0131mc\u0131lar\u0131n i\u015flemleri ba\u015far\u0131yla tamamlan\u0131rsa &#8216;NodeStates&#8217; tablosundaki <code>TransactionState<\/code> kolonuna &#8216;Done&#8217; de\u011ferine kar\u015f\u0131l\u0131k gelen &#8216;0&#8217; de\u011ferleri verilmektedir.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-4.png\" alt=\"Microservice Mimarisinde Two-Phase Commit(2PC) Pattern \u0130le Transaction Y\u00f6netimi - Nedir Nas\u0131l Uygulan\u0131r Sagadan Fark\u0131 Nedir\" width=\"886\" height=\"276\" class=\"aligncenter size-full wp-image-26643\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-4.png 886w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-4-300x93.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-4-768x239.png 768w\" sizes=\"auto, (max-width: 886px) 100vw, 886px\" \/><\/a>\n<\/li>\n<li><em style=\"color:red;\">Rollback Durumu<\/em><br \/>\nE\u011fer ki kat\u0131l\u0131mc\u0131lardan en az biri haz\u0131r olmasa ya da i\u015flem s\u00fcrecinde herhangi bir problem meydana gelip ba\u015far\u0131yla sonu\u00e7lanmasa &#8216;NodeStates&#8217; tablosundaki <code>IsReady<\/code> ve <code>TransactionState<\/code> kolonlar\u0131 s\u0131ras\u0131yla &#8216;Unready&#8217; ve &#8216;Abort&#8217; de\u011ferlerine kar\u015f\u0131l\u0131k gelen &#8216;2&#8217; de\u011ferini alacakt\u0131rlar. Misal olarak; &#8216;Order.API&#8217; servisinde &#8216;ready&#8217; endpoint&#8217;inden &#8216;false&#8217; de\u011ferini d\u00f6necek \u015fekilde ayarda bulunup, tekrar uygulamay\u0131 aya\u011fa kald\u0131r\u0131rsak e\u011fer a\u015fa\u011f\u0131daki gibi yap\u0131lan transaction&#8217;a ait t\u00fcm veriler i\u00e7in ilgili kolonlarda beklenen de\u011ferlerin i\u015flendi\u011fini g\u00f6zlemliyor olaca\u011f\u0131z.<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-5.png\" alt=\"Microservice Mimarisinde Two-Phase Commit(2PC) Pattern \u0130le Transaction Y\u00f6netimi - Nedir Nas\u0131l Uygulan\u0131r Sagadan Fark\u0131 Nedir\" width=\"884\" height=\"258\" class=\"aligncenter size-full wp-image-26644\" srcset=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-5.png 884w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-5-300x88.png 300w, https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2023\/10\/Microservice-Mimarisinde-Two-Phase-Commit2PC-Pattern-Ile-Transaction-Yonetimi-Nedir-Nasil-Uygulanir-Sagadan-Farki-Nedir-5-768x224.png 768w\" sizes=\"auto, (max-width: 884px) 100vw, 884px\" \/><\/a>\n<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<p>\u0130\u015fte bu kadar \ud83d\ude42 G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere 2PC protokol\u00fc bu \u015fekilde, bu mant\u0131kta uygulanmaktad\u0131r \ud83d\ude42 \u015eimdi gelin bu tecr\u00fcbe etti\u011fimiz protokol\u00fcn avantajlar\u0131n\u0131 ve dezavantajlar\u0131n\u0131 de\u011ferlendirerek i\u00e7eri\u011fimize devam edelim.<\/p>\n<h3>2PC Protokol\u00fcn\u00fcn Avantaj ve Dezavantajlar\u0131<\/h3>\n<p>2PC protokol\u00fc, g\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere olduk\u00e7a g\u00fc\u00e7l\u00fc data consistency modeli sa\u011flayan bir pattern&#8217;d\u0131r. \u0130\u015flenecek distributed transaction&#8217;\u0131n atomik olmas\u0131n\u0131n garantisini sa\u011flamakta ve t\u00fcm microservisler a\u00e7\u0131s\u0131ndan k\u00fcm\u00fclatif olarak ya ba\u015far\u0131yla sonu\u00e7 al\u0131nmas\u0131n\u0131 ya da topyek\u00fcn rollback ile i\u015flemlerin geri al\u0131nmas\u0131n\u0131 sa\u011flamaktad\u0131r. Lakin bunu yaparken t\u00fcm servisler \u00fczerinde bir senkronizasyon sa\u011flayaca\u011f\u0131ndan dolay\u0131 sistemi kilitleme\/engelleme durumu s\u00f6z konusu olacakt\u0131r. \u0130\u015fte bu durumdan dolay\u0131 microservices mimarilerde data consistency s\u00fcre\u00e7lerinde pek \u00f6nerilen yakla\u015f\u0131m de\u011fildir diyebiliriz.<\/p>\n<p>Ayr\u0131ca fark ettiyseniz 2PC protokol\u00fcnde b\u00fcy\u00fck \u00f6l\u00e7\u00fcde koordinat\u00f6r taraf\u0131ndan g\u00f6nderilen mesajlara ba\u011f\u0131ml\u0131l\u0131k s\u00f6z konusudur. Yani net kriz yaratabilecek tek bir hata noktas\u0131 mevcuttur ki bu noktada bir problem ya da sorun ya\u015fan\u0131rsa sistemin kontrolden \u00e7\u0131kmas\u0131 i\u00e7ten bile de\u011fildir. <\/p>\n<h3>2PC Protokol\u00fcn\u00fcn Tercih Edilebilece\u011fi Senaryolar<\/h3>\n<p>2PC protokol\u00fc a\u015fa\u011f\u0131daki senaryolara uygun davran\u0131\u015f sergileyebilir;<\/p>\n<ul>\n<li><strong><em>Finansal \u0130\u015flemler<\/em><\/strong><br \/>\nFinansal uygulamalar; para transferleri, \u00f6deme ve hesap i\u015flemleri gibi hassas ve kritik durumlar bar\u0131nd\u0131rd\u0131\u011f\u0131 i\u00e7in veri b\u00fct\u00fcnl\u00fc\u011f\u00fc olduk\u00e7a \u00f6nem arz eden senaryolar\u0131 sa\u011flamaktad\u0131rlar. \u0130\u015fte bu tarz finansal senaryolarda 2PC protokol\u00fc korunakl\u0131 i\u015flev yap\u0131lmas\u0131n\u0131 sa\u011flayabilir.\n<\/li>\n<li><strong><em>Envanter Y\u00f6netimi<\/em><\/strong><br \/>\nB\u00fcy\u00fck \u00e7apl\u0131 envanter y\u00f6netimi sistemlerinde; \u00fcr\u00fcn eklemek, g\u00fcncellemek veya silmek gibi i\u015flemlerin tutarl\u0131 bir \u015fekilde koordine edilmesi 2PC ile m\u00fcmk\u00fcn olabilir.\n<\/li>\n<li><strong><em>Sipari\u015f \u0130\u015fleme Sistemleri<\/em><\/strong><br \/>\nE-ticaret platformlar\u0131 ve sipari\u015f i\u015fleme sistemleri, m\u00fc\u015fteri sipari\u015flerini i\u015flemek ve envanteri g\u00fcncellemek i\u00e7in da\u011f\u0131t\u0131k bir mimariye sahip olabilmektedir. Bu t\u00fcr bir mimaride sipari\u015f i\u015flemleri ve envanter g\u00fcncellemeleri 2PC ile atomik bir \u015fekilde \u00e7\u00f6z\u00fcmlenebilir.\n<\/li>\n<li><strong><em>Yedekleme ve Geri Y\u00fckleme<\/em><\/strong><br \/>\nVeritaban\u0131 yedekleme ve geri y\u00fckleme i\u015flemleri, veri b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fcn korunmas\u0131 a\u00e7\u0131s\u0131ndan kritik arz etmektedir. Dolay\u0131s\u0131yla verilerin g\u00fcvenli bir \u015fekilde geri y\u00fcklenmesi i\u00e7in 2PC protokol\u00fcnden istifade edilebilir.\n<\/li>\n<li><strong><em>Kurumsal Uygulamalar<\/em><\/strong><br \/>\nB\u00fcy\u00fck \u00f6l\u00e7ekli kurumsal uygulamalar, birden fazla microservice aras\u0131nda i\u015flem koordinasyonu gerektirebilir. 2PC bu tarz uygulamalarda da tercih edilebilir.\n<\/li>\n<\/ul>\n<p>Nihai olarak;<br \/>\nTwo-Phase Commit(2PC) pattern&#8217;\u0131 nispeten basit bir prensibe sahip olsa da, performans ve maliyet a\u00e7\u0131s\u0131ndan pek avantajl\u0131 diyemeyece\u011fimiz bir protokold\u00fcr. Transaction s\u00fcreci boyunca sistemin kitlenmesi ve t\u00fcm i\u015flemlerin ba\u011fl\u0131 oldu\u011fu koordinat\u00f6r\u00fcn olas\u0131 hatalar\u0131 durumunda t\u00fcm sistemin krize girmesi 2PC protokol\u00fcn\u00fcn optimizasyonunu da zorla\u015ft\u0131rd\u0131\u011f\u0131 g\u00f6r\u00fclmektedir. Bizler bu i\u00e7eri\u011fimizde mevzu bahis pattern&#8217;\u0131 tam teferruatl\u0131 bir \u015fekilde art\u0131lar\u0131 ve eksileri e\u015fli\u011finde de\u011ferlendirmi\u015f ve yaz\u0131ya aktarm\u0131\u015f bulunmaktay\u0131z. Art\u0131k ihtiya\u00e7lar do\u011frultusunda tercih edip etmemek, sizlerin kriti\u011fine, gereksinimlerine ve tercihlerine kalm\u0131\u015ft\u0131r \ud83d\ude42<\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek \u00e7al\u0131\u015fmaya a\u015fa\u011f\u0131daki github adresinden eri\u015febilirsiniz.<br \/>\n<a href=\"https:\/\/github.com\/gncyyldz\/Two.Phase.Commit.Example\" rel=\"noopener\" target=\"_blank\">https:\/\/github.com\/gncyyldz\/Two.Phase.Commit.Example<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Bu i\u00e7eri\u011fimizde microservice yakla\u015f\u0131m\u0131n\u0131 uygulad\u0131\u011f\u0131m\u0131z mimarilerde veri tutarl\u0131l\u0131\u011f\u0131n\u0131 sa\u011flaman\u0131n davran\u0131\u015flar\u0131ndan biri olan Two-Phase Commit(2PC) modelini ele alacak, nas\u0131l ve hangi durumlarda kullan\u0131ld\u0131\u011f\u0131n\u0131 de\u011ferlendiriyor olaca\u011f\u0131z. Ayr\u0131ca neden Saga pattern&#8217;\u0131na nazaran daha az tercih edilmesi&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":26637,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4912,153,3573],"tags":[4942,4948,4944,3575,3289,4941,4946,4947,4945,4940,4943],"class_list":["post-26623","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net-8","category-design-pattern","category-microservices","tag-2pc","tag-2pc-phases","tag-hazirlik-asamasi","tag-microservice","tag-microservices","tag-microservices-two-phase-commit","tag-phase-1","tag-phase-2","tag-taahhut-asamasi","tag-two-phase-commit","tag-two-phase-commit2pc"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26623","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=26623"}],"version-history":[{"count":16,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26623\/revisions"}],"predecessor-version":[{"id":26647,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/26623\/revisions\/26647"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/26637"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=26623"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=26623"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=26623"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}