この記事では、Redis トランザクションを徹底的に理解し、Redis トランザクションの 2 つのモード (トランザクション モードと Lua スクリプト) を比較します。
正確には、Redis トランザクションには トランザクション モード と Lua スクリプト の 2 つのモードが含まれています。
最初に結論について話しましょう:
Redis のトランザクション モードには次の特徴があります:
しかし、Lua スクリプトには、より実用的なシナリオがあります。これはトランザクションの別の形式であり、ある程度の原子性がありますが、スクリプトがエラーを報告すると、トランザクションはロールバックされません。 Lua スクリプトは分離を確保し、前のステップの結果に応じて後続のステップを完全にサポートできます。 [関連する推奨事項: Redis ビデオ チュートリアル ]
Lua スクリプト モードは、分散ロック、遅延キュー、赤い封筒の取得、その他のシナリオなど、ほぼどこでも使用できます。
Redis トランザクションには次のコマンドが含まれます:
シリアル番号 | コマンドと説明 |
---|---|
1 | MULTI トランザクション ブロックの開始をマークします。 |
2 | EXEC は、トランザクション ブロック内のすべてのコマンドを実行します。 |
3 | DISCARD はトランザクションをキャンセルし、トランザクション ブロック内のすべてのコマンドの実行を放棄します。 |
4 | WATCH key [key ...] トランザクションが実行される前に、この (または複数の) キーが他のコマンドによって使用されているかどうかを監視します。変更された場合、トランザクションは中断されます。 |
5 | UNWATCH WATCH コマンドによるすべてのキーの監視を解除します。 |
トランザクションは 3 つの段階で構成されます:
次に、トランザクションの例を示します。
1 redis> MULTI 2 OK 3 redis> SET msg "hello world" 4 QUEUED 5 redis> GET msg 6 QUEUED 7 redis> EXEC 8 1) OK 9 1) hello world
ご質問がありますか?トランザクションの開始時に Redis キーを変更できますか?
トランザクションが EXEC コマンドを実行する前でも、Redis キーを変更できます。
トランザクションを開始する前に、watch コマンドを使用して Redis キーを監視できます。トランザクションを実行する前にキーの値を変更すると、トランザクションの実行は失敗し、nil が返されます。
上記の例を通じて、watch コマンドは オプティミスティック ロックと同様の効果を達成できます。
2.1 アトミック性
アトミック性とは、トランザクションすべての操作を指します。は完了または未完了のいずれかであり、中間段階で終了することはありません。トランザクションの実行中にエラーが発生した場合は、トランザクションがまったく実行されなかったかのように、トランザクションが開始される前の状態にロールバックされます。 最初の例: EXEC コマンドを実行する前に、クライアントから送信された運用コマンドが構文エラーまたは存在しないコマンドなど、間違っています。1 redis> MULTI 2 OK 3 redis> SET msg "other msg" 4 QUEUED 5 redis> wrongcommand ### 故意写错误的命令 6 (error) ERR unknown command 'wrongcommand' 7 redis> EXEC 8 (error) EXECABORT Transaction discarded because of previous errors. 9 redis> GET msg 10 "hello world"
1 redis> MULTI 2 OK 3 redis> SET msg "other msg" 4 QUEUED 5 redis> SET mystring "I am a string" 6 QUEUED 7 redis> HMSET mystring name "test" 8 QUEUED 9 redis> SET msg "after" 10 QUEUED 11 redis> EXEC 12 1) OK 13 2) OK 14 3) (error) WRONGTYPE Operation against a key holding the wrong kind of value 15 4) OK 16 redis> GET msg 17 "after"
Redis トランザクションは、特定の条件下でのみ特定のアトミック性を持ちます。
2.2 分離
データベースの分離とは、データベースが複数の同時トランザクションで同時にデータの読み取り、書き込み、変更を行えることを意味します。機能と分離により、複数のトランザクションが同時に実行される場合のクロス実行によるデータの不整合を防ぐことができます。 トランザクション分離は、次のようなさまざまなレベルに分割されます。同時シナリオで、トランザクションが相互の干渉を回避できるかどうか 。
トランザクションの実行は、EXEC コマンドが実行される前 と EXEC コマンドが実行された後 の 2 つの段階に分けて、別々に説明できます。
WATCH メカニズムを使用して、オプティミスティック ロックの効果を実現できます。
2.3 永続性
データベースの永続性とは、トランザクションの完了後、データの変更は永続的であることを意味します。システムが失敗しても失われることはありません。 Redis データが永続化されるかどうかは、Redis の永続化構成モードによって異なります。redis トランザクションの耐久性は保証できません。
2.4 一貫性
一貫性の概念は常に混乱を招きます。私が検索した情報では、2 つの異なる定義がありました。まず Wikipedia で一貫性の定義を見てみましょう:
一貫性とは、トランザクションがデータベースを 1 つの有効な状態からのみ取得できることを保証します。データベースに書き込まれるすべてのデータは、制約、カスケード、トリガー、およびそれらの組み合わせを含むすべての定義されたルールに従って有効である必要があります。これにより、不正なトランザクションによるデータベースの破損が防止されますが、トランザクションが正常に実行されることは保証されません。参照整合性により、主キーと外部キーの関係が保証されます。
このテキストでは、一貫性の核心は「constraint」、「 に書き込まれるすべてのデータ」です。データベースは、定義されたすべてのルールに従って有効である必要があります」。
制約を理解するにはどうすればよいですか?以下は、Zhihu の質問 「データベースの内部一貫性と外部一貫性を理解する方法 」からの引用です。Ant Financial の OceanBase R&D 専門家である Han Fusheng が回答しました。
「制約」ユーザーは、データがこの制約またはその制約に従う必要があることをデータベースに伝えます。データが変更されると、データベースはデータが制約を満たしているかどうかを確認します。制約が満たされなくなった場合、変更操作は実行されません。
リレーショナル データベースで最も一般的な 2 つのタイプの制約は、「一意制約」と「整合性制約」です。テーブルに定義された主キーと一意キーにより、指定されたデータ項目が決して繰り返されないことが保証されます。定義された参照整合性により、異なるテーブル内の同じ属性の一貫性も保証されます。
「ACID の一貫性」は非常に使いやすいため、ほとんどのユーザーの血液に溶け込んでいます。ユーザーはテーブルを設計するときに必要な制約を意識的に追加します。データベースもこの制約を厳密に適用します。
したがって、 トランザクションの一貫性は事前定義された制約に関連しており、その制約によって一貫性が確保されることが保証されます。
この文を詳しく見てみましょう:これにより、不正なトランザクションによるデータベースの破損は防止されますが、トランザクションが正しいことは保証されません。
これを書いてもまだ少し混乱している人もいるかもしれませんが、古典的なtransfer のケースを考えてみましょう。
トランザクションを開始します。Zhang San と Li Si の口座の初期残高は両方とも 1,000 元で、残高フィールドには制限はありません。張三は李斯に1200元を送金した。 Zhang San の残高は -200 に更新され、Li Si の残高は 2200 に更新されます。 実際のシナリオではユーザー残高を 0 未満にすることはできないため、アプリケーション レベルから見ると、このトランザクションは明らかに違法ですが、データベースの制約に完全に従っているため、データベース レベルから見ると、このトランザクションはそれでも一貫性は保証されています。 Redis のトランザクションの一貫性とは、Redis トランザクションが実行中にデータベースの制約に従い、違法または無効なエラー データが含まれていないことを意味します。 3 つの例外シナリオについてそれぞれ説明します。一貫性の核心は制約であるというセマンティクスに基づいて、Redis トランザクションは一貫性を保証できます。
原子性、分離性、耐久性はデータベースのプロパティですが、(ACID の意味での) 一貫性はデータベースのプロパティです。アプリケーションのプロパティ。アプリケーションは一貫性を達成するためにデータベースのアトミック性と分離プロパティに依存する場合がありますが、それはデータベースだけで決まるわけではありません。したがって、文字 C は実際には ACID に属しません。原子性、分離性、耐久性はデータベースの特性ですが、一貫性 (ACID の意味で) はアプリケーションの特性です。アプリケーションは一貫性を達成するためにデータベースの原子性と分離特性に依存する場合がありますが、これはデータベースだけに依存するわけではありません。したがって、文字 C は ACID に属しません。 多くの場合、私たちが苦労している一貫性は、実際には
現実世界との整合性を指します. 現実世界における一貫性は、物事の究極の目標です。
現実世界で一貫性を実現するには、次の点を満たす必要があります:2.5 トランザクションの特性
通常、Redis はインメモリ データベースと呼ばれており、従来のリレーショナル データベースとは異なります。より高いパフォーマンスとより速い書き込み速度を提供するために、設計および実装レベルでいくつかのバランスが取られており、トランザクションの ACID を完全にはサポートできません。
Redis トランザクションには次の特性があります:
エンジニアリングの観点から、トランザクション操作の各ステップが前のステップから返された結果に依存する必要があると仮定すると、監視を通じてオプティミスティック ロックを実装する必要があります。
3.1 はじめに
Lua は標準 C で書かれています。コードはシンプルで美しく、ほぼすべてのオペレーティング システムとプラットフォームでコンパイルして実行できます。 Lua スクリプトは C/C コードで簡単に呼び出すことができ、C/C 関数を順番に呼び出すこともできるため、Lua はアプリケーションで広く使用されています。
Lua スクリプトはゲーム分野で大きな話題を呼び、有名な「Westward Journey II」や「World of Warcraft」ではどちらも Lua スクリプトが広く使用されています。 Lua スクリプトは、Openresty や Kong など、Java バックエンド エンジニアが接触した API ゲートウェイで見ることができます。
Redis バージョン 2.6.0 以降、Redis の組み込み Lua インタープリターは Redis で Lua スクリプトを実行できるようになりました。
Lua スクリプトを使用する利点:
コマンドと説明 | |
---|---|
2 | |
3 | |
4 | |
5 | |
6 | |