PHP 微服務之【分布式事務】


分布式事務一直是微服務的一個難點。相關的解決方案和框架大部分是 java 的,那么 php 該如何解決呢?下面一步一步講解如何用 php 解決分布式事務。

 

單機單數據源事務

首先從單機事務開始。

大概邏輯如下 :

try { // 開始事務  $db->beginTransaction(); // 執行你的操作  // ...  // 提交事務  $db->commit(); } catch (Exception $e) { // 執行失敗 回滾  $db->rollBack(); } 

 

單機多個數據源事務

如果你業務涉及到多個數據庫,事務大概邏輯是這個樣子:

try { // 開始事務  $db1->beginTransaction(); $db2->beginTransaction(); // 執行你的操作  // ...  // 提交事務  $db1->commit(); $db2->commit(); } catch (Exception $e) { // 執行失敗 回滾  $db1->rollBack(); $db2->rollBack(); } 

 

多機多數據源事務(分布式事務)

如果你的數據源和業務代碼都是分開的(微服務)這就是我們今天的核心。
由前面兩種情況來看,大概邏輯是差不多的,主要也分為 4 個步驟。

  1. 開始事務
  2. 執行邏輯代碼
  3. 提交事務
  4. 回滾事務

有些文章也稱為 tcc 也就是 234 步驟。

我們用一個常用的例子:下單。
主要 3 個步驟:

  1. 創建訂單
  2. 修改庫存
  3. 修改用戶積分

假設訂單,庫存,用戶都是獨立的服務。

按照前面的經驗大概分為 4 個步驟,我們以用戶為例 代碼如下:

class User { // 開始事務  public function beginTransaction() { $db->beginTransaction(); return $this; } // 執行代碼  public function doTransaction() { // 執行你的操作  // ...  return $this; } public function commit() { $db->commit(); } public funtion rollBack() { $db->rollBack(); } } 

庫存 (stock),訂單 (order) 和上面類似,也需要這 4 個方法,我就不寫了。
難點在於我們沒法直接操作數據源,只能通過 rpc 調用相應的服務來操作。依次執行上面的方法就好了。代碼如下:

try { // 開始事務  $user = new User(); $stock = new Stock(); $order = new Order(); $user = $user->beginTransaction(); $stock = $stock->beginTransaction(); $order = $order->beginTransaction(); // 執行你的操作  $user = $user->doTransaction(); $stock = $stock->doTransaction(); $order = $order->doTransaction(); // 提交事務  $user->commit(); $stock->commit(); $order->commit(); } catch (Exception $e) { // 執行失敗 回滾  $user->rollBack(); $stock->rollBack(); $order->rollBack(); } 

到這里可能有人看出問題來了,正常情況下這樣肯定是不行的。要上面這段代碼成立需要滿足 1 個條件:User 分別調用了 3 次,也就是 3 個請求。要保證這 3 個請求是調用的同一個實例化后的對象。Stock 和 Order 一樣。

User 調用邏輯如下:

// 第一次請求調用 $user = new User(); $user = $user->beginTransaction(); // 第二次請求調用 復用的第一次 $user $user = $user->doTransaction(); // 第三次請求調用 復用的第一次 $user $user->commit(); //或者 $user->rollBack(); 

注意: 雖然調用了 3 次但是只 new 了一次, 第二次和第三次請求是復用的第一次的對象。要滿足這個條件 服務供方必須 常駐內存 ,而且提供的 rpc服務必須支持鏈式調用的功能。

one 框架 
極簡。高性能。松耦合。分布式。可運行於多種環境

one 框架完美支持上面的要求。只需要把上面的 UserStock 和 Order 添加為 rpc 服務即可。還需要注意 beginTransaction 和 doTransaction 方法必須返回 $this 提供給后面的方法調用。

user 服務如下:

RpcServer::add(User::class); 

其他兩個類似。到此分布式事務問題就搞定了,可能覺得這么簡單嗎?這主要由於 one框架的 rpc 服務提供了鏈式調用(多個請求復用同一個對象)的功能。

可能有人要問:如果因為網絡問題或者其他問題導致最后一個服務的最后一次調用失敗了怎么辦?
解決方案就是事務補償,你可以把這類極端的情況下的錯誤,放到一個隊列里 起一服務來專門處理這里問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM