Redisデータ構造の単純な動的文字列

 1つ:単純な動的文字列の構造

1:SDS構造

struct sdshdr {
  //buf已占用的空间长度
  //等于SDS所保存的字符串长度
  int len;
  //buf中剩余的空间长度   
  int free; 
  //字符数组,用于保存字符串
  char but[];  
}

2:SDSデータフォーマットの例

  • 空き属性値は5です。これは、このSDSに5バイトの未使用スペースがあることを意味します。
  • len属性の値は5です。これは、このSDSが5バイトの文字列を格納することを意味します。
  • buf属性は、char型の配列です。配列の最初の5バイトには、それぞれ「R」、「e」、「d」、「i」、および「s」の5文字が含まれ、最後のバイトには「空の文字列」が格納されます。 \ 0 '。

2:単純な動的文字列の利点

1:文字列の長さを取得するための一定の複雑さ

長さを取得するためのC文字列トラバーサルと比較して、SDSは長さを取得するために構造内のlen属性を取得するだけで済みます。これにより、文字列の長さをO(N)からO(1)に取得する元の複雑さが軽減されます。

2:バッファオーバーフローに終止符を打つ

C文字列がstrcat関数を実行するときに、実行する前に残りのスペースが十分かどうかを確認し忘れると、データが他の場所にオーバーフローし、他の文字列が変更される可能性があります。

次の図に示すように、メモリ内に2つのC文字列S1とS2が隣接している場合、S1は文字列「Redis」を格納し、S2は文字列「MongoDB」を格納します。

プログラマがstrcat(1、 "Cluster")を実行すると、S1のデータがS2のメモリにオーバーフローし、S2の文字列が改ざんされます。

SDSが文字列スプライシングを実行する場合、この問題は発生しません。実行前に、最初に残りのスペースが十分かどうかを確認します。十分でない場合は、実行に必要なサイズにスペースを拡張してから、文字列を実行します。 C言語。バッファオーバーフローが発生しないように接続機能。

3:文字列が変更されたときのメモリ再割り当ての数を減らします

  • C文字列が追加スプライシング機能を実行する場合、メモリ不足によるバッファオーバーフローを回避するために、メモリを再割り当てする必要があります。
  • C文字列がトリム切り捨て機能を実行する場合、使用されていないメモリスペースを解放するためにメモリを再割り当てする必要があります。この手順を忘れると、メモリリークが発生します。

    SDSの場合、設計者はスペースの事前割り当てと遅延解放されたスペースを使用して、頻繁なメモリ再割り当ての問題を解決しました。

  3.1:スペースの事前割り当て

      スプライシング機能を実行すると、メモリが空または不足していないことがわかり、メモリスペースが事前に割り当てられます。割り当てルールは次のとおりです。

  • SDSの変更された長さが1M未満の場合、len属性値と同じメモリスペースがfreeに割り当てられます。たとえば、変更されたS1文字列の長さが13バイトの場合、freeは13バイトのメモリスペースも割り当てます。 、およびbuf配列の実際の長さは13 + 13 + 1 = 27バイトの長さです(1は空の文字列を格納するために使用されます)
  • SDSの変更された長さが1M以上の場合、プログラムはfree1MBの未使用メモリスペースを割り当てます。SDSの変更されたlen属性値が2MBの場合、freeは1MBであり、buf配列の実際の長さです。 2MB + 1MB +1バイトです

  3.2:レイジースペースリリース

      SDSがsdstrim機能を実行すると、解放されたメモリが空きに含まれ、次にsdscat機能が実行されるときに解放されたスペースを使用できるため、頻繁なメモリの再割り当てを回避できます。

      同時に、SDSには対応する機能があり、必要なときにSDSの未使用スペースを解放できるため、メモリの浪費を心配する必要がありません。

      スペースの事前割り当てと遅延スペースの解放の両方で、頻繁なメモリ再割り当ての問題を回避できます。

4:バイナリセキュリティ

C文字列は特定のエンコーディング(ASCIIなど)に準拠している必要があり、文字列の終わりに加えて、文字列に空の文字列を含めることはできません。そうでない場合、文字列の終わりと見なされ、C文字列が制限されます。テキストになります。画像、音声、ビデオ、圧縮ファイルなどのバイナリデータを保存することはできません。

SDSはバイナリを介してデータを保存し、文字列がヌル文字ではなくlen属性の値で終了するかどうかを判断します。これにより、Redisはテキストデータだけでなく、任意の形式のバイナリデータも保存できるようになります。

5:一部のC文字列関数と互換性があります

SDSのデータの終わりは空の文字列に設定されるため、strcasecmp()関数など、<string.h>の一部の関数を使用して、不要なコードの重複を回避できます。

 

おすすめ

転載: blog.csdn.net/qq_37469055/article/details/114411035
おすすめ