【redis】redis之rehash

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:

  1. 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 the  ht[0] key number included in the current (i.e., a  ht[0].used value of the property):
    • If the expansion operation is performed, then the  ht[1] size of greater than or equal to the first  ht[0].used * 2 of 2 ^ n ( 2 a  n power of power);
    • If the shrink operation is performed, then the  ht[1] size of greater than or equal to the first  ht[0].used of 2 ^ n.
  2. Will be saved in  ht[0] all the key values to rehash  ht[1] above: rehash refers to recalculate the hash value and the index key value, then the key-value pair is placed into  ht[1]the specified location on the hash table.
  3. When  ht[0] all key-value pairs are contained moved to  ht[1] after ( ht[0] becomes empty table), release  ht[0] the  ht[1] set  ht[0] , and in  ht[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:

  1. ht[0].used Current value  4 ,  4 * 2 = 8 while  8 (2 ^ 3) happens to be the first greater than or equal  4 to  2 the  n power, so the program will  ht[1] hash table size is set  8 . Figure 4-9 shows the  ht[1] following distribution space, dictionary look.
  2. It will  ht[0] contain four key-value pairs to rehash  ht[1] , shown in Figure 4-10.
  3. Release  ht[0] , and  ht[1] set  ht[0] , and then to  ht[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 .

digraph {      label = "\n 图 4-8    执行 rehash 之前的字典";      rankdir = LR;      node [shape = record];      // 字典      dict [label = " <head> dict | type | privdata | <ht> ht | rehashidx \n -1 "];      // 哈希表      dictht0 [label = " <head> dictht | <table> table | <size> size \n 4 | <sizemask> sizemask \n 3 | <used> used \n 4"];      dictht1 [label = " <head> dictht | <table> table | <size> size \n 0 | <sizemask> sizemask \n 0 | <used> used \n 0"];      table0 [label = " <head> dictEntry*[4] | <0> 0 | <1> 1 | <2> 2 | <3> 3 "];      table1 [label = "NULL", shape = plaintext];      // 哈希表节点      kv0 [label = " <head> dictEntry | { k0 | v0 } "];     kv1 [label = " <head> dictEntry | { k1 | v1 } "];     kv2 [label = " <head> dictEntry | { k2 | v2 } "];     kv3 [label = " <head> dictEntry | { k3 | v3 } "];      //      node [shape = plaintext, label = "NULL"];      null0;     null1;     null2;     null3;      //      dict:ht -> dictht0:head [label = "ht[0]"];     dict:ht -> dictht1:head [label = "ht[1]"];      dictht0:table -> table0:head;     dictht1:table -> table1;      table0:0 -> kv2:head -> null0;     table0:1 -> kv0:head -> null1;     table0:2 -> kv3:head -> null2;     table0:3 -> kv1:head -> null3;  }

graphviz-b68acb4d868ec7d79a44935ce08a159746ca58da.png

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:

  1. Server is not currently in execution BGSAVE BGREWRITEAOF command or command, the load factor and the hash table is greater than or equal  1 ;
  2. 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 时, 程序自动开始对哈希表执行收缩操作。

Guess you like

Origin blog.csdn.net/bible_reader/article/details/97103674