rehash
With the implementation of the operation, key-value pairs stored in the hash table will be gradually increased or decreased in order to allow the load factor of the hash table (load factor) is maintained within a reasonable range, when you save the hash table key when too much or too little value for the number of procedures required for the size of the hash table corresponding expansion or contraction.
Work expansion and contraction of the hash table can be (re-hash) to complete the operation by performing rehash, Redis dictionary step for rehash hash table follows:
- A dictionary of
ht[1]
hash tables allocated space, this space depends on the size of the hash table of the operations to be performed, and theht[0]
key number included in the current (i.e., aht[0].used
value of the property):- If the expansion operation is performed, then the
ht[1]
size of greater than or equal to the firstht[0].used * 2
of 2 ^ n (2
an
power of power); - If the shrink operation is performed, then the
ht[1]
size of greater than or equal to the firstht[0].used
of 2 ^ n.
- If the expansion operation is performed, then the
- Will be saved in
ht[0]
all the key values to rehashht[1]
above: rehash refers to recalculate the hash value and the index key value, then the key-value pair is placed intoht[1]
the specified location on the hash table. - When
ht[0]
all key-value pairs are contained moved toht[1]
after (ht[0]
becomes empty table), releaseht[0]
theht[1]
setht[0]
, and inht[1]
the newly created an empty hash table, in preparation for the next rehash.
For example, suppose a program to be shown in FIG. 4-8 dictionary ht[0]
extended operation, the program performs the following steps:
ht[0].used
Current value4
,4 * 2 = 8
while8
(2 ^ 3) happens to be the first greater than or equal4
to2
then
power, so the program willht[1]
hash table size is set8
. Figure 4-9 shows theht[1]
following distribution space, dictionary look.- It will
ht[0]
contain four key-value pairs to rehashht[1]
, shown in Figure 4-10. - Release
ht[0]
, andht[1]
setht[0]
, and then toht[1]
assign a blank hash table, shown in Figure 4-11.
So far, the extended operation of the hash table is finished, the program successfully from the original size of the hash table is 4
changed to now 8
.
Expansion and contraction of the hash table
When any one of the following conditions is satisfied, the program will automatically begin to expand the hash table operations:
- Server is not currently in execution BGSAVE BGREWRITEAOF command or command, the load factor and the hash table is greater than or equal
1
; - The server is currently executing BGSAVE BGREWRITEAOF command or command, the load factor and the hash table is greater than or equal
5
;
Wherein the hash table can load factor by the formula:
# 负载因子 = 哈希表已保存节点数量 / 哈希表大小
load_factor = ht[0].used / ht[0].size
Calculated.
For example, for a size 4
that contains 4
a hash table of key-value pairs, the load factor of the hash table is:
load_factor = 4 / 4 = 1
Also, for example, for a size 512
that contains 256
a hash table of key-value pairs, the load factor of the hash table is:
load_factor = 256 / 512 = 0.5
根据 BGSAVE 命令或 BGREWRITEAOF 命令是否正在执行, 服务器执行扩展操作所需的负载因子并不相同, 这是因为在执行 BGSAVE命令或 BGREWRITEAOF 命令的过程中, Redis 需要创建当前服务器进程的子进程, 而大多数操作系统都采用写时复制(copy-on-write)技术来优化子进程的使用效率, 所以在子进程存在期间, 服务器会提高执行扩展操作所需的负载因子, 从而尽可能地避免在子进程存在期间进行哈希表扩展操作, 这可以避免不必要的内存写入操作, 最大限度地节约内存。
另一方面, 当哈希表的负载因子小于 0.1
时, 程序自动开始对哈希表执行收缩操作。