他のデータベースに精通しているユーザーがRedisを試すときに混乱することが多いのは、データベースの可視性がないことです。ほら、(潜在的に)何百万ものキーを持つことができる、プレーンでフラットなキースペースだけです。したがって、このキースペースを安価に反復処理する機能は、データベースの内容に精通するために非常に重要になります。
Redisキースペースを反復処理することで、他の重要なユースケースが頭に浮かぶことがあります。
- 特定のパターンに一致するガベージコレクションまたはキーのクリーンアップ
- データの移動とスキーマの変更、または特定のセットキーの別のデータ構造への移動
- デバッグ、データサンプリング、データ修正、または最近の変更によって混乱したすべてのキーの検索と修正
この投稿では、Redisで利用できるさまざまなキースペースの反復オプションについて詳しく説明します。
O(N)イテレータ:キー
Redis KEYSコマンドは、パターンに一致するデータベース内のすべてのキー(またはキースペース内のすべてのキー)を返します。ハッシュに格納されているすべてのフィールドをフェッチするための同様のコマンドは、HGETALLであり、SMEMBERSのメンバーをフェッチするためのすべてのコマンドです。 Redis自体のキーは、辞書(別名ハッシュテーブル)に保存されます。 KEYSコマンドは、このディクショナリを反復処理し、パターンに一致するすべてのものを単一の配列応答として送信することで機能します。他のコマンドも同様に機能します。
このような操作のパフォーマンスは、コレクションのサイズ、つまりO(N)によって異なります。したがって、キーの数が多い本番環境では、KEYSの使用は強くお勧めしません。 Redisはシングルスレッドであり、この反復中にブロックされるため、他の操作がブロックされます。したがって、KEYSは、デバッグや、パフォーマンスが問題にならないその他の特別な場合(データベースをオフラインにしてデータ修正を適用する場合など)にのみ使用する必要があります。このアルゴリズムについて覚えておくべきもう1つの重要な点は、一致するすべてのキーを1つの応答として一緒に送信することです。これは、キースペースが小さい場合に非常に便利ですが、大きなキースペースでは複数の問題が発生します。ただし、KEYSは、独自の開発環境の開発者の間で人気のあるコマンドです。
実行中のキー:
127.0.0.1:6379[1]> MSET one 1 two 2 three 3 four 4 OK # All the keys 127.0.0.1:6379[1]> keys * 1) "four" 2) "three" 3) "two" 4) "one" # keys that begin with the letter 't' 127.0.0.1:6379[1]> keys t* 1) "three" 2) "two" # keys that have a 'ee' in them 127.0.0.1:6379[1]> keys *ee* 1) "three"
カーソルベースのイテレータ:SCAN
SCANとその姉妹コマンドであるSSCAN(セットの場合)、HSCAN(ハッシュの場合)、およびZSCAN(ソートされたセットの場合)は、Redisデータ構造を反復処理するためのカーソルベースのアプローチを提供します。これらは2.8.0以降Redisで利用可能です。
キーは増分反復で返され、反復ごとに一定の時間が保証されます。カーソル(この場合は整数)は、反復が初期化され、更新されたカーソルが返され、反復ごとに返されます。反復サイクルは、SCANリクエストでカーソルが0に設定されたときに始まり、サーバーから返されるカーソルが0になったときに終了します。Redisアーキテクチャのニュアンスとカーソルアルゴリズムの実装により、このアプローチのいくつかの特徴があります。
>- 完全な反復では、完全な反復の開始から終了まで、コレクションに存在していたすべての要素が常に取得されます。
- 完全な反復では、完全な反復の開始から終了まで、コレクションに存在しなかった要素が返されることはありません。
- 指定された要素が複数回返される場合があります。重複した要素の場合を処理するのはアプリケーション次第です
- 完全な反復中にコレクションに常に存在しなかった要素が返されるかどうかは不明です。未定義です。
- 各カウント中に返される要素の数はさまざまであり、0にすることもできます。ただし、サーバーがカーソル値0を返すまで、反復は完了しません。
- COUNT オプションを使用して、各反復で返される要素の数を制限できます。デフォルト値は10です。ただし、これは単なる提案と見なされ、すべての場合に強制されるわけではありません。 COUNT値は、反復呼び出しごとに変更できます。
- 一致 オプションを使用すると、KEYSコマンドで許可されているようなパターンを指定できます。
- サーバー側では、カーソルの実装は完全にステートレスです。これにより、(潜在的に)無限の反復を並行して開始できます。また、反復が最後まで継続し、いつでも停止できることを保証する必要はありません。
その特殊性にもかかわらず、SCANは非常に便利なコマンドであり、ほとんどのユースケースでキースペースの反復を選択するための適切なコマンドです。
SCANは非常に便利なコマンドであり、#RedisClick To Tweet でキースペースの反復を選択するための適切なコマンドです。実行中のSCAN
127.0.0.1:6379[1]> flushdb OK 127.0.0.1:6379[1]> keys * (empty list or set) 127.0.0.1:6379[1]> debug populate 33 OK 127.0.0.1:6379[1]> scan 0 COUNT 5 1) "4" 2) 1) "key:1" 2) "key:9" 3) "key:13" 4) "key:29" 5) "key:23" 127.0.0.1:6379[1]> scan 4 1) "42" 2) 1) "key:24" 2) "key:28" 3) "key:18" 4) "key:16" 5) "key:12" 6) "key:2" 7) "key:6" 8) "key:31" 9) "key:27" 10) "key:19" 127.0.0.1:6379[1]> scan 42 1) "9" 2) 1) "key:3" 2) "key:4" 3) "key:20" 4) "key:8" 5) "key:32" 6) "key:5" 7) "key:26" 8) "key:10" 9) "key:21" 10) "key:14" 127.0.0.1:6379[1]> scan 9 COUNT 100 1) "0" 2) 1) "key:25" 2) "key:30" 3) "key:22" 4) "key:17" 5) "key:15" 6) "key:0" 7) "key:11" 8) "key:7"
フードの下
SCAN(およびその姉妹コマンド)がスキャンスルーに使用するアルゴリズムは興味深いものであり、上記で説明したコマンドの特性の一部につながります。 Antirezは、彼のブログ投稿でそれを高レベルで説明し、実装(関数dictScan)の上のコメントで(少し良く)説明されています。詳細に説明すると、この投稿が長くなりすぎるため、その意味を明確にするために十分な説明を行います。
- ほとんどのRedisデータ構造は、内部的に辞書として表されます(ソートされたセットの場合は少なくとも部分的に)。これらは、衝突の連鎖を伴う2の累乗サイズのハッシュテーブルとして実装されます。ここでカーソルベースの反復アルゴリズムを作成する際の課題は、(APIの)単純さと速度のRedisの原則を犠牲にすることなく、ハッシュの拡大と縮小に対処できるようにすることです。
- SCANは基本的に、反復ごとに一連のハッシュバケットをスキャンし、それらのパターンに一致する要素を返します。バケットの固定リストのみを参照するため、反復によって値がまったく返されない場合があります。
- 返されるカーソルは、基本的に、繰り返されるハッシュテーブルへのオフセットです。ハッシュテーブルのプロパティとともにオフセットを増やしながら、オフセットの上位レベルのビットを巧妙に操作することにより、ハッシュテーブルの拡大と縮小(つまり、再ハッシュ)を処理します。このアプローチの意味するところは、反復中に追加された新しい要素が返される場合と返されない場合があるということです。ただし、カーソル自体は、ハッシュテーブルのサイズを変更したときに再起動する必要はありません。
- 特定のバケットに一度だけアクセスし、そのすべてのキーを一度に返す必要があります。これも、ハッシュのサイズ変更(つまり、再ハッシュ)によって反復の進行が複雑にならないようにするためです。ただし、これにより、COUNT引数は厳密に強制できなくなります。
- 上記のアプローチはサーバー側では完全にステートレスであるため、基本的には、メモリ使用量を増やすことなく、反復を停止したり、大量の反復を並行して開始したりできることを意味します。
概要
高レベルでは、Redisキースペースを反復処理するために2つの選択肢があります。
- パフォーマンスが問題にならない場合、またはキースペースのサイズが適切な場合は、KEYSを使用します。
- それ以外の場合は、SCANを使用してください。
Redis™*のホスティングがサポートされるようになったことをご存知ですか?自分のクラウドアカウントの安全性でRedis™のフルマネージドホスティングを取得し、Redis™のデプロイにAWS/Azureクレジットを活用します。