Redis data structure: comprehensive analysis of Hash type

Redis, as an open source, in-memory data structure storage system, is widely used in various scenarios such as caching, message queues, and publish-subscribe systems with its excellent performance and flexible data types. Among the five basic data types of Redis, the Hash type is a very important data type. It can store a collection of key-value pairs, and can add, delete, update, and search operations with a time complexity of less than 1 millisecond, so it has a wide range of uses in practical applications.

In the next article, I will introduce the Hash type of Redis in detail, including its internal implementation, main features, common commands and application scenarios. Whether you are new to Redis or a developer with some experience, I believe you can learn some useful knowledge from this article. Let's have a deep understanding of Redis's Hash type and explore its charm.



1. Redis-Hash data type

1.1. Introduction to Redis-Hash type

The Hash type of Redis is a collection of key-value pairs, and this data type is suitable for storing objects. In the Hash type, each key has a corresponding value, which is very similar to Python's dictionary, Java's HashMap, and JavaScript objects.

Here are some key features of the Redis Hash type:

  1. Key-value pair collection: The Hash type can store multiple key-value pairs, and each key has a corresponding value.

  2. Binary Safe: Hash type keys and values ​​are binary safe, meaning they can contain any data, including binary data.

  3. Large capacity: A single Hash type can store more than 400 million key-value pairs.

  4. Efficient lookup speed: No matter how much data is stored in the Hash, the speed of finding a key is very fast.

1.2. Redis-Hash application scenarios

The Hash type of Redis is a collection of key-value pairs, suitable for storing objects, so it has a wide range of applications in many scenarios. Here are some common application scenarios:

  1. Store objects: The Hash type can store multiple key-value pairs, which is very suitable for storing objects. For example, you can use the Hash type to store user information, such as username, password, email, etc.;

  2. Data analysis: You can use the Hash type to store various statistical data, such as user behavior data, and then perform data analysis;

  3. Social network: In a social network application, you can use the Hash type to store the user's friend list, follower list, etc.

The above are just some common application scenarios. In fact, due to the flexibility of Redis, you can apply the Hash type of Redis to more scenarios according to your own needs.


2. Redis-Hash underlying structure
2.1. Introduction to the underlying structure of Redis-Hash

The underlying implementation of Redis's Hash type is a very optimized data structure, which will choose to use a compact compressed list (ziplist) or hashtable (hashtable) as the underlying implementation according to the actual situation.

The Hash type of Redis will switch between the compressed list (ziplist) and the hash table (hashtable) according to the actual situation, which mainly depends on two configuration parameters: hash-max-ziplist-entriesand hash-max-ziplist-value.

  1. hash-max-ziplist-entries: This parameter is used to set the maximum number of nodes that the compressed list can store. If the number of elements of a Hash type exceeds this value, then it will switch from a compressed list to a hash table. The default value is 512;
  2. hash-max-ziplist-value: This parameter is used to set the maximum size (in bytes) of each node in the compression list. If the size of any element of a Hash type exceeds this value, then a switch is made from the compressed list to the hash table. The default value is 64.

Both of these parameters can be set in the Redis configuration file. By adjusting these two parameters, you can choose to save memory or improve performance according to your application characteristics.

  1. Convert from compressed list to hash table: When the number of fields and values ​​stored by the Hash type exceeds the hash-max-ziplist-entriesvalue, or the size of any field or value exceeds hash-max-ziplist-valuethe value, Redis will convert the underlying structure from a compressed list to a hash table. This process is automatic and transparent to the user.
  2. Conversion from hash table to compressed list: However, once the underlying structure of the Hash type has been converted to a hash table, it cannot be converted back to a compressed list. This is because the performance of the hash table is higher, and in most cases, once the size of a Hash type exceeds a certain threshold, its size is likely to continue to grow.
2.2, Redis-compressed list (ziplist)

When the number of fields and values ​​stored in the Hash type is small, and the string length of the fields and values ​​is short, Redis will choose to use the compressed list as the underlying implementation. A compressed list is a special encoding structure designed to save memory, which stores all fields and values ​​together compactly. The advantage of this method is that it occupies less memory, but when the data needs to be modified, the entire compressed list may need to be rewritten, and the performance is low.

Redis' compressed list (ziplist) is a special encoding structure designed to save memory. A compressed list stores all elements compactly together, and each element occupies only contiguous memory space.

A compressed list has the following structure:

+---------+---------+--------+---------+---------+---------+--------+
| zlbytes | zltail  | zllen  | entry_1 | entry_2 |  ...    | zlend  |
+---------+---------+--------+---------+---------+---------+--------+

Ps: In the source code of Redis, the structure of the compressed list (ziplist) is not directly defined as a C structure, but a continuous memory is operated through a series of macros and functions.

Attributes illustrate
“zlbytes” A 4-byte integer, indicating the number of bytes occupied by the entire compression list, including <zlbytes>its own size.
"golden" A 4-byte integer representing the offset of the last element in the compressed list. This offset is relative to the starting address of the entire compressed list.
“zllen” A 2-byte integer representing the number of elements in the compressed list. If the number of elements exceeds 65535, then this value will be set to 65535, and the entire compressed list needs to be traversed to get the actual number of elements.
“entry” Compress the elements in the list, each element consisting of one or more bytes. The first byte of each element (also known as "entry header") is used to indicate the length of the element and the encoding method.
“zlend” A byte with a value of 255 indicating the end of the compressed list.
2.3, Redis-hash table (hashtable)

When the number of fields and values ​​stored in the Hash type is large, or the string length of the fields and values ​​is long, Redis will choose to use the hash table as the underlying implementation. A hash table is a common key-value pair mapping structure, which maps keys to a bucket through a hash function, and then searches in the bucket. The advantage of this method is that the performance of searching and modifying data is high, but it also takes up more memory.

Redis's hash table (hash table) is a common key-value pair mapping structure, which maps keys to a bucket through a hash function, and then searches in the bucket. Redis's hash table uses the linked list method to resolve hash conflicts, that is, when multiple keys are mapped to the same bucket, they are stored in the same linked list.

In the source code of Redis, the structure of the hash table is defined as follows:

typedef struct dictEntry {
    
    
    void *key;
    void *val;
    struct dictEntry *next;
} dictEntry;

typedef struct dictht {
    
    
    dictEntry **table;
    unsigned long size;
    unsigned long sizemask;
    unsigned long used;
} dictht;

typedef struct dict {
    
    
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    int iterators; /* number of iterators currently running */
} dict;

in:

  • dictEntryA structure represents a node in a hash table, containing a key ( key), a value ( val), and a pointer to the next node ( next).

  • dicthtThe structure represents a hash table, which contains a pointer to the hash table array ( table), the size of the hash table array ( size), the hash table array size mask ( sizemask), and the number of used nodes ( used).

  • dictThe structure represents a dictionary containing two hash tables ( ht), the index currently being rehashed ( rehashidx), and the number of iterators currently running ( iterators).

This is the structure of a Redis hash table.


3. Hash common commands

The following are some commands related to the Hash type in Redis:

3.1. Set Hash value

The command to set the Hash value in Redis is HSETthat its syntax is as follows:

HSET key field value

Among them, keyis the name of the hash table, fieldis the field name in the hash table, and valueis the value corresponding to the field. If the field does not already exist in the hash table, a new field is created and its value is set to the specified value. If the field already exists, the original value will be overwritten.

For example, we can set the value of user:1001a field in a hash table named with the following command :nameAlice

HSET user:1001 name Alice

If you need to set the values ​​of multiple fields at the same time, you can use HMSETthe command, its syntax is as follows:

HMSET key field1 value1 [field2 value2 ...]

For example, we can set the value of both the and fields user:1001in a hashtable at the same time using the following command :nameage

HMSET user:1001 name Alice age 25

This allows you to set the values ​​of multiple fields at once.

In Redis, the command to get the Hash value is HGET, its syntax is as follows:

HGET key field

Where, keyis the name of the hash table, fieldand is the field name in the hash table.

For example, we can get the value of user:1001a field in a hashtable named using the following command name:

HGET user:1001 name
3.2. Get Hash value

If you need to get the values ​​of multiple fields in the hash table, you can use HMGETthe command, its syntax is as follows:

HMGET key field1 [field2 ...]

For example, we can get the values ​​of the and fields user:1001in the hashtable using the following command :nameage

HMGET user:1001 name age

If you need to get all the fields and values ​​in the hash table, you can use HGETALLthe command, its syntax is as follows:

HGETALL key

For example, we can get user:1001all the fields and values ​​in a hash table with the following command:

HGETALL user:1001
3.3. Delete Hash value

In Redis, the command to delete the Hash value is HDEL, and its syntax is as follows:

HDEL key field [field ...]

where keyis the name of the hash table and fieldis the name of the field to be deleted. You can delete one or more fields at a time.

For example, we can delete a user:1001field in a hash table named with the following command name:

HDEL user:1001 name

If you want to delete multiple fields, you can list the names of these fields in turn after the command, for example:

HDEL user:1001 name age

This command will delete the and fields user:1001in the hash table .nameage

It should be noted that HDELthe command will only delete the specified field and its value, but not the entire hash table. If you want to delete the entire hash table, you can use DELthe command, for example:

DEL user:1001

This command deletes the entire user:1001hash table.

3.4. Other Hash commands

Some other common commands of Hash in Redis are:

  1. HEXISTS key field: Check whether the specified field exists in the hash table key.
  2. HLEN key: Get the number of fields in the hash table.
  3. HKEYS key: Get all the fields in the hash table.
  4. HVALS key: Get all the values ​​in the hash table.
  5. HGETALL key: Get all the fields and values ​​of the specified key in the hash table.
  6. HINCRBY key field increment: Add increment to the integer value of the specified field in the hash table key.
  7. HINCRBYFLOAT key field increment: Add increment to the floating-point value of the specified field in the hash table key.
  8. HMSET key field value [field value ...]: Set multiple field-value (field-value) pairs to the key of the hash table at the same time.
  9. HMGET key field [field ...]: Get all the values ​​of the given field.

おすすめ

転載: blog.csdn.net/weixin_45187434/article/details/132510601