Nginx中对红黑树的使用

article/2025/4/24 16:55:37

nginx哪些地方用了红黑树

  • 一、Nginx定义的红黑树
  • 二、Nginx使用红黑树的地方
    • 2.1、ngx_cycle
    • 2.2、ngx_open_file_cache
  • 总结

一、Nginx定义的红黑树

Nginx定义的红黑树在/src/core/ngx_rbtree.h和/src/core/ngx_rbtree.c。定义了红黑树节点、红黑树、红黑树插入函数等等。

其中/src/core/ngx_rbtree.h的代码如下:


#ifndef _NGX_RBTREE_H_INCLUDED_
#define _NGX_RBTREE_H_INCLUDED_#include <ngx_config.h>
#include <ngx_core.h>typedef ngx_uint_t  ngx_rbtree_key_t;
typedef ngx_int_t   ngx_rbtree_key_int_t;typedef struct ngx_rbtree_node_s  ngx_rbtree_node_t;struct ngx_rbtree_node_s {ngx_rbtree_key_t       key;ngx_rbtree_node_t     *left;ngx_rbtree_node_t     *right;ngx_rbtree_node_t     *parent;u_char                 color;u_char                 data;
};typedef struct ngx_rbtree_s  ngx_rbtree_t;typedef void (*ngx_rbtree_insert_pt) (ngx_rbtree_node_t *root,ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);struct ngx_rbtree_s {ngx_rbtree_node_t     *root;ngx_rbtree_node_t     *sentinel;ngx_rbtree_insert_pt   insert;
};#define ngx_rbtree_init(tree, s, i)                                           \ngx_rbtree_sentinel_init(s);                                              \(tree)->root = s;                                                         \(tree)->sentinel = s;                                                     \(tree)->insert = ivoid ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
void ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node);
void ngx_rbtree_insert_value(ngx_rbtree_node_t *root, ngx_rbtree_node_t *node,ngx_rbtree_node_t *sentinel);
void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *root,ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
ngx_rbtree_node_t *ngx_rbtree_next(ngx_rbtree_t *tree,ngx_rbtree_node_t *node);#define ngx_rbt_red(node)               ((node)->color = 1)
#define ngx_rbt_black(node)             ((node)->color = 0)
#define ngx_rbt_is_red(node)            ((node)->color)
#define ngx_rbt_is_black(node)          (!ngx_rbt_is_red(node))
#define ngx_rbt_copy_color(n1, n2)      (n1->color = n2->color)/* a sentinel must be black */#define ngx_rbtree_sentinel_init(node)  ngx_rbt_black(node)static ngx_inline ngx_rbtree_node_t *
ngx_rbtree_min(ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
{while (node->left != sentinel) {node = node->left;}return node;
}#endif /* _NGX_RBTREE_H_INCLUDED_ */

二、Nginx使用红黑树的地方

Nginx使用红黑树的地方有:

  1. ngx_cycle。
  2. ngx_open_file_cache。
  3. ngx_resolver。
  4. ngx_event_openssl。
  5. ngx_event_timer。
  6. ngx_http_file_cache。
  7. ngx_http_geo_module。
  8. ngx_http_limit_conn_module。
  9. ngx_http_limit_req_module。
  10. ngx_stream_geo_module 。
  11. ngx_stream_limit_conn_module。

2.1、ngx_cycle

nginx的每个工作进程都有其自己的ngx_cycle。
在/src/core/ngx_cycle.h中定义的数据结构struct ngx_cycle_s引用了红黑树变量:

struct ngx_cycle_s{// ...ngx_rbtree_t              config_dump_rbtree;ngx_rbtree_node_t         config_dump_sentinel;// ...
}

(1)在nginx的main()函数中,会调用nginx_init_cycle函数初始化ngx_cycle_t。
/src/core/nginx.c

int ngx_cdecl
main(int argc, char *const *argv)
{// ...cycle = ngx_init_cycle(&init_cycle);if (cycle == NULL) {if (ngx_test_config) {ngx_log_stderr(0, "configuration file %s test failed",init_cycle.conf_file.data);}return 1;}// ...
}

(2)在nginx_init_cycle函数初始化红黑树。提供红黑树插入函数ngx_str_rbtree_insert_value。
/src/core/ngx_cycle.c

ngx_cycle_t *
ngx_init_cycle(ngx_cycle_t *old_cycle)
{
// ...ngx_rbtree_init(&cycle->config_dump_rbtree, &cycle->config_dump_sentinel,ngx_str_rbtree_insert_value);// ...
}

(3)在ngx_conf_add_dump函数轮询和插入红黑树节点。
/src/core/ngx_conf_file.c

static ngx_int_t
ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename)
{off_t             size;u_char           *p;uint32_t          hash;ngx_buf_t        *buf;ngx_str_node_t   *sn;ngx_conf_dump_t  *cd;hash = ngx_crc32_long(filename->data, filename->len);sn = ngx_str_rbtree_lookup(&cf->cycle->config_dump_rbtree, filename, hash);if (sn) {cf->conf_file->dump = NULL;return NGX_OK;}p = ngx_pstrdup(cf->cycle->pool, filename);if (p == NULL) {return NGX_ERROR;}cd = ngx_array_push(&cf->cycle->config_dump);if (cd == NULL) {return NGX_ERROR;}size = ngx_file_size(&cf->conf_file->file.info);buf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size);if (buf == NULL) {return NGX_ERROR;}cd->name.data = p;cd->name.len = filename->len;cd->buffer = buf;cf->conf_file->dump = buf;sn = ngx_palloc(cf->temp_pool, sizeof(ngx_str_node_t));if (sn == NULL) {return NGX_ERROR;}sn->node.key = hash;sn->str = cd->name;ngx_rbtree_insert(&cf->cycle->config_dump_rbtree, &sn->node);return NGX_OK;
}

(4)ngx_conf_add_dump被ngx_conf_parse调用

/src/core/ngx_conf_file.c

char *
ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
{
// ...if (ngx_dump_config
#if (NGX_DEBUG)|| 1
#endif){if (ngx_conf_add_dump(cf, filename) != NGX_OK) {goto failed;}} else {cf->conf_file->dump = NULL;}
// ...
}

(5)红黑树使用流程图:

ngx_rbtree.c
ngx_string.c
ngx_conf_file.c
ngx_rbtree.h
ngx_cycle.c
nginx.c
call
call
call
call
call
call
call
ngx_rbtree_insert()
ngx_str_rbtree_lookup()
ngx_conf_add_dump()
ngx_conf_parse()
ngx_rbtree_init()
ngx_init_cycle()
main()
其他函数

2.2、ngx_open_file_cache

ngx_open_file_cache_t是文件缓存,主要在ngx_http_log_module、ngx_http_core_module、ngx_stream_log_module几个模块中使用。
在/src/core/ngx_open_file_cache.h中定义的数据结构struct ngx_cycle_s引用了红黑树变量:

// ...
struct ngx_cached_open_file_s {ngx_rbtree_node_t        node;ngx_queue_t              queue;u_char                  *name;time_t                   created;time_t                   accessed;ngx_fd_t                 fd;ngx_file_uniq_t          uniq;time_t                   mtime;off_t                    size;ngx_err_t                err;uint32_t                 uses;#if (NGX_HAVE_OPENAT)size_t                   disable_symlinks_from;unsigned                 disable_symlinks:2;
#endifunsigned                 count:24;unsigned                 close:1;unsigned                 use_event:1;unsigned                 is_dir:1;unsigned                 is_file:1;unsigned                 is_link:1;unsigned                 is_exec:1;unsigned                 is_directio:1;ngx_event_t             *event;
};typedef struct {ngx_rbtree_t             rbtree;ngx_rbtree_node_t        sentinel;ngx_queue_t              expire_queue;ngx_uint_t               current;ngx_uint_t               max;time_t                   inactive;
} ngx_open_file_cache_t;// ...

(1)红黑树的初始化在ngx_open_file_cache_init函数中调用。
/src /core/ngx_open_file_cache.c

ngx_open_file_cache_t *
ngx_open_file_cache_init(ngx_pool_t *pool, ngx_uint_t max, time_t inactive)
{
// ...ngx_rbtree_init(&cache->rbtree, &cache->sentinel,ngx_open_file_cache_rbtree_insert_value);
// ...
}

(2)ngx_http_log_module模块的ngx_http_log_commands中注册了ngx_http_log_open_file_cache。ngx_http_log_open_file_cache会调用ngx_open_file_cache_init做初始化。

/src/http/modules/ngx_http_log_module.c


static char *
ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{// ...llcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);if (llcf->open_file_cache) {llcf->open_file_cache_valid = valid;llcf->open_file_cache_min_uses = min_uses;return NGX_CONF_OK;}return NGX_CONF_ERROR;
}static ngx_command_t  ngx_http_log_commands[] = {{ ngx_string("log_format"),NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,ngx_http_log_set_format,NGX_HTTP_MAIN_CONF_OFFSET,0,NULL },{ ngx_string("access_log"),NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_1MORE,ngx_http_log_set_log,NGX_HTTP_LOC_CONF_OFFSET,0,NULL },{ ngx_string("open_log_file_cache"),NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,ngx_http_log_open_file_cache,NGX_HTTP_LOC_CONF_OFFSET,0,NULL },ngx_null_command
};ngx_module_t  ngx_http_log_module = {NGX_MODULE_V1,&ngx_http_log_module_ctx,              /* module context */ngx_http_log_commands,                 /* module directives */NGX_HTTP_MODULE,                       /* module type */NULL,                                  /* init master */NULL,                                  /* init module */NULL,                                  /* init process */NULL,                                  /* init thread */NULL,                                  /* exit thread */NULL,                                  /* exit process */NULL,                                  /* exit master */NGX_MODULE_V1_PADDING
};

(3)ngx_http_core_module模块的ngx_http_core_commands中注册了ngx_http_core_open_file_cache。ngx_http_core_open_file_cache会调用ngx_open_file_cache_init做初始化。

/src/http/modules/ngx_http_core_module.c

static char *
ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{// ...clcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);if (clcf->open_file_cache) {return NGX_CONF_OK;}return NGX_CONF_ERROR;
}static ngx_command_t  ngx_http_core_commands[] = {// ...{ ngx_string("open_file_cache"),NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,ngx_http_core_open_file_cache,NGX_HTTP_LOC_CONF_OFFSET,offsetof(ngx_http_core_loc_conf_t, open_file_cache),NULL },// ...
}ngx_module_t  ngx_http_core_module = {NGX_MODULE_V1,&ngx_http_core_module_ctx,             /* module context */ngx_http_core_commands,                /* module directives */NGX_HTTP_MODULE,                       /* module type */NULL,                                  /* init master */NULL,                                  /* init module */NULL,                                  /* init process */NULL,                                  /* init thread */NULL,                                  /* exit thread */NULL,                                  /* exit process */NULL,                                  /* exit master */NGX_MODULE_V1_PADDING
};

(4)ngx_stream_log_module模块的ngx_stream_log_commands中注册了ngx_stream_log_open_file_cache。ngx_stream_log_open_file_cache会调用ngx_open_file_cache_init做初始化。

/src/http/modules/ngx_stream_log_module.c

static char *
ngx_stream_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{// ...lscf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);if (lscf->open_file_cache) {lscf->open_file_cache_valid = valid;lscf->open_file_cache_min_uses = min_uses;return NGX_CONF_OK;}return NGX_CONF_ERROR;
}static ngx_command_t  ngx_stream_log_commands[] = {{ ngx_string("log_format"),NGX_STREAM_MAIN_CONF|NGX_CONF_2MORE,ngx_stream_log_set_format,NGX_STREAM_MAIN_CONF_OFFSET,0,NULL },{ ngx_string("access_log"),NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_1MORE,ngx_stream_log_set_log,NGX_STREAM_SRV_CONF_OFFSET,0,NULL },{ ngx_string("open_log_file_cache"),NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1234,ngx_stream_log_open_file_cache,NGX_STREAM_SRV_CONF_OFFSET,0,NULL },ngx_null_command
};static ngx_stream_module_t  ngx_stream_log_module_ctx = {NULL,                                  /* preconfiguration */ngx_stream_log_init,                   /* postconfiguration */ngx_stream_log_create_main_conf,       /* create main configuration */NULL,                                  /* init main configuration */ngx_stream_log_create_srv_conf,        /* create server configuration */ngx_stream_log_merge_srv_conf          /* merge server configuration */
};ngx_module_t  ngx_stream_log_module = {NGX_MODULE_V1,&ngx_stream_log_module_ctx,            /* module context */ngx_stream_log_commands,               /* module directives */NGX_STREAM_MODULE,                     /* module type */NULL,                                  /* init master */NULL,                                  /* init module */NULL,                                  /* init process */NULL,                                  /* init thread */NULL,                                  /* exit thread */NULL,                                  /* exit process */NULL,                                  /* exit master */NGX_MODULE_V1_PADDING
};

(5)红黑树使用流程图:

ngx_rbtree.c
ngx_stream_log_module.c
ngx_http_core_module.c
ngx_http_log_module.c
ngx_open_file_cache.c
ngx_rbtree.h
注册
注册
注册
注册
注册
注册
注册
call
call
call
call
call
call
call
call
ngx_rbtree_delete()
ngx_rbtree_insert()
ngx_stream_log_open_file_cache()
ngx_command_t ngx_stream_log_commands[]
ngx_module_t ngx_stream_log_module
ngx_http_core_open_file_cache()
ngx_command_t ngx_http_core_commands[]
ngx_module_t ngx_http_core_module
ngx_http_log_open_file_cache()
ngx_command_t ngx_http_log_commands[]
ngx_module_t ngx_http_log_module
ngx_open_file_cache_cleanup()
ngx_open_file_cache_init()
ngx_open_cached_file()
ngx_rbtree_init()
其他函数

总结

Nginx在很多地方使用了红黑树,nginx红黑树的使用基本是这样的流程:

  1. 定义红黑树变量。可以是在单独定义或者作为结构体的成员。
  2. 初始化红黑树,ngx_rbtree_init(),并提供插入value的函数,比如nginx内部实现的ngx_str_rbtree_insert_value() 。
  3. 初始化完成后,就可以在需要的地方调用ngx_rbtree_delete()、ngx_rbtree_insert()等函数。

在这里插入图片描述


http://chatgpt.dhexx.cn/article/wQW15B8H.shtml

相关文章

为什么要有红黑树?什么是红黑树?画了20张图,看完这篇你就明白了

为什么要有红黑树 想必大家对二叉树搜索树都不陌生&#xff0c;首先看一下二叉搜索树的定义&#xff1a; 二叉搜索树&#xff08;Binary Search Tree&#xff09;&#xff0c;或者是一棵空树&#xff0c;或者是具有下列性质的二叉树&#xff1a; 若它的左子树不空&#xff0c;…

“红黑树”详解丨红黑树的应用场景

今天我们要说的红黑树就是就是一棵非严格均衡的二叉树&#xff0c;均衡二叉树又是在二叉搜索树的基础上增加了自动维持平衡的性质&#xff0c;插入、搜索、删除的效率都比较高。红黑树也是实现 TreeMap 存储结构的基石。 文章相关视频讲解&#xff1a; 红黑树在linux中的3种应…

AVL树与红黑树(RBTree)的概念与区别

要想了解AVL树与红黑树的区别&#xff0c;首先我们要先知道&#xff0c;这两棵树是属于自平衡二叉树&#xff0c;那么什么是平衡二叉树呢&#xff1f; 一、平衡二叉树 二叉树的每一个节点的左右子树的深度差不超过1。 二、如何实现自平衡&#xff1f; 通过旋转&#xff0c;…

HashMap 链表与红黑树转换

链表转换为红黑树 //此处遍历链表for (int binCount 0; ; binCount) {//遍历到链表最后一个节点if ((e p.next) null) {p.next newNode(hash, key, value, null);//如果链表元素个数大于等于TREEIFY_THRESHOLDif (binCount > TREEIFY_THRESHOLD - 1) // -1 for 1st//红黑…

为什么要有红黑树?什么是红黑树?

为什么要有红黑树 想必大家对二叉树搜索树都不陌生&#xff0c;首先看一下二叉搜索树的定义&#xff1a;二叉搜索树&#xff08;Binary Search Tree&#xff09;&#xff0c;或者是一棵空树&#xff0c;或者是具有下列性质的二叉树&#xff1a; 若它的左子树不空&#xff0c;则…

HashMap与红黑树

一、为什么需要HashMap? 在我们写程序的时候经常会遇到数据检索等操作&#xff0c;对于几百个数据的小程序而言&#xff0c;数据的存储方式或是检索策略没有太大影响&#xff0c;但对于大数据&#xff0c;效率就会差很远。 1、线性检索&#xff1a; 线性检索是最为直白的方法…

数据结构:什么是红黑树?为什么要用红黑树?

本篇主要谈谈对红黑树的理解&#xff0c;大家都晓得JDK8中的hashmap底层是数组链表红黑树实现的&#xff0c;当面试官问你&#xff1a;为啥要加上红黑树实现呢&#xff1f;&#xff1f; 那我们首先从概念来了解一下&#xff1a; 一、什么是红黑树&#xff1f; 红黑树是一个接…

随处可见的红黑树详解

随处可见的红黑树详解 前言为什么要有红黑树二叉搜索树平衡二叉搜索树红黑树 红黑树的应用场景红黑树的性质&#xff08;重点&#xff09;红黑树的定义红黑树的左旋与右旋红黑树插入结点与插入维护红黑树的三种情况插入结点插入结点后维护红黑树父结点是爷结点是左子树1. 叔结点…

HashMap-链表与红黑树转换触发条件

JDK1.8对HashMap进行了很多优化。 例如当一个槽位slot上的链表个数过多时&#xff0c;则会将链表转换为红黑树&#xff0c;以提高查询检索的效率。 访问节点方式&#xff1a;先找到节点所在的数组index索引位置&#xff0c;然后判断节点是什么结构进行遍历。 节点结构是非树…

9.HashMap里的红黑树是什么

1. 简介 红黑树是一种自平衡二叉查找树。它的统计性能要好于平衡二叉树&#xff08;AVL树&#xff09;&#xff0c;因此&#xff0c;红黑树在很多地方都有应用。在C STL中&#xff0c;很多部分(目前包括set, multiset, map,multimap)应用了红黑树的变体(SGI STL中的红黑树有一…

算法:什么是红黑树

红黑树的定义 红黑树的英文是“Red-Black Tree”&#xff0c;简称 R-B Tree。它是一种不严格的平衡二叉查找树。顾名思义&#xff0c;红黑树中的节点&#xff0c;一类被标记为黑色&#xff0c;一类被标记为红色。除此之外&#xff0c;一棵红黑树还需要满足这样几个要求&#x…

pygraphviz的安装与红黑树可视化

大家好&#xff0c;我是小小明&#xff0c;今天我将带大家安装pygraphviz&#xff0c;并通过它对红黑树这种数据结构进行可视化。 pygraphviz的安装与红黑树的可视化 安装graphviz 下载地址&#xff1a;http://www.graphviz.org/download/ windows平台下可以选择&#xff1…

到底什么是红黑树?

到底什么是红黑树&#xff1f; 首先&#xff0c;可以这么简单粗暴的理解&#xff0c;红黑树≈平衡的二叉排序树。 那么很显然&#xff0c;要想弄懂红黑树&#xff0c;得先明白什么是树、二叉树、二叉排序树、平衡树以及不平衡树。下面我们一个个来了解。 1.第一个问题&#x…

面试常问:什么是红黑树?

什么是红黑树&#xff1f; ———————————— 二叉查找树&#xff08;BST&#xff09;具备什么特性呢&#xff1f; 1.左子树上所有结点的值均小于或等于它的根结点的值。 2.右子树上所有结点的值均大于或等于它的根结点的值。 3.左、右子树也分别为二叉排序树。 下图…

红黑树简介

一、什么是红黑树 红黑树&#xff08;Red Black Tree&#xff09; 是一种自平衡二叉查找树&#xff0c;是在计算机科学中用到的一种数据结构&#xff0c;典型的用途是实现关联数组。 红黑树是在1972年由Rudolf Bayer发明的&#xff0c;当时被称为平衡二叉B树&#xff08;symme…

什么是红黑树?

一、红黑树的产生 1.二叉树 定义&#xff1a;二叉树&#xff08;binary tree&#xff09;是指树中节点的度不大于2的有序树&#xff0c;它是一种最简单且最重要的树。二叉树的递归定义为&#xff1a;二叉树是一棵空树&#xff0c;或者是一棵由一个根节点和两棵互不相交的&…

说说什么是红黑树?

分析&回答 红黑树介绍 R-B Tree&#xff0c;全称是Red-Black Tree&#xff0c;又称为“红黑树”&#xff0c;红黑树就是一种平衡的二叉查找树&#xff0c;说他平衡的意思是他不会变成“瘸子”&#xff0c;左腿特别长或者右腿特别长。除了符合二叉查找树的特性之外&#xf…

漫画:什么是红黑树?(整合版)

前段时间&#xff0c;小灰发布了红黑树相关的文章&#xff0c;分成上下篇来讲解。 这一次&#xff0c;小灰把两篇文章做了整合&#xff0c;并且修正了红黑树删除部分的图片错误&#xff0c;感谢大家的指正。 ————— 第二天 ————— ———————————— 二叉查找…

抗性基因数据库CARD介绍

随着抗生素药物的发现及使用&#xff0c;越来越多的耐药菌株由此产生。而耐药菌株的发展则会增加疾病治疗的难度和成本&#xff0c;因此耐药微生物的研究则显得尤为重要。目前&#xff0c;通过对耐药基因的鉴定挖掘能够一定程度上帮助我们揭开耐药机制&#xff0c;为疾病的治疗…