ホームページ  >  記事  >  データベース  >  Redis データ型とアプリケーション シナリオ

Redis データ型とアプリケーション シナリオ

angryTom
angryTomオリジナル
2020-02-13 13:23:368270ブラウズ

Redis データ型とアプリケーション シナリオ

redis データ型とアプリケーション シナリオ

Redis は、文字列 (文字列)、ハッシュ (ハッシュ)、リスト (リスト) の 5 つのデータ型をサポートします。 、set(セット)、zset(ソートセット:順序付きセット)です。

1. 文字列

はじめに: 文字列データ型は、最も一般的に使用される単純なキー/値型であり、通常のキー/値ストレージはこのカテゴリに分類できます。 。 value には文字列だけでなく数値も指定できます。バイナリ セーフであるため、画像ファイルの内容を文字列として保存できます。 Redis の文字列は、memcached の現在の機能を完全に実現でき、より効率的です。 Memcached と同じ get、set、incr、decr およびその他の操作を提供することに加えて、Redis は次の追加操作も提供します:

1. 文字列の長さの取得

2. Append文字列 Content

3 に設定します。文字列の特定の内容を設定および取得します。

4. 文字列の特定のビットを設定および取得します。

5. シリーズを設定します。バッチ 文字列の内容

一般的なコマンド: set、get、decr、incr、mget など。

アプリケーション シナリオ:

1. Memcached と CKV が適用されるすべてのシナリオ。文字列と数値には直接アクセスします。構造化データは最初にシリアル化してから値に設定する必要があるため、値を取得した後に逆シリアル化が必要になります。

2. INCR、INCRBY、DECR、DECRBY、および Redis のその他の命令を使用して、アトミック カウントの効果を実現できます。つまり、ビジネス統計集計要件を実現するために使用できます。また、グローバルに一意の ID を生成する idmaker の実装にも使用できます。

3. セッションキーを保存し、分散セッションシステムを実装します。 Redis キーは、セッション キーの自動有効期限を実現するために使用される有効期限を簡単に設定できます。 skey を検証するときは、最初に uid に基づいて対応する redis にルーティングします。skey を取得できない場合は、skey の有効期限が切れているため、再度ログインする必要があります。skey が取得されて検証に合格した場合は、有効期限が切れます。空の時間をアップグレードすることができます。

4. Set nx または SetNx、キーが存在しない場合にのみ設定されます。これはマスターの選択や分散ロックの実装に使用できます。すべてのクライアントは常に SetNx マスター myName を使用してマスターに登録しようとし、成功したクライアントは常に Expire を使用して有効期限を更新します。マスターが死亡すると、キーは無効になり、残りのノードで新しいラウンドのスナッチが発生します。

5. redis2.6 でサポートされる Lua スクリプトを使用すると、さらに 2 つの安全な分散ロックを実装できます: 1 つはプロセスが競合するシナリオに適していますが、単一のプロセスが常にロックを取得して処理します。元の処理プロセスがハングアップしてロックの有効期限が切れない限り、ロックは他のプロセスによって取得されます。積極的にロックを解除する必要はありません。 get、expire/pexpire、setnx ex| px の Lua スクリプトを通じて実装され、各プロセスがロックを取得して処理するために競合するのに適したシナリオです。 set nx ex| px でロックを取得し、使用後は get で判断し、del でロックを解除しないと、ロックが切れる前にロックを取得できません。

6. GetSet は、新しい値を設定し、古い値を返します。たとえば、カウンターを実装するには、GetSet を使用してカウントを取得し、それを 0 にリセットします。

7. GetBit/SetBit/BitOp/BitCount、ビットマップの再生方法、たとえば、今日訪問するユニーク ユーザーの数を数えるとき、各登録ユーザーにはオフセットがあります。今日来たらビットを設定してくださいto 1. BitCount を使用して、今日の総人数を取得します。

8. Append/SetRange/GetRange/StrLen、拡張、置換、インターセプトを実行し、テキストの長さを検索します。これは、特定のデータ形式に非常に役立ちます。

実装方法: 文字列はデフォルトでは文字列としてredisに格納されており、redisObjectで参照されますが、incr、decrなどの演算があった場合は数値型に変換して計算します。 redisObject のエンコーディング フィールドは int です。

2. ハッシュ

はじめに: ハッシュは文字列と文字列値の間のマッピングを保存します。ハッシュはオブジェクトのさまざまな属性をマップに保存し、オブジェクトの特定の属性のみを読み取り/更新できます。この方法では、長すぎるプロパティをそのままにしておくことができ、さらに、異なるモジュールは相互の同時実行による上書き競合を引き起こすことなく、必要なプロパティのみを更新できます。

一般的に使用されるコマンド: hget、hset、hgetall など。

アプリケーション シナリオ:

1. ユーザー情報などの構造化データを保存します。 Memcached や CKV では、ユーザーのニックネーム、年齢、性別、ポイントなどのユーザー情報については、まずシリアル化して文字列値として保存する必要があります。 、通常は、値が取得されて逆シリアル化された後、項目の値が変更され、その後シリアル化されて保存されます。これはオーバーヘッドが増加するだけでなく、同時操作が可能な状況にも適していません (たとえば、2 つの同時操作ではポイントの変更が必要です)。 Redis のハッシュ構造を使用すると、データベース内の属性を更新するのと同じように、特定の属性値のみを変更できます。以下に示すように:

2. キーはユーザー ID、値はマップ、このマップのキーはメンバーの属性名、値は属性値であるため、データは内部のマップのキー (Redis では内部マップのキーはフィールドと呼ばれます) を通じて直接操作できます。つまり、対応する属性データはキー (ユーザー ID) フィールド (属性ラベル) を通じて操作できます。データを繰り返し保存する必要がなく、シリアル化や同時変更制御の問題も発生しません。

3. ただし、ここで注意が必要なのは、Redis はすべての属性データを直接取得するためのインターフェイス (hgetall) を提供していますが、内部 Map のメンバーが多数ある場合、内部 Map 全体を走査する必要があります。 Redis シングルスレッド モデル したがって、このトラバーサル操作には時間がかかり、他のクライアントからのリクエストにまったく応答しない可能性があるため、特別な注意が必要です。

4. インデックスの構築に使用できます。たとえば、ユーザー オブジェクトは、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 つのハッシュ キーを使用して、インデックス値の格納に複数の文字列キーを使用することを避けることができます。

5. HINCRBY は idmaker の実装にも使用できます。文字列型の idmaker と比較すると、各型にキーが必要ですが、ハッシュ型は 1 つのキーだけで済みます。

実装方法:

Value に対応する Redis ハッシュは実際には HashMap です。2 つの異なる実装があります。ハッシュのメンバーが少ない場合、Redis はそれに類似した 1 次元配列を使用します。メモリの節約 実体のHashMap構造を使わずにコンパクトに格納する方法 対応する値redisObjectのエンコードはzipmap メンバ数が増えると自動的に実体HashMapに変換される この時のエンコードはht

3. リスト

はじめに: リストは双方向のリンク リストであり、双方向のポップ/プッシュをサポートしています。世界のルールは一般に左からプッシュします。 LPush/RPop の右端からのポップ、およびメッセージが到着するまでクライアントがブロックできるブロック バージョン BLPop/BRPop もあります。 RPopLPush/BRPopLPush もあり、これはポップアップしてクライアントに戻りますが、同時に自分自身を別のリストにプッシュし、LLen がリストの長さを取得します。値による操作もあります。LRem (値による要素の削除)、LInsert (特定の値の前後の要素の挿入)、複雑さは O(N)、N はリストの長さです。は一意ではないため、すべての要素を走査するには、Set は O(log(N)) のみを受け取ります。

添字によって実行される操作: 添字は 0 から始まり、キューは左から右にカウントされ、添字が負の数の場合は右から左に計算されます。 LSetは要素の値を添え字で設定します。 LIndex は、添え字によって要素を返します。 LRange は、要素を直接バウンスする POP とは異なり、リスト内の添え字を持つ要素のみを返します。ページングによく使用されます。 LTrim は、リストのサイズを制限します。たとえば、最新の 20 件のメッセージのみを保持します。複雑度も O(N) で、LSet の N は List の長さ、LIndex の N は添字の値、LRange の N は要素数をリストする開始の値です。配列ではなくリンク リストを使用すると、添字によってアクセスできます。実際、添字がキューの先頭と末尾にない限り、リンク リストを走査する必要があります。 LTrim の N は、削除する要素の数です。

一般的に使用されるコマンド: lpush、rpush、lpop、rpop、lrange など。

適用シナリオ:

1. Twitterのフォローリストやファンリストなどの各種リスト、最新ニュースランキング、各記事へのコメントなどもRedisで実装可能' リスト構造。

2 メッセージ キューでは、リストの PUSH 操作を使用してタスクをリストに保存し、ワーカー スレッドが POP 操作を使用して実行するタスクを取り出します。ここのメッセージ キューには ACK メカニズムがありません。コンシューマが Pop にタスクを渡し、完了する前にクラッシュしたらどうなるでしょうか?解決策の 1 つは、追加のソート セットを追加することです。配布するときは、リストとソート セットの両方に同時に送信します。配布時間はスコアとして使用されます。ユーザーはタスクを完了した後、ZREM を使用して削除する必要があります。ソート セット内のジョブを定期的に削除し、タイムアウトになった未完了のタスクを削除してリストに戻します。もう 1 つのアプローチは、各ワーカーに追加のリストを追加し、タスクをポップアップするときに RPopLPush を使用し、同時にジョブをワーカー自身のリストに入れ、完了時に LREM を使用してジョブを削除することです。クラスター管理者 (動物園の飼育員など) がワーカーが死亡したことを発見した場合、ワーカーのリストの内容はメイン リストに戻されます。

3 LRANGE を使用すると、リストコンテンツのページング機能を簡単に実現できます。

4. 最新の N データを取得する操作: LPUSH を使用して、コンテンツ ID を挿入し、リストの先頭にキーワードとして格納します。 LTRIM は、リスト内の項目数を最大 5000 に制限するために使用されます。ユーザーが取得する必要があるデータの量がこのキャッシュ容量を超える場合は、リクエストをデータベースに送信する必要があります。

実装方法:

Redis リストの実装は双方向のリンク リストであり、逆方向の検索とトラバーサルをサポートでき、操作がより便利ですが、追加のメモリ オーバーヘッドが発生します。 . Redis 内部 送信バッファ キューなどを含む多くの実装でも、このデータ構造が使用されます。

4. Set

はじめに: これは順序のないセットであり、セット内の要素には順序がなく、繰り返されません。重複した要素を Set に入れると、それらは自動的に削除されます。

一般的なコマンド:

sadd、spop、smembers、sunion など。

アプリケーション シナリオ:

1. 一部のリストは重複排除が必要であり、セットはメンバーがセット コレクションに含まれているかどうかを判断するための重要なインターフェイスを提供します。これもリストでは提供できないものです。 . .

2. 一部の集合データを保存できます。たとえば、Weibo アプリケーションでは、ユーザーのすべてのフォロワーを 1 つのコレクションに保存したり、すべてのファンを 1 つのコレクションに保存したりできます。 Redis は、コレクションの交差、和集合、差分などの操作も提供しており、共同注意、共通の設定、2 級友人などの機能を実装するのに非常に便利です。上記のすべてのコレクション操作では、別のコマンドを使用することもできます。結果をクライアントに返すか、新しいコレクションに保存します。別の例として、QQ には「フレンドタグ」と呼ばれるソーシャル機能があり、「ビッグビューティー」、「大物」、「Ouba」などの友達をタグ付けできます。ここでは、各ユーザーのタグをコレクション内に保存することもできます。

3. 特定のページにアクセスした特定の登録ユーザーまたは IP アドレスの数を知りたい場合は、 SADD page:day1: を実行できます。特定のユーザーの数を知るには、SCARD page:day1: を使用します。特定のユーザーがこのページにアクセスしたかどうかをテストする必要がありますか?システムメンバー ページ:day1:

実装方法:

set の内部実装は、値が常に null である HashMap です。実際、ハッシュを計算することですぐにソートされます。これは、set が次のことを判断するために提供できるものでもあります。メンバーはセット内の Reason です。

5. ソートされたセット

はじめに: ソートされたセットは、セットと比較して、要素がセットに入れられるときに要素のスコアも提供されます。スコアに応じて自動的にソートできます。

一般的に使用されるコマンド:

zadd、zrange、zrem、zcard など

使用シナリオ:

1. 順序付けされた重複しないデータを保存します。 set Twitter の公開タイムラインなどのリストは、公開時間をスコアとして保存し、取得時に自動的に時間順に並べ替えることができます。

2. 重み付けされたキューを作成できます。たとえば、通常のメッセージのスコアは 1、重要なメッセージのスコアは 2 です。その後、ワーカー スレッドは逆の順序で作業タスクを取得することを選択できます。スコアの。重要なタスクに優先順位を付けます。

3. ランキング関連: ZADD リーダーボード <スコア> <ユーザー名> 。高スコア ユーザーのトップ 100 を取得するのは簡単です: ZREVRANGE リーダーボード 0 99。ユーザーのグローバル ランキングも同様で、「ZRANK leaderboard 」を実行するだけです。

4. ニュースはユーザーの投票と時間に基づいて並べ替えられます。ZADD 中のスコア = ポイント / 時間 ^ アルファ。このようにして、ユーザーの投票はそれに応じてニュースを掘り出しますが、時間が経過するとニュースは埋もれてしまいます。ある指標です。

5. 期限切れアイテムの処理: UNIX 時間をキーとして使用して、リストを時間順に並べ替えます。 current_time と time_to_live を取得して、期限切れのアイテムを見つけるという難しいタスクを完了します。別のバックグラウンド タスクは、ZRANGE...WITHSCORES を使用して、期限切れのエントリをクエリし、削除します。

実装方法:

Redis ソート セットは内部的に HashMap とスキップ リスト (SkipList) を使用して、データの保存と順序付​​けを保証します。HashMap はメンバーからスコアへのマッピングを配置し、すべてのメンバーがスキップされます。テーブルに格納され、ソートの基準は HashMap に格納されたスコアです。ジャンプ テーブル構造を使用すると、より高い検索効率が実現でき、実装も比較的簡単です。

Redis の詳細については、「redis データベース チュートリアル」列に注目してください。

以上がRedis データ型とアプリケーション シナリオの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。