この記事では、Redis データ構造の String 型を理解し、Redis の KV ストレージ構造について説明します。お役に立てば幸いです。
Redis は分散 KV キャッシュとしてよく使用されますが、多くの人は単にそれを使用していますが、その下に多くの未知の秘密があることを知りません。 [関連する推奨事項: Redis ビデオ チュートリアル ]
String は、Redis でサポートされる最も基本的なデータ型です。文字列、そのデータ構造とストレージはどのようなものですか。
ご存知のとおり、redis は C 言語で書かれており、C 言語には String 型はなく、char[] のみがあります。初期化中にサイズを指定する必要があり、タイプを変更することはできません。 incrコマンドやappendコマンドなどの動的追加・拡張などの機能を実現するために、redisではこれらの機能を実現するSDS(Simple Dynamic String)を定義・保守しています。
まず、Redis ソース コードで定義されているデータ構造を見てみましょう。スペースを節約するために、ここでは 5 つのタイプがあります。
1. len: char[] の長さを取得するには、配列を走査する必要があります。len(char[]) の時間計算量は O(n) です。 ;
2. alloc : C 言語には String 型はなく、char[] だけがあり、char[] は最初にスペースの長さを割り当てる必要があります。char[] には事前に割り当てられた長さがあり、データが大きくなった後に拡張する必要があります;
3. falgs: 常に 1 バイトを占有します。最下位の 3 ビットはヘッダーのタイプを示すために使用されます。ヘッダーは5種類あり、sds.hに定数定義があります。
4. buf[]: C 言語の char 配列。'\0' が終わりを表します。これは、バイナリ データの保存に '\0' を含めることはできないことを意味します。画像、音声などのバイナリ ストレージには問題が発生します。 . - これが、Redis が実装した SDS がバイナリセーフな文字列であると述べた理由です。
1. Redis によって実装された SDS は拡張をサポートしています
2. 長さ len が含まれており、長さを取得する複雑さは次のとおりです。 O(1 )
3. スペースの事前割り当て
4. 遅延スペースの解放 (後述)
利点
欠点
jemalloc がメモリを割り当てるときは、割り当てられたスペースとして N に適用するバイト数に基づいて、N より大きいが N に最も近い 2 のべき乗を見つけます。これにより、頻繁な割り当ての数を減らすことができます。例えば。 6 バイトのスペースを申請した場合、jemalloc は実際に 8 バイトのスペースを割り当てます。24 バイトのスペースを申請した場合、jemalloc は 32 バイトを割り当てます。したがって、先ほど述べたシナリオでは、dictEntry 構造体は 32 バイトを占有します。
スペースの事前割り当ては、SDS の文字列拡張操作を最適化するために使用されます。SDS API が SDS を変更し、スペースを変更する必要がある場合に使用されます。 SDS への割り当て 拡張時に、プログラムは変更に必要な領域を SDS に割り当てるだけでなく、追加の未使用領域も SDS に割り当てます。
このうち、追加で割り当てられる未使用領域の量は、次の式で決定されます。
Redis は、スペースの事前割り当て戦略を通じて、文字列拡張操作を継続的に実行するために必要なメモリの再割り当ての数を減らすことができます。
レイジー スペース リリースは、SDS の文字列短縮操作を最適化するために使用されます。SDS API が SDS によって保存された文字列を短縮する必要がある場合、プログラムはそれを実行します。すぐにはではありません。メモリの再割り当てを使用して短縮後の余分なバイトをリサイクルしますが、free 属性を使用してこれらのバイト数を記録し、将来の使用を待ちます。
Redis では、すべてのストレージは KV キーと値のペアの形式で保存されます。K は文字列型で、これは SDS です。V はそれを可能にしますは文字列、リスト、ハッシュなどです (Redis によってサポートされるデータ構造)。V は特定の型に直接設定されませんが、redisObject の層でカプセル化されます。実際に格納されたデータ構造は、具体的には ptr ポインタによって指されます。 。
さらに、領域を節約するために、redis は ptr ポインターをさまざまな方法で保存しますが、一方で Long 型の整数を保存する場合、RedisObject 内のポインターは整数データに直接割り当てられるため、整数を指すために追加のポインターが必要ないため、ポインターのスペース オーバーヘッドが節約されます。一方、文字列データが保存され、その文字列が 44 バイト以下の場合、RedisObject 内のメタデータ、ポインター、SDS は連続したメモリ領域となるため、メモリの断片化が回避されます。このレイアウト方式はembstr符号化方式とも呼ばれます。もちろん、文字列が 44 バイトを超えると、SDS 内のデータ量が増加し始め、Redis は SDS と RedisObject を一緒にレイアウトしなくなり、代わりに SDS に独立した領域を割り当て、SDS 構造を指すポインターを使用します。 。このレイアウト方法は raw エンコード モードと呼ばれます。図に示すように、
raw raw SDS の文字長が 44 未満に短縮された場合、embstr エンコーディングに逆変換されますか?
いいえ、Redis の基礎となるコーディングは、変更後は元に戻せません (ロールバックされません)。
Redis は一般的に使用されるキャッシュ ミドルウェアですが、使用するときにより適切なデータ構造を選択できるように、そのデータ構造とストレージを明確に理解する必要があります。そしてメモリの推定値。
redis メモリ計算アドレス http://www.redis.cn/redis_memory/
プログラミング関連の知識の詳細については、プログラミング入門を参照してください。 !
以上がRedis データ構造の String 型について話しましょうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。