Nginx基础. Nginx基本哈希表

本文探讨了Nginx中哈希表的独特性质,它在运行时是静态且只读的,这意味着所有结构和数据在配置初始化阶段就已确定。哈希表的初始化对于运行时查找性能至关重要。
摘要由CSDN通过智能技术生成
根据以往的学习经验, 比如STL中的哈希表, 利用开链法, vector+list作为容器, 当hashtable中的元素总数超过一定数量时, 选择扩充vector.
再比如libevent中的哈希表, 与STL中的哈希表类似, 但比较复杂, 每个bucket中都可能有一个链表,每个链表元素中也可能存在一个链表. 但理解起来都并不复杂.
现在看的Nginx中的哈希表, 则与上面谈到的哈希有很明显的不同之处.

在nginx中, 存储server_name和ngx_http_core_srv_conf_t的映射时用到了hash结构.
配置server_names_hash_max_size可以控制bucket的最大数量,server_names_hash_bucket_size可以控制每个bucket的大小
下图, 就是nginx存储不含通配符的server_name时使用的hash结构:
             


       进行解释之前, 需要提一下, nginx中的哈希表一个特别之处在于, 这个hash表是静态只读的,即不能在运行时动态添加新元素的,一切的结构和数据都在配置初始化的时候就已经规划完毕,所以“init”过程的优劣,对运行时查找的性能影响非常大

        我们假设哈希表的bucket数量为size , 每个元素的哈希值为 [hash%size], 从上图可以看到, 此哈希表解决冲突的办法类似开链, 但又并不是使用链表来存储具有相同 [hash%size] 值的元素, 而是令具有相同[hash%size]值的元素存放在一块连续的内存中, 以一个NULL指针作为结尾. 上面我们说到了两个可以控制bucket的最大数量和每个bucket的大小的配置, 但并没有说这个哈希表的bucket数量到底是多少. 试想, 当前我们的bucket大小是确定的, 假如冲突太多, 即有多个元素被存放在同一个bucket, 这样肯定会导致某bucket"超载". 那么解决的办法就是扩大bucket的数量, 即size的值(这样不仅能使原来具有相同[hash%size]的元素不再相同, 还能使冲突发生的更稀疏). 看看能不能保证所有存放多个相同 [hash%size]的元素的bucket不"超载". 但是既然我们设定了bucket的最大数量, 一旦size达到这个值还没能满足我们的要求, 那么就返回错误.
同时, 每个bucket的大小必须能保证存放至少一个元素.无论这个元素的大小是多少.
好了, 大致的介绍就到这里. 下面是详细的代码分析.




一、 数据结构的定义

1、基本哈希表的元素
每个元素都是 key-value的形式
typedef struct {
    void             *value;            //即为key-value中对应的value
    u_short           len;              //为key-value中key的长度
    u_char            name[1];          //为key的首地址. 使用长度为1的数组是为了将来申请的len大小的空间是连续的(详细的请搜索 "0或1长度数组")
} ngx_hash_elt_t;

2、基本哈希表结构
typedef struct {
    ngx_hash_elt_t  **buckets;          //即为哈希表
    ngx_uint_t        size;             //哈希表中bucket的个数
} ngx_hash_t;

3、支持通配符的哈希表结构
其实也就是多了一个额外的value指针, 当使用ngx_hash_wildcard_t通配符哈希表作为容器元素时,可以使用value指向用户数据。
这里暂时不做多解释
typedef struct {
    ngx_hash_t        hash;
    void             *value;
} ngx_hash_wildcard_t;

4、该结构也主要用来保存要hash的数据,即键-值对<key,value>
在实际使用中,一般将多个键-值对保存在ngx_hash_key_t结构的数组中,作为参数传给ngx_hash_init()或ngx_hash_wildcard_init()函数
用于表示即将添加到哈希表中的元素
typedef struct {
    ngx_str_t         key;
    ngx_uint_t        key_hash;         //由哈希函数根据key计算出的值. 将来此元素代表的结构体会被插入bucket[key_hash % size]
   
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值