更新: 以下は、3.2までのRedisバージョンに適用されます。そのバージョンから、効果ベースのレプリケーションは非決定論の禁止を解除し、すべての賭けがオフ(またはオン)になります。
SCAN
を混合することはできません(混合すべきではありません)。 前者の応答は、サーバープロセスに固有の内部Redisデータ構造に依存しているため、スクリプト内の任意の書き込みコマンドを含むコマンドファミリー。言い換えると、2つのRedisプロセス(マスターとスレーブなど)が同じ応答を返すことは保証されていません(したがって、Redisレプリケーションコンテキスト(操作ではなくステートメントベース)では、それが壊れます)。
Redisは、書き込みコマンド(DEL
など)をブロックすることで、このようなケースから身を守ろうとします。 )ランダムコマンドの後に実行された場合(例:SCAN
だけでなく、TIME
、SRANDMEMBER
および同様)。それを回避する方法はあると思いますが、それを実行しますか?システムの動作が定義されていない未知の領域に入ることになります。
代わりに、ランダムな読み取りと書き込みを混在させてはならないという事実を受け入れ、問題を解決するための別のアプローチ、つまり、アトミックな方法でパターンに従って一連のキーを削除することを考えてみてください。
まず、要件のいずれかを緩和できるかどうかを自問してください。アトミックである必要がありますか?原子性とは、(最終的な実装に関係なく)削除の期間中Redisがブロックされ、操作の長さがジョブのサイズ(つまり、削除されるキーの数とその内容[大きなセットを削除することはたとえば、短い文字列を削除するよりもコストがかかります])。
アトミック性が必須ではない場合は、定期的/怠惰にSCAN
小さなバッチで削除します。必須の場合は、基本的に邪悪なKEYS
をエミュレートしようとしていることを理解してください。 コマンド:)しかし、パターンについての予備知識があれば、もっとうまくやることができます。
アプリケーションの実行時にパターンがわかっていると仮定すると、関連するキーを収集し(たとえば、セット内で)、その収集を使用して、キースペース全体を調べるよりも効率的なアトミックでレプリケーションセーフな方法で削除を実現できます。 。
ただし、最も「難しい」問題は、原子性を確保しながらアドホックパターンマッチングを実行する必要がある場合です。その場合、問題は、キースペースのパターンでフィルタリングされたスナップショットを取得し、その直後に一連の削除を取得することになります(データベースがブロックされている間)。その場合、KEYS
を非常にうまく使用できます Luaスクリプト内で、最高のものを期待してください...(ただし、SHUTDOWN NOSAVE
に頼ることができることを十分に理解しています。 非常に迅速に:P)。
最後の最適化は、キースペース自体にインデックスを付けることです。両方のSCAN
およびKEYS
基本的に全表スキャンなので、そのテーブルにインデックスを付けるとしたらどうでしょうか。トランザクション中に照会できるキーの名前のインデックスを保持することを想像してください。おそらく、ソートされたセットと辞書式順序(HT @TwBert )を使用できます。 )パターンマッチングのニーズのほとんどを排除します。しかし、かなりのコストがかかります...複式簿記(各キーの名前のコストをRAMとCPUに保存する)を行うだけでなく、アプリケーションを複雑にする必要があります。なぜ複雑さを加えるのですか?このようなインデックスを実装するには、アプリケーション層(および場合によっては他のすべてのLuaスクリプト)で自分で維持する必要があるため、インデックスも更新するトランザクションで、Redisへの各書き込み操作を慎重にラップします。
あなたがそれをすべてやったと仮定すると(そして、バグの複雑さの可能性の追加、Redis、RAMとCPUの書き込み負荷の少なくとも2倍、スケーリングの制限などの明らかな落とし穴を考慮に入れて...)あなたは自分自身を軽くたたくことができます肩を並べて、Redisを設計されていない方法で使用したことを祝福します。今後のバージョンのRedisには、この課題に対するより優れたソリューションが含まれる場合と含まれない場合があります( @TwBert-RCP / contribを共同で実行し、Redisを少しハックしたいですか? )、これを試す前に、元の要件を再考し、Redisを正しく使用していることを確認することを強くお勧めします(つまり、データアクセスのニーズに応じて「スキーマ」を設計します)。