Introduction
Redis hash dictionary uses the key value to find the corresponding value. Note how the redis dictionary performs rehash.
Source code dict. h dict. c Data Structure
As shown in, the hash dictionary is represented by a dict struct, which contains two hash tables for rehash operations. Meanwhile, hash tables use tables to resolve conflicts. The specific data structure is as follows:
/** Hash table node */typedef struct dictentry {// key void * key; // value Union {void * val; uint64_t u64; int64_t s64;} V; // link back to node struct dictentry * Next;} dictentry; /** type-specific processing functions of a cluster */typedef struct dicttype {// calculate the key's hash function unsigned int (* hashfunction) (const void * Key ); // function void * (* keydup) (void * privdata, const void * Key) of the replication key; // function void * (* valdup) (void * privdata, const void * OBJ); // compares the INT (* Keycompare) (void * privdata, const void * key1, const void * key2); // key interpretation function void (* keydestructor) (void * privdata, void * Key); // value interpretation function void (* valdestructor) (void * privdata, void * OBJ);} dicttype; /** hash table */typedef struct dictht {// hash table node pointer array (also known as bucket) dictentry ** table; // the size of the pointer array unsigned long size; // The length mask of the pointer array, used to calculate the index value unsigned long sizemask; // The number of nodes displayed in the hash is unsigned long used;} dictht ;/** ** Each dictionary uses two hash tables for progressive rehash */typedef struct dict {// type-specific processing function dicttype * type; // type processing function's private data void * privdata; // hash table (2) dictht HT [2]; // mark the rehash progress, -1 indicates that int rehashidx is not performed on rehash; // number of currently running security iterators int iterators;} dict; /** dictionary iterator ** if the safe attribute value is 1, it indicates that the iterator is a secure iterator. * When the security iterator is iterating a dictionary, it can still call dictadd, dictfind, and other functions. ** If the value of the Safe attribute is 0, it indicates that this is not a security iterator. * If the running iterator is an insecure iterator, it can only call the dictnext function on the dictionary. */Typedef struct dictiterator {// dictionary in iteration dict * D; int table, // Number of the hash table being iterated (0 or 1) index, // The index of the hash table array being iterated is safe; // is it safe? Dictentry * entry, // current hash node * nextentry; // subsequent node of the current hash node} dictiterator;
Analysis
Rehash
Two hash tables are used in the dictionary to facilitate rehash. There are two primary rehash Methods: one is to call cron in the background to perform hash Based on step 1, the second is to perform step-by-step hash when adding or deleting the elements in the dictionary.
Here, each hash step is measured in the linked list corresponding to a real hash key, that is to say, the step-by-step rehash is to rehash a key linked list in the original hash table to the position in the new hash table. Here we can see that redis sacrifices the memory but achieves a performance response. Scatter the rehash operation to avoid sharp performance degradation caused by blocking.
Iterator
If the attributes of the iterator are safe, it indicates that other operations such as dictadd can be performed during the iteration. If the iterator is insecure, it can only perform next operations.
Redis also restricts rehash when an iterator accesses the dictionary, because this will cause multiple accesses to an element. However, the dictionary can be traversed at any time during the rehash process. Once the iterator starts to traverse the dictionary, the rehash will pause until no iterator is available to traverse the dictionary.