この記事では、Redis のデータ型に関する関連知識を提供します。主に、一般的なデータ型の使用シナリオに関連する問題を紹介します。皆様のお役に立てれば幸いです。
# 推奨学習:
Redis 学習チュートリアル
Redis データ型と使用シナリオ
- Redis データ型と使用シナリオ
他の KV データベースと比較した Redis の主な特徴の 1 つは、豊富なデータ型をサポートしていることです。合計 5 つのデータ型をサポートしており、これら 5 つのデータ型とその使用シナリオ、および内部実装を以下に 1 つずつ紹介します。
- string
はじめに: 文字列型は Redis の最も基本的なデータ型であり、最も一般的に使用されるデータ型であり、Redis の唯一のデータ型として多くのプレーヤーでも使用されています。レディス。 Redis では文字列型はバイナリ セーフです。つまり、文字列値はバイナリ文字列を考慮し、特定の形式を考慮しません。これを使用して、文字列を json 形式または JPEG 画像形式で保存できます。
#文字列の長さを取得する コンテンツを文字列に追加する 文字列を設定および取得する特定のコンテンツ -
#文字列の特定の部分を設定および取得する
-
一連の文字列の内容をバッチで設定する
-
一般的に使用されるコマンド: set、get、decr、incr、mget など。
-
アプリケーション シナリオ:
(1) MySQL にフィールドの値を格納する
キーをテーブル名: 主キー名: 主キー値: として設計します。フィールド名
(2) ストレージ オブジェクト
文字列型はあらゆる形式の文字列をサポートします。最も一般的に使用されるのは、json またはその他のオブジェクトでフォーマットされた文字列を格納することです。 (このシナリオではハッシュ データ型を使用することをお勧めします)
set user:id:1 '[{"id":1,"name":"zj","email":"156577812@qq.com"},{"id":1,"name":"zj","email":"156577812@qq.com"}]'
ログイン後にコピー
(3) 自動インクリメント ID の生成
Redis の文字列型の値が整数形式の場合、Redis はそれを自動的に処理できます。インクリメント (incr) およびデクリメント (decr) 演算。すべての Redis 操作はアトミックであるため、複数のクライアントが接続するときに発生する可能性のあるトランザクションの問題を心配する必要はありません。
ハッシュ-
はじめに: ハッシュは、文字列と文字列値の間のマッピングを保存します。ハッシュはオブジェクトのさまざまな属性をマップに保存し、オブジェクトの特定の属性のみを読み取り/更新できます。この方法では、長すぎるプロパティをそのままにしておくことができ、さらに、異なるモジュールは相互の同時実行による上書き競合を引き起こすことなく、必要なプロパティのみを更新できます。
一般的に使用されるコマンド: hget、hset、hgetall など。
アプリケーション シナリオ:
ユーザー情報などの構造化データを保管します。 Memcached や CKV では、ユーザーのニックネーム、年齢、性別、ポイントなどのユーザー情報については、まずシリアル化して文字列値として保存する必要があります。 、通常は、値が取得されて逆シリアル化された後、項目の値が変更され、その後シリアル化されて保存されます。これはオーバーヘッドが増加するだけでなく、同時操作が可能な状況にも適していません (たとえば、2 つの同時操作ではポイントの変更が必要です)。 Redis のハッシュ構造を使用すると、データベース内の属性を更新するのと同じように、特定の属性値のみを変更できます。以下に示すように、
Key はユーザー ID、value は Map、この Map の key はメンバーの属性名、value は属性値というように、変更とアクセスが可能になります。データの内部マップのキー (内部マップのキーは Redis ではフィールドと呼ばれます)、つまり、対応する属性データはキー (ユーザー ID) フィールド (属性ラベル) を通じて操作できます。データを繰り返し保存する必要がなく、シリアル化や同時実行が発生することもありません。制御の問題を修正します。
ただし、Redis はすべての属性データを直接取得するためのインターフェイス (hgetall) を提供していますが、内部 Map のメンバーが多数ある場合、内部 Map 全体を走査する必要があることに注意してください。 Redis シングルスレッド モデル このため、このトラバーサル操作には時間がかかり、他のクライアントからのリクエストにまったく応答しなくなるため、特別な注意が必要です。
インデックスの構築に使用できます。たとえば、ユーザー オブジェクトは、ID に加えて、名前でもクエリする必要がある場合があります。キー user:name:id を使用してハッシュを構築できます。ユーザー オブジェクトを挿入するとき (set user:101{"id":101) ,"name":"calvin ”}) ちなみに、このハッシュにエントリを挿入します (hset user:name:id calvin 101)。このとき、calvin はハッシュのキーとして使用され、値は次のとおりです。 101.名前でクエリを実行する場合は、hgetuser:name:id calvin を使用して、calvin という名前のキーから ID を取得します。特定のデータを検索するために複数のインデックスを使用する必要がある場合は、1 つのハッシュ キーを使用して、インデックス値の格納に複数の文字列キーを使用することを避けることができます。
HINCRBY は idmaker の実装にも使用できます。文字列型の idmaker と比較すると、各型にキーが必要ですが、ハッシュ型は 1 つのキーだけで済みます。
ハッシュデータ型は、上記のデータを格納する際に文字列型に比べて柔軟性が高く、高速であるという利点があります。具体的には、文字列型で格納する場合、json形式に変換して解析する必要があります。文字列でなくても変換が必要ですが、メモリのオーバーヘッドという点では、やはりハッシュの方が有利です。
実現方法:
Value に対応する Redis ハッシュは実際には HashMap です。ここには 2 つの異なる実装があります。ハッシュのメンバーが少ない場合、Redis はメモリを節約するために、ハッシュの代わりに 1 次元配列のようなメソッドを使用してコンパクトに格納します。本物のHashMapを使用する構造で、対応する値redisObjectのエンコードはzipmapで、メンバー数が増えると自動的に本物のHashMapに変換され、エンコードはhtとなります。
はじめに:
リストは、挿入順にソートされた文字列のリンクされたリストです。先頭と末尾に新しい要素を挿入できます (二重リンク リストによって実装され、両端に要素を追加する時間計算量は O(1) です)。要素を挿入するとき、キーが存在しない場合、redis はキーの新しいリンク リストを作成します。リンク リスト内のすべての要素が削除されると、キーも redis から削除されます。
一般的に使用されるコマンド: lpush、rpush、lpop、rpop、lrange など。
適用シナリオ:
Twitterのフォローリストやファンリストなどの各種リスト、最新ニュースランキング、各記事へのコメントなどもRedisのリスト構造を利用して実装可能。
メッセージ キューでは、リストの PUSH 操作を使用してタスクをリストに保存し、ワーカー スレッドが POP 操作を使用して実行するタスクを取り出します。ここのメッセージ キューには ACK メカニズムがありません。コンシューマが Pop にタスクを渡し、完了する前にクラッシュしたらどうなるでしょうか?解決策の 1 つは、追加のソート セットを追加することです。配布するときは、リストとソート セットの両方に同時に送信します。配布時間はスコアとして使用されます。ユーザーはタスクを完了した後、ZREM を使用して削除する必要があります。ソート セット内のジョブを定期的に削除し、タイムアウトになった未完了のタスクを削除してリストに戻します。もう 1 つのアプローチは、各ワーカーに追加のリストを追加し、タスクをポップアップするときに RPopLPush を使用し、同時にジョブをワーカー自身のリストに入れ、完了時に LREM を使用してジョブを削除することです。クラスター管理者 (動物園の飼育員など) がワーカーが死亡したことを発見した場合、ワーカーのリストの内容はメイン リストに戻されます。
LRANGEを使用すると、リストコンテンツのページング機能を簡単に実現できます。
最新の N データを取得する操作: LPUSH を使用して、コンテンツ ID を挿入し、リストの先頭にキーワードとして格納します。 LTRIM は、リスト内の項目数を最大 5000 に制限するために使用されます。ユーザーが取得する必要があるデータの量がこのキャッシュ容量を超える場合は、リクエストをデータベースに送信する必要があります。
実装方法:
Redis リストの実装は双方向のリンク リストであり、逆方向の検索とトラバーサルをサポートでき、操作がより便利ですが、追加のメモリ オーバーヘッドが発生します。 . Redis 内部 送信バッファ キューなどを含む多くの実装でも、このデータ構造が使用されます。
はじめに: これは順序のないセットです。セット内の要素には順序がありません。繰り返します。重複した要素を Set に入れると、それらは自動的に削除されます。
一般的なコマンド:
sadd、spop、smembers、sunion など。
アプリケーション シナリオ:
一部のリストは重複を排除する必要があり、set はメンバーがセット コレクションに含まれているかどうかを判断するための重要なインターフェイスを提供しますが、これはリストでは提供できないものです。
いくつかの集合データを保存できます。たとえば、Weibo アプリケーションでは、ユーザーのすべてのフォロワーをコレクションに保存したり、ユーザーのすべてのファンをコレクションに保存したりできます。 Redis は、コレクションの交差、和集合、差分などの操作も提供しており、共同注意、共通の設定、2 級友人などの機能を実装するのに非常に便利です。上記のすべてのコレクション操作では、別のコマンドを使用することもできます。結果をクライアントに返すか、新しいコレクションに保存します。別の例として、QQ には「フレンドタグ」と呼ばれるソーシャル機能があり、「ビッグビューティー」、「大物」、「Ouba」などの友達をタグ付けできます。ここでは、各ユーザーのタグをコレクション内に保存することもできます。
特定のページにアクセスした特定の登録ユーザーまたは IP アドレスの数を知りたい場合は、 SADD page:day1:
を実行できます。特定のユーザーの数を知るには、SCARD page:day1: を使用します。特定のユーザーがこのページにアクセスしたかどうかをテストする必要がありますか?システムメンバー ページ:day1:。 実装方法: set の内部実装は、値が常に null である HashMap です。実際、ハッシュを計算することですぐにソートされます。これは、set が次のことを判断するために提供できるものでもあります。メンバーはセット内の Reason です。
はじめに: セットと比較して、順序付きセットは、要素を配置するときに提供する必要があります。要素のスコアをスコアに基づいて自動的に並べ替えることができます。 一般的に使用されるコマンド: zadd、zrange、zrem、zcard など 使用シナリオ: 順序付けされた重複しないセット リストを保存する, たとえば、Twitterの公開タイムラインを公開時刻をスコアとして保存しておくと、取得時に自動的に時刻順に並び替えられるようになります。 重み付けされたキューを作成できます。たとえば、通常のメッセージのスコアは 1、重要なメッセージのスコアは 2 です。その後、ワーカー スレッドは、ワーカー スレッドの逆の順序で作業タスクを取得することを選択できます。スコア。重要なタスクに優先順位を付けます。
期限切れアイテムの処理: UNIX 時間をキーとして使用して、リストを時間順に並べ替えます。 current_time と time_to_live を取得して、期限切れのアイテムを見つけるという難しいタスクを完了します。別のバックグラウンド タスクは、ZRANGE...WITHSCORES を使用して、期限切れのエントリをクエリし、削除します。
実装方法:
Redis ソート セットは内部的に HashMap とスキップ リスト (SkipList) を使用して、データの保存と順序付けを保証します。HashMap はメンバーからスコアへのマッピングを配置し、すべてのメンバーがスキップされます。テーブルに格納され、ソートの基準は HashMap に格納されたスコアです。ジャンプ テーブル構造を使用すると、より高い検索効率が実現でき、実装も比較的簡単です。
推奨される学習: Redis ビデオ チュートリアル
以上がRedis データ型と使用シナリオの概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。