トランザクションのドキュメントには次のように書かれています。
「トランザクションを廃止し、最終的に削除する場合があります」および「Redisトランザクションで実行できることはすべて、スクリプトでも実行できます」
http://redis.io/topics/transactions
しかし、それはありますか?これに問題があります。
トランザクション内では、複数の変数を監視し、それらの変数を読み取り、それらの変数の一意の状態に基づいて、EXECを呼び出す前に完全に異なる一連の書き込みを行うことができます。その間に何かがこれらの変数の状態に干渉する場合、EXECはトランザクションを実行しません。(これにより、再試行できます。これは完璧なトランザクションシステムです。)
EVALスクリプトではそれができません。このページのドキュメントによると:
「純粋関数としてのスクリプト...スクリプトは常に、同じ入力データセットが与えられた場合に同じ引数で同じRedis書き込みコマンドを評価します。スクリプトによって実行される操作は、スクリプトとして変更される可能性のある非表示の(明示的でない)情報や状態に依存できません。実行は進行するか、スクリプトの異なる実行間で進行します。また、I/Oデバイスからの外部入力に依存することもできません。」
EVALで見られる問題は、スクリプト内でこれらの変数の状態を取得できず、それらの変数の状態に基づいて一意の書き込みセットを作成できないことです。繰り返しますが、「スクリプトは常に、同じ入力データセットが与えられた場合に同じ引数を使用して同じRedis書き込みコマンドを評価します。」したがって、結果の書き込みはすでに決定されており(最初の実行からキャッシュされます)、EVALスクリプトはスクリプト内のGET値を気にしません。実行できる唯一のことは、EVALを呼び出す前にこれらの変数に対してGETを実行し、次にそれらの変数をEVALスクリプトに渡すことですが、ここに問題があります。GETの呼び出しとEVALの呼び出しの間にアトミック性の問題があります。
つまり、トランザクションに対してWATCHを実行するすべての変数、EVALの場合は、代わりにそれらの変数をGETしてから、EVALスクリプトに渡す必要があります。スクリプトのアトミックな性質は、スクリプトが実際に開始されるまで保証されないため、EVALを呼び出してスクリプトを開始する前に、これらの変数をGETする必要があります。これにより、これらの変数の状態がGETと受け渡しの間で変化する可能性があります。 EVALに。したがって、非常に重要な一連のユースケースでは、EVALでは得られないWATCHでのアトミック性の保証があります。
では、重要なRedis機能が失われる原因となるトランザクションの非推奨についての話があるのはなぜですか?または、私がまだ理解していないEVALスクリプトを使用してこれを行う方法は実際にありますか?または、EVALでこれを解決できる機能が計画されていますか?(架空の例:WATCHがEXECで機能するのと同じようにWATCHをEVALで機能させる場合、それは機能する可能性があります。)
これに対する解決策はありますか?または、Redisが長期的に完全にトランザクションセーフではない可能性があることを理解していますか?