<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://luongvilam123.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://luongvilam123.github.io/" rel="alternate" type="text/html" /><updated>2025-10-12T13:35:48+00:00</updated><id>https://luongvilam123.github.io/feed.xml</id><title type="html">Lam</title><subtitle>~/lambda</subtitle><entry><title type="html">Mysecondblog</title><link href="https://luongvilam123.github.io/mySecondBlog/" rel="alternate" type="text/html" title="Mysecondblog" /><published>2025-10-07T00:00:00+00:00</published><updated>2025-10-07T00:00:00+00:00</updated><id>https://luongvilam123.github.io/mySecondBlog</id><content type="html" xml:base="https://luongvilam123.github.io/mySecondBlog/"><![CDATA[<h1 id="heap-data-structure">Heap Data Structure</h1>

<p>In the heap data structure, the root node is compared with its children and arranged according to the order. So if a is a root node and b is its child, then the property, <strong>key (a)&gt;= key (b)</strong> will generate a max heap.</p>

<p>The above relation between the root and the child node is called as “Heap Property”.</p>

<p><strong>Depending on the order of parent-child nodes, the heap is generally of two types:</strong></p>

<p><strong>#1) Max-Heap</strong>: In a Max-Heap the root node key is the greatest of all the keys in the heap. It should be ensured that the same property is true for all the subtrees in the heap recursively.</p>

<p>The below diagram shows a Sample Max Heap. Note that the root node is greater than its children.</p>

<p><img src="https://www.softwaretestinghelp.com/wp-content/qa/uploads/2020/05/1-7.png" alt="" /></p>

<p><strong>#2) Min-Heap</strong>: In the case of a Min-Heap, the root node key is the smallest or minimum among all the other keys present in the heap. As in the Max heap, this property should be recursively true in all the other subtrees in the heap.</p>

<p><strong>An example,</strong> of a Min-heap tree, is shown below. As we can see, the root key is the smallest of all the other keys in the heap.</p>

<p><img src="https://www.softwaretestinghelp.com/wp-content/qa/uploads/2020/05/2-6.png" alt="" /></p>

<p><strong>A heap data structure can be used in the following areas:</strong></p>

<ul>
  <li>Heaps are mostly used to implement Priority Queues.</li>
  <li>Especially min-heap can be used to determine the shortest paths between the vertices in a Graph.</li>
</ul>

<p>As already mentioned, the heap data structure is a complete binary tree that satisfies the heap property for the root and the children. This heap is also called a <strong>binary heap</strong>.</p>

<h1 id="binary-heap"><strong>Binary Heap</strong></h1>

<p><strong>A binary heap fulfills the below properties:</strong></p>

<ul>
  <li>A binary heap is a complete binary tree. In a complete binary tree, all the levels except the last level are completely filled. At the last level, the keys are as far as left as possible.</li>
  <li>It satisfies the heap property. The binary heap can be max or min-heap depending on the heap property it satisfies.</li>
</ul>

<p>A binary heap is normally represented as an Array. As it is a complete binary tree, it can easily be represented as an array. Thus in an array representation of a binary heap, the root element will be A[0] where A is the array used to represent the binary heap.</p>

<p>So in general for any ith node in the binary heap array representation, A[i], we can represent the indices of other nodes as shown below.</p>

<table>
  <thead>
    <tr>
      <th><strong>A [(i-1)/2]</strong></th>
      <th><strong>Represents the parent node</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>A[(2*i)+1]</td>
      <td>Represents the left child node</td>
    </tr>
    <tr>
      <td>A[(2*i)+2]</td>
      <td>Represents the right child node</td>
    </tr>
  </tbody>
</table>

<p><strong>Consider the following binary heap:</strong></p>

<p><img src="https://www.softwaretestinghelp.com/wp-content/qa/uploads/2020/05/3-6.png" alt="" /></p>

<p><strong>The array representation of the above min binary heap is as follows:</strong></p>

<p><img src="https://www.softwaretestinghelp.com/wp-content/qa/uploads/2020/05/4-6.png" alt="" /></p>

<p>As shown above, the heap is traversed as per the <strong>level order</strong> i.e. the elements are traversed from left to right at each level. When the elements at one level are exhausted, we move on to the next level.</p>

<ol>
  <li>The <code class="language-plaintext highlighter-rouge">Customer Service</code> attempts to reserve credit</li>
  <li>It then sends back a reply message indicating the outcome</li>
  <li>The saga orchestrator either approves or rejects the <code class="language-plaintext highlighter-rouge">Order</code></li>
</ol>]]></content><author><name></name></author><summary type="html"><![CDATA[Heap Data Structure]]></summary></entry><entry><title type="html">Saga Pattern</title><link href="https://luongvilam123.github.io/Saga-Pattern/" rel="alternate" type="text/html" title="Saga Pattern" /><published>2025-09-19T00:00:00+00:00</published><updated>2025-09-19T00:00:00+00:00</updated><id>https://luongvilam123.github.io/Saga-Pattern</id><content type="html" xml:base="https://luongvilam123.github.io/Saga-Pattern/"><![CDATA[<p>Khi các hệ thống của chúng ta chuyển dịch sang kiến trúc Microservices, câu chuyện về việc phối hợp giữa vô số services trở nên phức tạp hơn bao giờ hết. Bài viết này sẽ dẫn bạn đi qua một “hiện trường” quen thuộc, cùng khám phá vì sao Saga Pattern được xem là lời giải thân thiện cho những distributed transaction dài hơi.</p>

<h3 id="bối-cảnh-vấn-đề">Bối Cảnh Vấn Đề</h3>

<p>Hãy tưởng tượng bạn đang sở hữu một hệ thống Microservices với những đặc điểm sau:</p>

<ul>
  <li>Mỗi service có database riêng và trao đổi với nhau thông qua các sự kiện (Event-Driven Architecture).</li>
  <li>Dòng nghiệp vụ của bạn kéo theo nhiều bước xử lý nằm rải rác ở các services khác nhau.</li>
  <li>Bạn cần một cơ chế bảo đảm toàn bộ chuỗi thao tác đó hoàn thành trọn vẹn, hoặc nếu có lỗi thì hệ thống vẫn hồi phục được.</li>
</ul>

<p>Đó chính là lúc distributed transactions bước lên sân khấu – và cũng là lúc Saga Pattern thể hiện giá trị.</p>

<h3 id="câu-chuyện-minh-họa">Câu Chuyện Minh Họa</h3>

<p><img src="/images/example-1.jpg" alt="Ví dụ về Saga Pattern" /></p>

<p>Để dễ hình dung, hãy cùng nhìn vào hành trình giải ngân một khoản vay. Chuỗi các bước 1, 2, 3, 4 lần lượt được xử lý bởi những services chuyên trách khác nhau. Mỗi bước được gọi là một <em>local transaction</em>: service thực hiện logic của nó, lưu kết quả vào database riêng và phát đi tín hiệu (event/response) để kích hoạt bước kế tiếp. Khi toàn bộ chuỗi hoàn thành, chúng ta có một distributed transaction trọn vẹn.</p>

<h3 id="bài-toán-đặt-ra">Bài Toán Đặt Ra</h3>

<p>Vậy làm sao để điều phối chuỗi local transactions này? Two-Phase Commit (2PC) là một lựa chọn, nhưng trong phạm vi bài viết chúng ta sẽ tập trung vào phương án được ưa chuộng hơn trong thế giới microservices: <strong>Saga Pattern</strong>.</p>

<h3 id="saga-pattern-là-gì">Saga Pattern Là Gì?</h3>

<p>Saga Pattern là một design pattern dùng để quản lý distributed transactions bằng cách chia chúng thành các local transactions được điều phối tuần tự. Có hai chiến lược chính:</p>

<ol>
  <li><strong>Saga Choreography (Điều Phối Phân Tán)</strong> – mỗi local transaction phát ra domain event để kích hoạt service kế tiếp.</li>
  <li><strong>Saga Orchestration (Điều Phối Tập Trung)</strong> – một orchestrator đóng vai trò nhạc trưởng, điều khiển các services lần lượt thực hiện local transaction của mình.</li>
</ol>

<h3 id="khi-choreography-lên-ngôi">Khi Choreography Lên Ngôi</h3>

<p><img src="/images/example-2.png" alt="Ví dụ về Saga Pattern Choreography" /></p>

<p>Trong phiên bản choreographed của bài toán cho vay, mọi thứ vận hành theo các sự kiện được phát tán:</p>

<ol>
  <li>Khách hàng gửi yêu cầu vay → <code class="language-plaintext highlighter-rouge">Eligibility Service</code> nhận request <code class="language-plaintext highlighter-rouge">POST /eligibilityCheck</code>, xử lý thông tin pháp lý và phát sự kiện thành công.</li>
  <li><code class="language-plaintext highlighter-rouge">Affordability Service</code> nhận sự kiện, kiểm tra thu nhập khách hàng, lưu kết quả và tiếp tục phát sự kiện mới.</li>
  <li><code class="language-plaintext highlighter-rouge">Decision Service</code> tạo khoản vay, ghi nhận dữ liệu và phát sự kiện quyết định giải ngân.</li>
  <li><code class="language-plaintext highlighter-rouge">Disbursement Service</code> nhận sự kiện cuối cùng, giải ngân khoản vay và ghi sổ kế toán.</li>
</ol>

<p>Dòng sự kiện khép lại khi tiền được giải ngân – distributed transaction hoàn tất một cách nhẹ nhàng.</p>

<h3 id="khi-orchestration-dẫn-dắt">Khi Orchestration Dẫn Dắt</h3>

<p><img src="/images/example-3.png" alt="Ví dụ về Saga Pattern Orchestration" /></p>

<p>Với chiến lược orchestration, chúng ta thêm một nhân vật trung tâm – orchestrator:</p>

<ol>
  <li>Khách hàng gửi yêu cầu vay → orchestrator nhận request và chủ động gửi sự kiện đến <code class="language-plaintext highlighter-rouge">Eligibility Service</code>.</li>
  <li>Khi <code class="language-plaintext highlighter-rouge">Eligibility Service</code> hoàn tất, orchestrator nhận thông báo và ra lệnh cho <code class="language-plaintext highlighter-rouge">Affordability Service</code> tiếp tục.</li>
  <li>Từng bước lần lượt được orchestrator điều khiển tới <code class="language-plaintext highlighter-rouge">Decision Service</code> và <code class="language-plaintext highlighter-rouge">Disbursement Service</code>.</li>
  <li>Khi bước cuối cùng hoàn thành, orchestrator xác nhận distributed transaction đã kết thúc.</li>
</ol>

<p>Về bản chất, hai chiến lược khác nhau ở cách điều phối, nhưng đều sử dụng các local transactions để xây dựng nên một workflow dài hơi.</p>

<h3 id="ưu-và-nhược-điểm">Ưu Và Nhược Điểm</h3>

<h2 id="ưu-điểm">Ưu Điểm</h2>
<ol>
  <li><strong>Khả năng mở rộng &amp; độc lập</strong> – Services chỉ cần lo phần việc của mình, không chia sẻ database, dễ dàng scale độc lập và tránh sự phụ thuộc chặt chẽ.</li>
  <li><strong>Giảm áp lực khóa dữ liệu</strong> – Local transaction commit ngay khi xong việc, giảm thời gian giữ lock, phù hợp với quy trình dài hạn và hạn chế deadlock.</li>
  <li><strong>Khả năng phục hồi</strong> – Khi một bước thất bại, Saga có thể chạy <em>compensating transaction</em> để quay ngược các bước trước đó, đảm bảo eventual consistency.</li>
  <li><strong>Ăn ý với Event-Driven Architecture</strong> – Saga phát huy sức mạnh khi kết hợp với message queue như Kafka, RabbitMQ, EventBridge,…</li>
</ol>

<h2 id="nhược-điểm-cons">Nhược Điểm (Cons)</h2>

<ul>
  <li><strong>Consistency chỉ là “eventual”</strong> – Không có đảm bảo atomic như 2PC. Trong một khoảng thời gian, dữ liệu có thể ở trạng thái trung gian (inconsistent).</li>
  <li><strong>Phức tạp khi định nghĩa compensating transaction</strong> – Không phải lúc nào cũng dễ để “undo” một bước (ví dụ: đã gửi email/SMS cho khách thì khó mà rollback).</li>
  <li><strong>Quản lý workflow phức tạp</strong> – Với choreography, hệ thống có nguy cơ tạo “event spaghetti” khó đọc và khó maintain; trong khi orchestration tạo dependency vào một orchestrator trung tâm dễ trở thành bottleneck.</li>
  <li><strong>Debug và giám sát khó khăn hơn</strong> – Transaction được phân tán qua nhiều service và xử lý bất đồng bộ, khiến việc trace và monitor khó hơn so với giao dịch đơn lẻ.</li>
  <li><strong>Latency cao hơn</strong> – Các bước thực hiện nối tiếp thông qua messaging làm độ trễ lớn hơn so với một ACID transaction trong cùng database.
    <h3 id="lời-kết">Lời Kết</h3>
  </li>
</ul>

<p>Saga Pattern không phải là viên đạn bạc, nhưng là một công cụ hiệu quả để giữ cho distributed transactions trong kiến trúc microservices vận hành an toàn, linh hoạt. Tùy vào bài toán, bạn có thể chọn choreography để tận dụng kiến trúc phân tán, hoặc orchestration nếu muốn sự điều phối tập trung. Điều quan trọng nhất là hiểu rõ bối cảnh hệ thống của bạn để lựa chọn giải pháp phù hợp.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Khi các hệ thống của chúng ta chuyển dịch sang kiến trúc Microservices, câu chuyện về việc phối hợp giữa vô số services trở nên phức tạp hơn bao giờ hết. Bài viết này sẽ dẫn bạn đi qua một “hiện trường” quen thuộc, cùng khám phá vì sao Saga Pattern được xem là lời giải thân thiện cho những distributed transaction dài hơi.]]></summary></entry></feed>