ホームページ  >  記事  >  高い同時実行性の下でインターフェイスの冪等性を確保する方法

高い同時実行性の下でインターフェイスの冪等性を確保する方法

Java学习指南
Java学习指南転載
2023-07-26 16:58:48864ブラウズ

1. 背景

実際のシステムには多くの操作があり、それらは何度実行されても同じ効果を生み出すか、同じ結果を返すはずです。

例:

  1. フロントエンドは選択されたデータを繰り返し送信し、バックグラウンドはこのデータに対応する応答結果を 1 つだけ生成する必要があります。

  2. 支払いリクエストを開始するとき、ユーザー アカウントは 1 回だけ差し引かれる必要があります。ネットワークの再送信またはシステム バグの再発行が発生した場合、金額は 1 回だけ差し引かれる必要があります。

  3. メッセージの送信は 1 回だけにしてください。同じテキスト メッセージをユーザーに送信すると、ユーザーは泣きます;

  4. ビジネスを作成するとき1 つのビジネス リクエストで 1 つしか作成できず、複数作成すると大きな問題が発生します。

やその他多くの重要な状況では、これらのロジックをサポートする冪等機能が必要です。

2. 冪等性の概念

冪等性 (べき等、冪等) は、抽象代数でよく見られる数学およびコンピューター サイエンスの概念です。

プログラミングにおける冪等操作の特徴は、複数の実行の影響が 1 回の実行の影響と同じであることです。冪等関数または冪等メソッドは、同じパラメータを使用して繰り返し実行でき、同じ結果が得られる関数です。

これらの関数はシステムの状態に影響を与えることがなく、繰り返しの実行によるシステムの変化を心配する必要はありません。たとえば、「getUsername() 関数と setTrue()」関数はべき等関数です。

より複雑な操作の冪等性の保証は、一意のトランザクション番号 (シリアル番号) を使用することで実現されます。

私の理解: 冪等性は操作です。何度実行しても、その効果と結果は変わりません。返された結果は同じです。同じです

3. 技術的解決策

1. クエリ操作 1 回または複数回クエリを実行した場合、クエリ結果は次のようになります。データが変更されていない場合も同様です。 Select は自然な冪等操作です。

2. 削除操作 削除操作も冪等であり、1 回の削除と複数回の削除によりデータが削除されます。 (返される結果は異なる場合があることに注意してください。削除されたデータが存在しない場合は 0 が返されます。削除されたデータが複数ある場合は、複数の返された結果が返されます。)

3. 一意新しいダーティ データを防ぐためのインデックス 例: Alipay の資本口座。Alipay にはユーザー アカウントもあります。各ユーザーは 1 つの資本口座しか持てません。1 人のユーザーに対して複数の資本口座が作成されるのを防ぐにはどうすればよいですか? 次に、一意のインデックスを追加します。資本勘定テーブルにユーザー ID を追加できるようにするため、新しいユーザーは資本勘定を正常に記録します。

キー ポイント: 一意のインデックスまたは一意の結合インデックスを使用して、新しいデータのダーティ データを防止します (テーブルに一意のインデックスがあり、同時に新しいデータが追加されたときにエラーが報告された場合、再度クエリを実行します。それだけです。データはすでに存在しているはずです。結果を返すだけです)

4. 防止するためのトークン メカニズムページの繰り返し送信

ビジネス要件:

ページ上のデータは 1 回のみクリックして送信できます

発生原因: 繰り返しのクリック、ネットワークの再送信、または nginx の再送信などにより、

解決策: クラスター環境: トークンと redis を使用します (redis はシングルスレッドなので、処理をキューに入れる必要があります) 単一 JVM 環境: トークンと redis またはトークンと jvm メモリを使用します

処理プロセス:

  1. データを送信する前に、サービスからトークンを申請する必要があります。トークンは、redis または jvm メモリに配置されます。トークンは、次の期間有効です。

  2. トークンは送信後にバックグラウンドで検証されます。同時にトークンを削除し、新しいトークンを生成して

トークンの機能を返します:

適用するには、一度だけ有効で、現在のフローを制限できます

注: redis には、トークンを判断するために削除操作を使用する必要があります。削除が成功した場合は、トークンの検証に合格したことを意味します。トークンを検証するために select delete を使用すると、同時実行の問題が発生します。

5 の使用は推奨されません。悲観的ロック データの取得ロックと取得の時間

select * from table_xxx where id='xxx' for update;

注: id フィールドは主キーまたは唯一のインデックスでなければなりません。そうしないとテーブルがロックされ、人が死ぬことになります

悲観的ロックを使用する 通常、トランザクションと併用されますが、データのロック時間が非常に長くなる可能性があるため、実際の状況に応じて

#6 を選択してください。 table はデータが更新された瞬間にロックされ、それ以外の時にはテーブルにロックされないため、悲観的ロックよりも効率的です。

オプティミスティック ロックは、バージョンまたはその他のステータス条件を通じてさまざまな方法で実装できます:

1. バージョン番号による実装

update table_xxx set name=#name#,version=version+1 where version=#version#

以下に示すように (インターネットから):

高い同時実行性の下でインターフェイスの冪等性を確保する方法
2. 条件付き制限

update tablexxx set avaiamount=avaiamount-#subAmount# where avaiamount-#subAmount# >= 0

Requirement:quality-#subQuality# >= により、このシナリオはバージョン番号を使用せず、のみを使用する場合に適しています。更新はデータのセキュリティ検証を目的としています。在庫モデル、シェア控除、ロールバックシェアに適しており、より高いパフォーマンスを備えています

注意:乐观锁的更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,上面两个sql改成下面的两个更好

update tablexxx set name=#name#,version=version+1 where id=#id# and version=#version#update tablexxx set avaiamount=avaiamount-#subAmount# where id=#id# and avai_amount-#subAmount# >= 0

7. 分布式锁 还是拿插入数据的例子,如果是分布是系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定

这时候可以引入分布式锁,通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁

这样其实是把多线程并发的锁的思路,引入多多个系统,也就是分布式系统中得解决思路。

要点:某个长流程处理过程要求不能并发执行,可以在流程执行之前根据某个标志(用户ID+后缀等)获取分布式锁,其他流程执行时获取锁就会失败,也就是同一时间该流程只能有一个能执行成功,执行完成后,释放分布式锁(分布式锁要第三方系统提供)

8. select + insert 并发不高的后台系统,或者一些任务JOB,为了支持幂等,支持重复执行,简单的处理方法是,先查询下一些关键数据,判断是否已经执行过,在进行业务处理,就可以了

注意:核心高并发流程不要用这种方法

9. 状态机幂等 在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机(状态变更图),就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机

ステート マシンが既に次の状態にあり、この時点で前の状態への変更が発生した場合、理論的には変更することはできませんが、この場合、有限ステート マシンの冪等性が保証されます。

注: 注文やその他のドキュメント タイプのビジネスには長い状態フローがあります。状態マシンを深く理解する必要があります。これは、ビジネス システムの設計能力を向上させるのに非常に役立ちます。

10. 外部インターフェイスを提供する API は冪等性をどのように保証しますか

たとえば、UnionPay が提供する支払いインターフェイス: 販売者が支払いリクエストを送信するために販売者にアクセスする必要がある場合、それに付随します。 by: ソース ソース、シーケンス シリアル番号

ソース シーケンスはデータベース内にあります。複数の支払いを防ぐために内部で一意のインデックスが作成されます (同時実行の場合、処理できるリクエストは 1 つだけです)

キー ポイント冪等呼び出しをサポートする外部インターフェイスを提供するために、インターフェイスには渡す必要がある 2 つのフィールドがあります。1 つはソース、もう 1 つはソースのシリアル番号シーケンスです。これら 2 つのフィールドは結合として使用されます。プロバイダーシステムの一意のインデックス

このように、サードパーティが呼び出した場合、まず自分のシステムで処理されているかどうかを確認します。処理されていれば、対応する処理結果が返されます。が処理されていない場合は、対応する処理が実行され、結果が返されます。

べき等でフレンドリーであるためには、まずビジネスが処理されたかどうかをクエリする必要があることに注意してください。クエリせずにビジネス システムに直接挿入すると、エラーが報告されますが、実際には処理されています。加工された。

まとめ

冪等性は、資格のあるプログラマーの遺伝子である必要があります。システムを設計するとき、特に Alipay、銀行、インターネット金融会社など、すべてお金が関係する企業では、冪等性が最優先に考慮されます。システムの効率性やデータの正確性が求められるため、過剰な控除や過払いなどの問題が発生してはなりませんが、対応が難しく、ユーザーエクスペリエンスも良くありません。

以上が高い同時実行性の下でインターフェイスの冪等性を確保する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はJava学习指南で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。