5つの分散トランザクションソリューションを比較すると、私は依然としてAlibabaのSeata(原則+実践)を好む

5つの分散トランザクションソリューションを比較すると、私は依然としてAlibabaのSeata(原則+実践)を好む

[[354367]]

この記事はWeChatの公開アカウント「Programmer's Insider Things」から転載したもので、著者はProgrammer's Insider Thingsです。この記事を転載する場合は、Programmer Insider 公式アカウントまでご連絡ください。

長い間投稿していませんでした。最近とても忙しいです。父親になって43日目です。肉体的にも精神的にも疲れています。年末だったため、会社はKPIを達成するために技術部門に10時までの残業を強制していました。夜になると、子供は2、3時間おきに起きてしまうので、基本的にぐっすり眠る機会はありませんでした。彼は毎日ぼんやりしており、時々奇妙な発疹も出るので、私たちはいつも心配していました。

記事を書くための限られた時間は無限に分割されます。あぁ〜働くって本当に大変ですね。

その小さな表情は何を意味しているのでしょうか?

最初は何を書いていいか分かりませんでしたが、たまたま分散トランザクションに Alibaba の Seata ミドルウェアを使用するという新しいプロジェクトが手元にあったので、実践を共有します。

Seata を紹介する前に、分散トランザクションの基本的な概念を簡単に確認しましょう。

分散トランザクションの生成

まず、Baidu の分散トランザクションの定義を見てみましょう。分散トランザクションとは、参加者、トランザクションをサポートするサーバー、リソース サーバー、およびトランザクション マネージャーが異なる分散システムの異なるノードに配置されているトランザクションを指します。

え〜とちょっと抽象的ですね。理解するために簡単な絵を描いてみましょう。注文を受けて在庫を減らし、残高を差し引く例を見てみましょう。

システムが小さい場合、モノリシック アーキテクチャは既存のビジネス ニーズを完全に満たすことができます。すべてのビジネスがデータベースを共有し、注文プロセス全体では、1 つの方法と同じトランザクションでデータベースを操作するだけで済む場合があります。この時点で、すべての操作をコミットするか、すべての操作をロールバックするのは簡単です。

サブライブラリとサブテーブル、SOA

しかし、ビジネス量が拡大し続けると、モノリシックアーキテクチャは徐々に膨大なトラフィックに耐えられなくなります。このとき、データベースとテーブルを分割し、アプリケーションを SOA サービスに分割する必要があります。これにより、注文センター、ユーザー センター、在庫センターなどが生まれました。これによって生じた問題は、ビジネスが互いに分離され、各ビジネスが独自のデータベースを維持し、データ交換が RPC 呼び出しを通じてのみ実行できることでした。

ユーザーが再度注文を行う場合、注文ライブラリ、在庫ライブラリ、ユーザーライブラリ アカウントに対して同時に操作を実行する必要があります。ただし、現時点ではローカルデータの一貫性のみを保証でき、他のサービスを呼び出す操作が成功するかどうかは保証できません。したがって、注文プロセス全体のデータの一貫性を確保するには、分散トランザクションが必要になります。

シータの利点

分散トランザクションを実装するためのソリューションは数多くあり、XA プロトコルに基づく 2PC や 3PC、ビジネス レイヤーに基づく TCC、メッセージ キュー + メッセージ テーブルを適用して実装される最終的な一貫性ソリューション、そして今日説明する Seata ミドルウェアなどがあります。それぞれのソリューションの長所と短所を見てみましょう。

2PC

XA プロトコルに基づいて実装された分散トランザクションは、トランザクション マネージャーとローカル リソース マネージャーの 2 つの部分に分かれています。ローカル リソース マネージャーは、Oracle、MYSQL などのデータベースによって実装されることが多く、これらのデータベースは XA インターフェイスを実装しており、トランザクション マネージャーはグローバル スケジューラーとして機能します。

2 フェーズ コミット (2PC) はビジネスにほとんど影響を与えません。その最大の利点は、ユーザーにとって透明性があることです。ユーザーは、ローカル トランザクションと同様に XA プロトコルに基づく分散トランザクションを使用できるため、トランザクションの ACID 特性を厳密に保証できます。

しかし、2PC の欠点も明らかです。これは、強力な一貫性を備えた同期ブロッキング プロトコルです。トランザクションの実行中は、必要なすべてのリソースをロックする必要があります。これは一般に、固定トランザクションと呼ばれます。したがって、一定の実行時間を持つ短いトランザクションに適しており、全体的なパフォーマンスは比較的劣ります。

トランザクション コーディネーターがクラッシュしたり、ネットワーク ジッターが発生すると、参加者はリソースをロックした状態のままになったり、一部の参加者のみが正常に送信したりして、データの不整合が発生します。したがって、高い同時実行パフォーマンスが最も重要となるシナリオでは、XA プロトコルに基づく分散トランザクションは最適な選択ではありません。

3PC

3 フェーズ コミット (3PC) は、2 フェーズ コミット (2PC) の改良版です。これは、2 フェーズ コミット プロトコルのブロッキング問題を解決するために使用されます。コーディネータがクラッシュすると、参加者は最終的な選択を行うことができず、ブロックされたままになり、リソースがロックされます。

2PC では、コーディネータのみにタイムアウト メカニズムがありますが、3PC では、コーディネータと参加者の両方にタイムアウト メカニズムが導入されています。コーディネーターが失敗した場合、参加者は永久にブロックされることはありません。さらに、第 1 フェーズと第 2 フェーズの間に準備フェーズが挿入され (下の図に示すように、少し長く見えます)、最終的な送信フェーズの前に各参加ノードのステータスが一貫していることが保証されます。

3PC は、コーディネータの障害後に参加者がブロックされる問題を解決するためにタイムアウト メカニズムを使用しますが、余分なネットワーク通信が追加され、パフォーマンスが低下するため、推奨されません。

TCC

いわゆる TCC プログラミング モードも、2 フェーズ コミットのバリエーションです。違いは、TCC がビジネス レイヤーでコードを記述して 2 フェーズ コミットを実装することです。 TCC はそれぞれ Try、Confirm、Cancel の略です。一つの業務運営は、これら3つの方法に対応している必要があります。

次の単一在庫控除を例に挙げます。試行段階では在庫を取得し、確認段階では実際に在庫を減らします。在庫の減額が失敗した場合、キャンセル ステージがロールバックされ、在庫が解放されます。

TCC では、各メソッドがトランザクションを直接コミットするため、リソース ブロッキングの問題はありません。例外が発生すると、Cancel を使用してロールバックし、補正します。これはしばしば補償取引と呼ばれます。

元々は 1 つの方法でしたが、現在は 3 つの方法のサポートが必要です。 TCC はビジネスに非常に侵襲的であり、このモデルはうまく再利用できないため、開発量の急増につながることがわかります。ネットワークの変動やその他の要因も考慮する必要があります。リクエストが確実に配信されるように再試行メカニズムが用意されているため、インターフェースのべき等性を考慮する必要があります。

メッセージトランザクション(結果整合性)

メッセージ トランザクションは、実際にはメッセージ ミドルウェアに基づく 2 フェーズ コミットであり、ローカル トランザクションとメッセージ送信を同じトランザクションに配置して、ローカル操作とメッセージ送信が同時に成功することを保証します。発注時に在庫を差し引く原理図:

  • 注文システムは在庫減額の準備をするために MQ にメッセージを送信します。 MQ はメッセージを保存し、成功した ACK を返します。
  • 準備されたメッセージが正常に実行されたことを示す ACK を受信した後、注文システムはローカル注文操作を実行します。メッセージの送信が成功したにもかかわらずローカル トランザクションが失敗することを防ぐために、注文システムは MQ コールバック インターフェイスを実装し、ローカル トランザクションが正常に実行されたかどうかを継続的にチェックします。失敗した場合、準備されたメッセージはロールバックされます。成功した場合、メッセージは最終的にコミットされます。
  • 在庫システムは在庫減額メッセージを消費し、ローカル トランザクションを実行します。控除が失敗した場合、メッセージは再送信されます。再試行回数を超えると、ローカル テーブルは失敗したメッセージを保持し、補正するためにスケジュールされたタスクを開始します。

メッセージ ミドルウェアに基づく 2 フェーズ コミット ソリューションは、通常、同時実行性の高いシナリオで使用され、パフォーマンスが大幅に向上する代わりに、強力なデータ一貫性が犠牲になります。ただし、この方法を実装するにはコストと複雑さが比較的高く、実際のビジネス状況によって異なります。

シータ

Seata は、2 フェーズ コミットから進化した分散トランザクション ソリューションでもあり、AT、TCC、SAGA、XA などのトランザクション モードを提供します。ここではATモードに焦点を当てます。

Seata は 2 段階のサブミッションなので、各段階で何が行われるか見てみましょう。以下では、注文から在庫と残高を差し引く例も取り上げます。

まず、Seata 分散トランザクションのいくつかの役割を紹介します。

  • トランザクション コーディネーター (TC): グローバル トランザクション コーディネーター。グローバル トランザクションと各ブランチ トランザクション (異なるサービス) のステータスを調整し、グローバル トランザクションと各ブランチ トランザクションのロールバックまたはコミットを実行するために使用されます。
  • トランザクション マネージャー™: トランザクション マネージャーは、ビジネス レイヤーで全体的なトランザクションを開始/コミット/ロールバックするために使用されます (アノテーションを使用して、サービスを呼び出すメソッドでトランザクションを開始します)。
  • リソース マネージャー (RM): 一般的に、ブランチ トランザクションを表すビジネス データベースを指します。ブランチ トランザクションを管理し、TC と調整してブランチ トランザクションを登録し、ブランチ トランザクションのステータスを報告し、ブランチ トランザクションのコミットまたはロールバックを実行します。

Seata は分散トランザクションを実装し、重要な役割 UNDO_LOG (ロールバック ログ レコード テーブル) を設計します。このテーブルは、各アプリケーションの分散トランザクションのビジネス ライブラリに作成されます。このテーブルの中心となる機能は、更新前後の業務データのデータミラーリングをロールバックログに整理し、UNDO_LOG テーブルにバックアップして、業務上の異常をいつでもロールバックできるようにすることです。

フェーズ1

たとえば、以下ではユーザー テーブルの名前フィールドを更新します。

  1. アップデート ユーザー セット 名前= 'シャオフーは最もハンサム'  どこ 名前= 'プログラマーのインサイダー'  

まず、Seata の JDBC データ ソース エージェントは、ビジネス SQL を解析して SQL メタデータを抽出します。つまり、SQL タイプ (UPDATE)、テーブル (ユーザー)、条件 (名前 = 'Programmer') などの関連情報を取得します。

第一段階のフローチャート

まず、データ フロント ミラーをクエリし、解析によって取得した条件情報に基づいてクエリ ステートメントを生成し、データの一部を検索します。

  1. 選択  名前 から ユーザー どこ 名前= 'プログラマーのインサイダー'  

データフロントミラー

次に、ビジネスSQLを実行して、フロントミラーデータの主キーに基づいてバックミラーデータをクエリします。

  1. 選択 名前 から ユーザー ここで、 id = 1


データバックミラー

更新前後の業務データのデータミラーをロールバックログに整理し、業務データの更新ログとロールバックログを同じローカルトランザクションでコミットし、それぞれ業務テーブルと UNDO_LOG テーブルに挿入します。

ロールバックレコードのデータ形式は次のとおりです: afterImage (前イメージ)、beforeImage (後イメージ)、branchId (ブランチトランザクションID)、xid (グローバルトランザクションID)

  1. {
  2. 「ブランチID」 :641789253、
  3. 「xid」 : 「xid:xxx」
  4. 「元に戻すアイテム」 :[
  5. {
  6. 「後イメージ」 : {
  7. 「行」 :[
  8. {
  9. 「フィールド」 :[
  10. {
  11. 「名前」 : 「ID」
  12. 「タイプ」 : 4,
  13. 「値」 :1
  14. }
  15. ]
  16. }
  17. ]、
  18. "テーブル名" : "製品"  
  19. },
  20. 「前画像」 :{
  21. 「行」 :[
  22. {
  23. 「フィールド」 :[
  24. {
  25. 「名前」 : 「ID」
  26. 「タイプ」 : 4,
  27. 「値」 :1
  28. }
  29. ]
  30. }
  31. ]、
  32. "テーブル名" : "製品"  
  33. },
  34. "sqlType" : "更新"  
  35. }
  36. ]
  37. }

これにより、送信されたビジネス データの更新には必ず対応するロールバック ログが必要になります。

ローカル トランザクションをコミットする前に、各ブランチ トランザクションは、ブランチ (ブランチ ID) をグローバル トランザクション コーディネーター TC に登録し、変更するレコードのグローバル ロックを申請する必要があります。このデータをロックするには、SELECT FOR UPDATE ステートメントを使用します。ロックを取得できない場合は、ローカル トランザクションをロールバックする必要があります。 TM がトランザクションを開始すると、グローバルに一意の XID が生成され、呼び出された各サービス間で渡されます。

このようなメカニズムにより、グローバル トランザクションの最初のフェーズでローカル トランザクション ブランチ (Branch Transaction) をコミットし、ローカル トランザクションによってロックされたリソースを即座に解放することができます。第 2 フェーズでリソースを解放する従来の XA トランザクションと比較して、Seata はロック範囲を削減し、効率を向上させます。第 2 フェーズで例外が発生し、ロールバックする必要がある場合でも、対応するロールバック データを UNDO_LOG テーブルからすばやく見つけて、SQL に逆解析し、ロールバック補正を実現できます。

最後に、ローカル トランザクションがコミットされ、更新されたビジネス データと以前に生成された UNDO LOG データが一緒にコミットされ、ローカル トランザクションの送信結果がグローバル トランザクション コーディネーター TC に報告されます。

第二段階

2 番目の段階では、各ブランチの解決に基づいてコミットまたはロールバックを実行します。

解決がグローバル コミットの場合、各ブランチ トランザクションはコミットされて成功し、グローバル トランザクション コーディネーター (TC) はブランチに第 2 フェーズの要求を送信します。 TC からブランチ送信要求を受信すると、要求は非同期タスク キューに配置され、送信成功結果がすぐに TC に返されます。非同期キューは、ブランチ ID に基づいて、対応する UNDO LOG ロールバック レコードを非同期かつバッチで検索して削除します。

解決がグローバル ロールバックの場合、プロセスはグローバル コミットよりも少し複雑になります。 RM サービスは、TC グローバル コーディネータからロールバック要求を受信し、XID とブランチ ID を通じて対応するロールバック ログ レコードを見つけ、ロールバック レコードを通じて逆更新 SQL を生成して実行し、ブランチのロールバックを完了します。

注意: ローカル ビジネス トランザクションの実行後、ロールバック ログ レコード操作を削除する必要があります。

複数の分散トランザクションの利点と欠点については上記で説明しました。分散トランザクションの途中でSeataを実践して体感してみましょう。

シータプラクティス

Seata は独立して導入する必要があるミドルウェアなので、まずは Seata Server をセットアップします。ここでは、最新バージョンの seata-server-1.4.0 を例に説明します。ダウンロードアドレス: https://seata.io/en-us/blog/download.html

ファイルを解凍した後は、\seata\conf ディレクトリ内の file.conf ファイルと registry.conf ファイルのみに注意する必要があります。

Seata サーバー

ファイル.conf

file.conf ファイルは、永続的なトランザクション ログのモードを構成するために使用されます。現在、file、db、redis の 3 つのモードが提供されています。


file.conf ファイルの設定

注: db モードを選択した後、対応するデータベースに 3 つのテーブルを作成する必要があります: globalTable (永続的なグローバル トランザクション)、branchTable (送信された各ブランチの永続的なトランザクション)、および lockTable (リソースをロックする各ブランチの永続的なトランザクション)。

  1. -- GlobalSessionデータを保存するテーブル 
  2. -- 永続的なグローバルトランザクション 
  3. 作成する テーブルが存在しない場合`global_table`
  4. `xid` VARCHAR (128)ではない  NULL
  5. `transaction_id` BIGINT
  6. `status` TINYINT NOT   NULL
  7. `application_id` VARCHAR (32)、
  8. `transaction_service_group` VARCHAR (32)、
  9. `トランザクション名` VARCHAR (128)、
  10. `タイムアウト` INT ,
  11. `begin_time` BIGINT
  12. `application_data` VARCHAR (2000)、
  13. `gmt_create` 日付時刻、
  14. `gmt_modified` 日付時刻、
  15. 主要な キー(`xid`)、
  16. キー`idx_gmt_modified_status` (`gmt​​_modified`, `status`),
  17. キー`idx_transaction_id` (`transaction_id`)
  18. ) エンジン = InnoDB
  19. デフォルト文字セット = utf8;
  20.  
  21. -- BranchSessionデータを保存するテーブル 
  22. --各コミットブランチのトランザクションを永続化する 
  23. 作成する テーブルが存在しない場合`branch_table`
  24. `branch_id` BIGINT        ない  NULL
  25. `xid` VARCHAR (128)ではない  NULL
  26. `transaction_id` BIGINT
  27. `resource_group_id` VARCHAR (32)、
  28. `resource_id` VARCHAR (256)、
  29. `branch_type` VARCHAR (8)、
  30. `ステータス` TINYINT、
  31. `client_id` VARCHAR (64)、
  32. `application_data` VARCHAR (2000)、
  33. `gmt_create` 日付時刻(6)、
  34. `gmt_modified` 日付時刻(6)、
  35. 主要な キー(`branch_id`)、
  36. キー`idx_xid` (`xid`)
  37. ) エンジン = InnoDB
  38. デフォルト文字セット = utf8;
  39.  
  40. -- ロックデータを保存するテーブル 
  41. -- 各ブランチロックテーブルトランザクションを永続化する 
  42. 作成する テーブルが存在しない場合`lock_table`
  43. `row_key` VARCHAR (128) NOT   NULL
  44. `xid` VARCHAR (96)、
  45. `transaction_id` BIGINT
  46. `branch_id` BIGINT        ない  NULL
  47. `resource_id` VARCHAR (256)、
  48. `テーブル名` VARCHAR (32)、
  49. `pk` VARCHAR (36)、
  50. `gmt_create` 日付時刻、
  51. `gmt_modified` 日付時刻、
  52. 主要な キー(`行キー`)、
  53. キー`idx_branch_id` (`branch_id`)
  54. ) エンジン = InnoDB
  55. デフォルト文字セット = utf8;

レジストリ.conf

registry.conf ファイルは、レジストリ センターと構成センターを設定します。

現在、登録センターは、nacos、eureka、redis、zk、consul、etcd3、sofa の 7 種類をサポートしています。ここでは登録センターとして eureka を使用します。構成センターは、nacos、apollo、zk、consul、etcd3 の 5 つのタイプをサポートしています。

registry.conf ファイルの設定

設定が完了したら、\seata\bin ディレクトリで seata-server を起動すると、Seata サーバーがセットアップされます。

シータクライアント

Seata Server 環境が構築されたら、order-server (注文サービス)、storage-server (在庫控除サービス)、account-server (口座金額サービス) の 3 つの新しいサービスを作成し、それぞれ eureka に登録します。

各サービスの一般的なコア構成は次のとおりです。

  1. 春:
  2. 応用:
  3. 名前: ストレージサーバー
  4. 雲:
  5. アリババ:
  6. シータ:
  7. tx-サービス-グループ: my_test_tx_group
  8. データソース:
  9. ドライバークラス: com.mysql.jdbc.Driver
  10. URL: jdbc:mysql://47.93.6.1:3306/seat-storage
  11. ユーザー名: root
  12. パスワード: root
  13.  
  14. # ユーレカレジストリ
  15. ユーレカ:
  16. クライアント:
  17. サービス URL:
  18. デフォルトゾーン: http://${eureka.instance.hostname}:8761/eureka/
  19. 実例:
  20. ホスト名: 47.93.6.5
  21. 優先IPアドレス: true  

一般的なビジネス プロセスは次のとおりです。ユーザーが注文要求を開始し、ローカル注文サービスが注文レコードを作成し、RPC を介してリモートでストレージ控除在庫サービスとアカウント控除残高サービスを呼び出します。 3 つのサービスが同時に正常に実行された場合にのみ、注文プロセスが完了します。サービスの実行に失敗した場合、他のすべてのサービスはロールバックされます。

Seata はビジネス コードに非常に干渉します。コード内でこれを使用するには、@GlobalTransactional アノテーションを使用してグローバル トランザクションを開始するだけです。

  1. @オーバーライド
  2. @GlobalTransactional( name = "create-order" 、 rollbackFor = Exception.class)
  3. パブリックvoid create (注文 注文) {
  4.  
  5. 文字列 xid = RootContext.getXID();
  6.  
  7. LOGGER.info( "------->トランザクションが開始されました" );
  8. //ローカルメソッド
  9. orderDao.create (注文) ;
  10.  
  11. //在庫を減算するリモートメソッド
  12. storageApi.decrease( order .getProductId(), order .getCount());
  13.  
  14. //口座残高を差し引くリモートメソッド
  15. LOGGER.info( "------->口座引き落とし注文開始" );
  16. accountApi.decrease( order .getUserId(), order .getMoney());
  17. LOGGER.info( "------->注文を終了するためにアカウントから引き落としています" );
  18.  
  19. LOGGER.info( "------->トランザクションが終了しました" );
  20. LOGGER.info( "グローバルトランザクションxid: {}" , xid);
  21. }

前述したように、Seata AT モードは分散トランザクションを実装します。データ ロールバック ログを保存するには、関連するビジネス ライブラリに undo_log テーブルを作成する必要があります。テーブル構造は次のとおりです。

  1. -- AT モードの場合、ビジネス データベース用にこの SQL を初期化する必要があります。 seata サーバーではそれは必要ありません。  
  2. 作成する テーブルが存在しない場合`undo_log`
  3. `id` BIGINT (20) NOT   NULL AUTO_INCREMENT COMMENT '増分ID' ,
  4. `branch_id` BIGINT (20) NOT   NULL COMMENT 'ブランチトランザクションID'
  5. `xid` VARCHAR (100)ではない  NULL COMMENT 'グローバルトランザクションID'
  6. `context` VARCHAR (128) NOT   NULL COMMENT 'undo_logコンテキスト(シリアル化など)'
  7. `rollback_info` LONGBLOB NOT   NULLコメント「ロールバック情報」
  8. `log_status` INT (11) NOT   NULL COMMENT '0:通常状態、1:防御状態'
  9. `log_created` 日付時刻NOT   NULLコメント'create datetime'
  10. `log_modified` 日付時刻NOT   NULLコメント'datetimeの変更'
  11. 主要な キー(`id`)、
  12. 個性的 キー`ux_undo_log` (`xid`, `branch_id`)
  13. ) エンジン = InnoDB
  14. AUTO_INCREMENT = 1
  15. デフォルト文字セット = utf8 コメント = 'AT トランザクション モード undo テーブル' ;

環境設定の作業はこれで完了です。完全なケースは後で GitHub に投稿される予定なので、ここではスペースを取りません。

シータのテスト

プロジェクト内のサービス呼び出しプロセスは次のとおりです。

サービスコールプロセス

各サービスを開始した後、注文インターフェースを直接要求して効果を確認します。注文テーブルが正常にレコードを作成し、保管在庫テーブルの使用フィールドの数が増加し、口座残高テーブルの使用フィールドの数が増加している限り、注文プロセスが成功したことを意味します。

生データ

リクエスト後の転送プロセスは正常であり、データは期待どおりです

注文データ

そして、TMトランザクションマネージャのオーダーサーバーサービスのコンソールにも2フェーズコミットのログが出力されていることがわかりました。

コンソールが2回送信

それでは、いずれかのサービスに異常がある場合、正常にロールバックされるかどうかを確認しましょう。アカウント サーバー サービスでタイムアウト例外をシミュレートして、グローバル トランザクションをロールバックできるかどうかを確認します。

グローバルトランザクションのロールバック

すべてのデータが正常に実行されなかったことが判明しましたが、これはグローバル トランザクションのロールバックも成功したことを示しています。

undo_log ロールバック レコード テーブルの変更を見てみましょう。 Seata はロールバック ログを非常に速く削除するため、テーブル内のロールバック ログを確認するには、特定のサービスにブレークポイントを設定して、より明確に確認する必要があります。

ロールバックレコード

要約する

上記では、2PC、3PC、TCC、MQ、Seata の 5 つの分散トランザクション ソリューションについて簡単に紹介し、Seata ミドルウェアの実装についても詳しく説明しました。しかし、どのソリューションを選択する場合でも、プロジェクトに適用する際には注意が必要です。データの一貫性が強い特定のシナリオを除き、可能であれば使用を避ける必要があります。なぜなら、どれだけパフォーマンスが優れていても、プロジェクトが分散トランザクションで覆われると、全体的な効率は数倍低下し、特に同時実行性の高い状況ではそのデメリットが顕著になるからです。

この場合の github アドレス: https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-seata-transaction

<<:  SD-WAN 業界を理解する: WAN クラウド化の観点から SD-WAN を見る

>>:  ガベージコレクションについて話しましょう。

推薦する

クラウドコンピューティングとデータ分析を活用してビジネス開発を促進

今日のダイナミックなビジネス環境において、組織は効率性、俊敏性、価値を高める革新的な方法を常に模索し...

360度検索が百度を打倒する方法

百度は長年にわたり中国の検索分野のリーダーであり、そのルーツは深く、後発企業が百度の地位に挑戦するの...

個人のウェブサイトで収益を上げる方法をご存知ですか?

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービス今は、個人のウェブサイト...

velocihost-512m KVM/10g SSD/1T トラフィック/G ポート/月額 7 USD

Velocihost は設立されてまだ半年ですが、KVM + SSD をベースにした低価格の VPS...

Shark Host(シャークテックコンピュータルーム):高防御サーバー/E3-1270/16gメモリ/32IP/ロサンゼルス/139ドル

Shark Host (sharktech コンピュータ ルーム) の最新ニュース: ロサンゼルス ...

誰かがテンセントミーティングの計算をしたところ、5か月で714億元の社会コストが節約されたことが判明した。

北京大学インターネット発展研究センターが9月1日に発表した「オンライン会議の社会的価値と今後の発展報...

オランダのVPSの推奨。ハイエンドのAS9929/4809と国際ネットワークを区別し、常にあなたに適したものが見つかります

オランダの VPS の推奨: オランダの VPS は苦情に強いものが多く、またオランダはヨーロッパや...

ハイブリッドクラウドが注目されるようになったのはなぜですか?いくつかの主要なクラウドコンピューティングサービスモデルについて議論する

近年、国内のクラウドコンピューティング市場は、複数の業界での徹底的な応用の傾向を示しています。特に、...

Yuehuai SEO: アンカーテキストを使用して高品質の外部リンクを作成するためのヒントについて簡単に説明します

ウェブサイトの最適化は、オンサイト最適化とオフサイト最適化の 2 つの側面に分かれています。その中で...

Vultr が 30 ドルをプレゼントします!早い者勝ちです!

VPS のダークホースである Vultr.com は、長い間注目を集めていません。ブラック フライデ...

SEOの観点から見た360度旅行

今日、偶然、360 Travelのウェブサイトが注目を集める形で立ち上げられたことを発見しました。一...

コンテンツページの最適化を通じてウェブサイトのランキングを向上させる方法

「外部リンクこそが王様」という言葉は、SEO 従事者が常に主張してきた言葉ですが、外部リンクがあらゆ...

ユーザーの検索行動とキーワード分析(パート3)

2 番目の記事では、ロングテールキーワードの方がコンバージョン率が高いことをようやく説明しました。し...

5Gとエッジコンピューティングが企業の新たな常態への対応にどのように役立つか

コロナウイルス危機への対応として、世界中の組織は、世界が正常に戻るか、少なくとも次の正常に戻るまで待...