出典:www.cnblogs.com/wyc1994666/p/10669212.html
以前に就職の面接を探していたとき、Redis関連の問題で立ち往生していました。
インタビューの前に、Redisの5つの一般的に使用されるデータ構造、Redis永続化戦略、分散ロックのRedis実装、単純なパブリッシュ/サブスクライブなど、通常のルーチンに従って準備しました。結局、Redisで尋ねられた質問~~
インタビュアー: 一般的に使用されるデータ構造に精通している履歴書を見てください。何について話しますか?
I: 一般的に使用される文字列、リスト、セット、zset、ハッシュの5つがあります(内部は非常に満足しています)
インタビュアー: 次に、使用したデータ構造を教えてください_I
: 文字列が最も使用されており、json文字列は通常_に格納されます
インタビュアー: Redisがその文字列を内部で実装する方法を知っていますか?_
I: ええと〜RedisはC言語で書かれていることを理解していますが、具体的な実装については明確ではありません〜
私は死ぬためにここにいます~~~
同じ経験の友達がいますか?
戻ってから、Redisの原理についての知識を補いましたが、たまたまインタビュー体験の最新のまとめだったので、今日の記事をお届けします。
この記事では、次のことについて説明します。
-
Redis文字列の実装
-
Redis文字列のパフォーマンス上の利点
Redis文字列の実装
RedisはC言語で記述されていますが、C言語の文字列を直接使用するのではなく、文字列のセットを単独で実装します。速度とパフォーマンスを向上させることが目的です。Redisも高性能を実現するために多大な労力を費やしていることがわかります。
Redisは、SDSと呼ばれる単純な動的文字列(Simple Dynamic String)を構築しました
1.SDSコード構造
struct sdshdr{
// 记录已使用长度
int len;
// 记录空闲未使用的长度
int free;
// 字符数组
char[] buf;
};
SDS?なんてこったい?なじみのない友達は、この名前に疑問を持っているかもしれません。これは単なる名詞であり、気にしないでください。Redisのデザインアイデアを評価することに焦点を当てる必要があります。一目でそれを説明するために下の絵を描いてください。
Redis文字列は、C言語文字列の実装ルールにも準拠します。つまり、最後の文字はヌル文字です。ただし、このヌル文字はlenではカウントされません。
2.SDSの動的膨張特性
SDSの最も強力で素晴らしい点は、その動的性です。長さを動的に変更します。例えば
上の図に示すように、最初のs1には5つの空きシートしかなく、後で「世界」の6文字を追加する必要がありますが、これは明らかに十分ではありません。今何時ですか?Redisは次の3つの操作を実行します。
-
サイズが十分かどうかを計算します
-
必要なサイズに合わせてスペースを広げます
-
使用サイズと同じ長さの空き空き領域を開くlen(len <1Mの場合)長さ1Mの空き領域を開く(len> = 1Mの場合)
これまでのところ、この実装がJavaのList実装に少し似ていると友人が思っているのを見たことがありますか?それを読んだ後、あなたはそれのように感じるでしょう。
Redis文字列のパフォーマンス上の利点
-
文字列の長さをすばやく取得する
-
バッファオーバーフローを回避する
-
スペース割り当ての数を減らし、メモリ使用効率を向上させます
1.文字列の長さをすばやく取得します
上記のSDS構造を見てください。
struct sdshdr{
// 记录已使用长度
int len;
// 记录空闲未使用的长度
int free;
// 字符数组
char[] buf;
};
使用される文字長lenはSDSに格納されているため、文字列の長さを取得する場合はlenを直接返すことができ、時間計算量はO(1)です。C言語の文字列を使用する場合、文字列の長さの取得関数の時間計算量はO(n)、nは文字数です。これは、最初から最後まで(空の文字「\ 0」に)トラバースおよび追加されるためです。
2.バッファオーバーフローを回避する
strcatを使用してC言語の文字列に文字列を追加する場合は、事前に必要なスペースを開く必要があります。スペースを開かないと、バッファオーバーフローが発生し、プログラムの他のコードに影響を与える可能性があります。次の図に示すように、文字列s1 = "hello"と文字列s2 = "baby"があり、strcat(s1、 "world")が実行され、実行前にs1用のスペースが作成されていません。これにより、バッファオーバーフローが発生しました。
Redisの場合、文字列が追加されるたびにスペースが十分かどうかがチェックされるため、バッファオーバーフローの問題は発生しません。各追加操作の前に、次の操作が実行されます。
-
サイズが十分かどうかを計算します
-
必要なサイズに合わせてスペースを広げます
3.スペース割り当ての数を減らし、メモリ使用効率を向上させます
文字列の追加操作にはメモリ割り当ての問題が含まれますが、メモリ割り当ての問題にはメモリ分割アルゴリズムとシステムコールが含まれるため、頻繁に発生するとパフォーマンスに影響が出るため、パフォーマンス指向のRedisには絶対に耐えられません。
そのため、次の2つの最適化対策が講じられています
-
スペースと割り当て
-
不活性空間のリサイクル
1.スペースの事前割り当て
追加操作の場合、Redisは十分なスペースを開くだけでなく、次の操作のために未使用のスペース(空き)を事前に割り当てます。未使用スペース(空き)のサイズは、変更された文字列の長さによって決まります。
変更された文字列の長さがlen <1Mの場合、lenと同じ長さの未使用スペースが割り当てられます(空き)
変更された文字列の長さlen> = 1Mの場合、1Mの未使用スペース(空き)が割り当てられます
この事前割り当て戦略では、メモリ割り当ての数が減ります。これは、割り当ての前に、既存の空き領域が十分かどうかを確認する前に、十分な場合は開かれないためです。
2.不活性スペースの回復
上記の状況とは逆に、レイジースペースレクラメーションは文字列削減操作に適しています。たとえば、文字列s1 = "hello world"がある場合、s1でsdstrim(s1、 "world")操作を実行します。操作が完了した後、Redisは縮小された部分をすぐに再利用しませんが、それをに割り当てます。メモリを必要とする次のプログラム。もちろん、Redisはメモリを再利用するためのAPIも提供します。これを手動で前後に呼び出して、メモリの一部を縮小および削減できます。
ここだよ〜
次回この問題に遭遇したとき、あなたはそれについて話すことができます、ハハハ〜
------------------------------------------- <終了> ---- -----------------------------------
Xiaomuのブログ