快速預覽
安裝laravel5.5 - laravel8之間的版本,然後安裝快速服務化的package
composer require windawake/laravel-reset-transaction dev-master
首先建立ResetProductController.php控制器,建立ResetProductModel.php模型,建立reset_transaction和reset_product兩張資料庫表。這些操作只需要執行下面命令全部完成
php artisan resetTransact:create-examples
phpunit.xml增加testsuite Transaction
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">
<testsuites>
......
<testsuite name="Transaction">
<directory>./vendor/windawake/laravel-reset-transaction/tests</directory>
</testsuite>
</testsuites>
......
</phpunit>
最後執行測試命令 ./vendor/bin/phpunit --testsuite=Transaction
執行結果如下所示,5個例子測試通過。
oot@DESKTOP-VQOELJ5:/web/linux/php/laravel/laravel62# ./vendor/bin/phpunit --testsuite=Transaction
PHPUnit 8.5.20 by Sebastian Bergmann and contributors.
..... 5 / 5 (100%)
Time: 219 ms, Memory: 22.00 MB
OK (5 tests, 5 assertions)
功能特性
- 開箱即用,不需要重構原有專案的程式碼,與mysql事務寫法一致,簡單易用。
- 支援http協議的服務化介面,想要支援其它協議則需要重寫中介軟體。
- 支援讀已提交,可重複讀,與mysql的事務隔離級別同步。
原理解析
看過《明日邊緣》電影就會知道,存檔和讀檔的操作。這個分散式事務元件仿造《明日邊緣》電影的原理,每次請求基礎服務一開始時讀檔,然後繼續後面的操作,結束時所有操作全部回滾並且存檔,最後commit把存檔全部執行成功。整個過程是遵守兩段提交協議,先prepare,最後commit。
如何使用
以vendor/windawake/laravel-reset-transaction/tests/TransactionTest.php
檔案為例子
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Support\Facades\DB;
class TransactionTest extends TestCase
{
public function testCreateWithCommit()
{
$num = rand(1, 10000);
$productName = 'php ' . $num;
$data = [
'store_id' => 1,
'product_name' => $productName,
];
// 開啟分散式事務,其實是生成全域性唯一id
$transactId = $this->beginDistributedTransaction();
$header = [
在header 'transact_id' => $transactId,
];
// 分散式事務內,請求都需要在request header帶上transact_id
$response = $this->post('api/resetProduct', $data, $header);
$product = $response->json();
// 分散式事務提交,也是介面請求,把之前的存檔記錄全部處理
$this->commitDistributedTransaction($transactId);
$response = $this->get('/api/resetProduct/' . $product['pid']);
$product = $response->json();
$this->assertEquals($productName, $product['product_name']);
}
private function beginDistributedTransaction()
{
return session_create_id();
}
private function commitDistributedTransaction($transactId)
{
$response = $this->post('/api/resetTransaction/commit', [], ['transact_id' => $transactId]);
return $response->getStatusCode();
}
private function rollbackDistributedTransaction($transactId)
{
$response = $this->post('/api/resetTransaction/rollback', [], ['transact_id' => $transactId]);
return $response->getStatusCode();
}
}
個人筆記
我之前寫了laravel快速服務化包,但是它沒有解決資料一致性的問題。嘗試用XA,但是XA只能解決單機多個資料庫,沒法解決多臺機器服務化的問題。然後我又嘗試去研究tcc和seata,但是看完後一臉懵逼,不知所措。無奈被逼上絕路,沒辦法了只能自創分散式事務解決方案。一直以來,我一直以為單單隻用mysql是沒法解決分散式事務的問題,現在終於明白,還是有辦法滴!
本作品採用《CC 協議》,轉載必須註明作者和本文連結