18

この記事を読んでいて、redis に 100 万個のキーを保存すると 17GB のメモリが使用されると書かれています。ただし、ハッシュに切り替えると、それぞれ 1k でチャンク化すると (例: HSET "mediabucket:1155" "1155315" "939")、1M を 5GB に保存できるため、かなりの節約になります。

redisのメモリ最適化を読みましたが、違いがよくわかりません。HGETは完全にO(1)ではありませんが、十分に近く、hsetを使用するとCPU使用量が増えると述べています。CPU使用量が増える理由がわかりません(スペースの取引時間は確かです。しかし、どのように/何を?)。「エンコード」については言及していますが、エンコード方法については言及していません。

文字列のみについても言及していますが、文字列のみが何を意味するのかわかりません。ハッシュフィールドですか?ハッシュフィールドのことですか?HSETには何も表示されません。正確には何がエンコードされ、SET を使用するよりもエンコードが効率的なのはなぜですか?

どうすればHSET "mediabucket:1155" "1155315" "939"より効率的になるSET "mediabucket:1155315" "939"でしょうか?SET のデータが少ない (1155315 ではなく 1155315 と 1155 が使用される)。個人的にはバイナリ キーを使用してみますが、HSET がより効率的である理由とは関係ないと思います。

編集 :

redis-db メーリング リストにもクロス投稿: https://groups.google.com/d/topic/redis-db/90K3UqciAx0/discussion

4

1 に答える 1

20

小さなハッシュ オブジェクトは、hash-max-ziplist-entries および hash-max-ziplist-value パラメータの値に応じて、ziplist としてエンコードされます。これは単純なデータのシリアル化です。

ziplist は次のように定義されます (Redis ソース コードから抽出)。

/* The ziplist is a specially encoded dually linked list that is designed
* to be very memory efficient. It stores both strings and integer values,
* where integers are encoded as actual integers instead of a series of
* characters. It allows push and pop operations on either side of the list
* in O(1) time. However, because every operation requires a reallocation of
* the memory used by the ziplist, the actual complexity is related to the
* amount of memory used by the ziplist.
*
* ----------------------------------------------------------------------------
*
* ZIPLIST OVERALL LAYOUT:
* The general layout of the ziplist is as follows:
* <zlbytes><zltail><zllen><entry><entry><zlend>
*
* <zlbytes> is an unsigned integer to hold the number of bytes that the
* ziplist occupies. This value needs to be stored to be able to resize the
* entire structure without the need to traverse it first.
*
* <zltail> is the offset to the last entry in the list. This allows a pop
* operation on the far side of the list without the need for full traversal.
*
* <zllen> is the number of entries.When this value is larger than 2**16-2,
* we need to traverse the entire list to know how many items it holds.
*
* <zlend> is a single byte special value, equal to 255, which indicates the
* end of the list.
*
* ZIPLIST ENTRIES:
* Every entry in the ziplist is prefixed by a header that contains two pieces
* of information. First, the length of the previous entry is stored to be
* able to traverse the list from back to front. Second, the encoding with an
* optional string length of the entry itself is stored.
*
* The length of the previous entry is encoded in the following way:
* If this length is smaller than 254 bytes, it will only consume a single
* byte that takes the length as value. When the length is greater than or
* equal to 254, it will consume 5 bytes. The first byte is set to 254 to
* indicate a larger value is following. The remaining 4 bytes take the
* length of the previous entry as value.
*
* The other header field of the entry itself depends on the contents of the
* entry. When the entry is a string, the first 2 bits of this header will hold
* the type of encoding used to store the length of the string, followed by the
* actual length of the string. When the entry is an integer the first 2 bits
* are both set to 1. The following 2 bits are used to specify what kind of
* integer will be stored after this header. An overview of the different
* types and encodings is as follows:
*
* |00pppppp| - 1 byte
*      String value with length less than or equal to 63 bytes (6 bits).
* |01pppppp|qqqqqqqq| - 2 bytes
*      String value with length less than or equal to 16383 bytes (14 bits).
* |10______|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt| - 5 bytes
*      String value with length greater than or equal to 16384 bytes.
* |11000000| - 1 byte
*      Integer encoded as int16_t (2 bytes).
* |11010000| - 1 byte
*      Integer encoded as int32_t (4 bytes).
* |11100000| - 1 byte
*      Integer encoded as int64_t (8 bytes).
* |11110000| - 1 byte
*      Integer encoded as 24 bit signed (3 bytes).
* |11111110| - 1 byte
*      Integer encoded as 8 bit signed (1 byte).
* |1111xxxx| - (with xxxx between 0000 and 1101) immediate 4 bit integer.
*      Unsigned integer from 0 to 12. The encoded value is actually from
*      1 to 13 because 0000 and 1111 can not be used, so 1 should be
*      subtracted from the encoded 4 bit value to obtain the right value.
* |11111111| - End of ziplist.
*
* All the integers are represented in little endian byte order.
*/

ハッシュ オブジェクトの各アイテムは、ziplist 内のキーと値のペアとして表されます (2 つの連続したエントリ)。キーと値はどちらも、単純な文字列または整数として格納できます。この形式は、動的データ構造 (実際のハッシュテーブルなど) を実装するために必要な多くのポインター (各 8 バイト) を保存するため、メモリ内でよりコンパクトになります。

欠点は、HSET/HGET 操作が ziplist に適用されると実際には O(N) になることです。そのため、ziplist は小さく保つ必要があります。ziplist データが L1 CPU キャッシュに収まる場合、対応するアルゴリズムは線形の複雑さにもかかわらず十分に高速です。

詳細については、次のリンクを参照してください。

Redis のメモリ使用量はデータの 10 倍

Redis データ構造のスペース要件

これらの回答は、他のデータ構造 (セット、リスト、またはソートされたセットなど) を参照していますが、まったく同じ概念です。

于 2012-10-08T12:13:13.373 に答える