前言
什么是Hash和解决hash 冲突的方案:
哈希的本质是从一个较大空间映射到一个较小的空间,因此在插入数据足够多之后,根据鸽巢原理,一定会存在位置冲突。常见的哈希表(Hash Table 或者字典,dictionary)会通过链表、开放地址探测等方式来处理冲突。单桶多函数的布谷鸟哈希,便是开放地址法处理冲突的一种哈希表,只不过有冲突后,不是通过线性寻找新的位置,而是通过额外哈希函数来寻找。
DPDK 提供的Hash是采用Cuckoo Hase 实现。 DPDK Hash 具备一下特点:
- 每个条目有唯一的key标识;
- 所有key 占有相同大小的空间,空间大小有创建的时候设定;
一、什么是CUCKOO Hash
Cuckoo Hash Table是本次引入的数据结构,它用了两个哈希函数来解决冲突。
Cuckoo利用两个哈希函数来实现最差O(1)的查询复杂度:
- 对任意一个Key可求出两个哈希值,相当于映射到两个桶,如A被映射到1,4,说明它可以被存到1号或4号桶,而实际在1号桶。本图中,用箭头连接某个Key实际存入的桶和另一个对应的桶,如1—>4。
- 当插入一个F时,如果对应的两个桶至少有一个为空,则将其插入到这个位置,否则任选一个桶,不妨设为A所在的1号桶。我们将其中原有的A =Key’/Value’踢出,将新的F存入。对于刚取出的A,它之所以存储在1号桶是因为用了两个哈希函数之一,那么我们用另外一个哈希函数,知道A对应的位置还有4号桶。若4号桶为空,则将A放入,整个过程就结束了。而事实上,4号桶中还存有B
= Key’’/Value’’,那么把它们踢出并重复上面的操作。整个过程中进行踢出、填入操作的,形如“1->4-> … ->空位”这样的序列我们将其称为Cuckoo Kick路径。
- 当查询一个F时,分别检查它的的哈希值对应的两个位置即可。
二、常见 Hash特点
1.Hash 优点
- Cuckoo查询操作的理论复杂度为最差O(1),优于Dense的期望查询复杂度O(1)和Chain的O(1+α)。
- 而Cuckoo的插入复杂度为均摊O(1)
三、DPDK采用的Hash 原理
3.1 DPDK Hash libary 具体原理
3.2 DPDK Hash Table 具体实现
Hase table 包含两个表:
第一个表是一个桶数组构成,每个桶中具有相同数量的连续数组条目。每个条目包含计算的给定Key的主要和次要签名(hask index)(如下所述)和第二个表的索引。
第二个表是存储在哈希表中的所有Key的数组及其与每个Key相关联的数据。(Key + 8Byte integer 或者 key + ptr)
3.3存储的数据
**NODE**
只能在单线程模式下,使用的API: “rte_hash_set_cmp_func()”.
3.5 Hash bucket index
bucket
First table is an array of buckets each of which consists of multiple entrie.
bucket index
四、DPDK应用
Hash 可以用来实现 Flow Classification。流分类用于将每个输入数据包映射到它所属的连接/流。这种操作是必需的,因为每个输入分组的处理通常在其连接的上下文中进行,因此相同的操作集合被应用于来自相同流的所有分组。
使用流分类的每个应用通常具有被定义为从输入报文中读取一个或多个字段来构成Key,用于标识流。我们通常使用5-tuple 来标识一条流。