最近想用libuv写个http服务器,看到了这个开源项目haywire,在看到第39次提交的时候,作者用基数树来存储不同路由的controller,不过在后续版本中改为了使用hash,不过想来不如正好学学基数树,作者使用的基数树是这个版本radix_tree,这个版本缺少注释,且和一般思路不一样的使用的是二叉树而非N叉树,为了理解方便,我选择了注释较多的rax


数据结构

  首先要提到的是rax的数据结构设计:

typedef struct raxNode {uint32_t iskey:1;     /* Does this node contain a key? */uint32_t isnull:1;    /* Associated value is NULL (don't store it). */uint32_t iscompr:1;   /* Node is compressed. */uint32_t size:29;     /unsigned char data[];
} raxNode;

这里第一个要说到的点是:你觉得这样一个数据结构的大小是多少?24? 16? 还是8?

  第一个原因是位域,也就是结构体中的冒号: ,冒号在这里声明实际需要使用的位数,iskey,isnull,iscompr,size四个一共加起来32位,占4个字节。
  第二个原因是data[]占0个字节。unsigned char data[];这样一个结构在这里并不是理解成一个指针8个字节。而是一个柔性数组的概念,实现一个可变长度。data[1]占结构体1个字节,data[2]占结构体2个字节…data[13]占13个字节。数组类型的内存是结构体中直接分配的,而不是像指针一样需要我们后来分配。如下图可见:

typedef struct raxNode {unsigned char data[13];
} raxNode;int main(int argc, char *argv[])
{printf("%d\n", sizeof(raxNode));return 0;
}


data[]

  接下来我们还是要谈data,在这里data的意义并不是一个简单的unsigned char数组,它存储的是键值key和radixNode指针两种变量。

图来自:https://my.oschina.net/yunqi/blog/3039132
data的实际使用方式在大多数时候是以内存地址的方式进行的。

#define raxNodeLastChildPtr(n) ((raxNode**) ( \((char*)(n)) + \raxNodeCurrentLength(n) - \sizeof(raxNode*) - \(((n)->iskey && !(n)->isnull) ? sizeof(void*) : 0) \
))

  这是访问最后一个节点的函数(也就是访问图中的A-ptr)。n是一个raxNode*指针,对这个指针指向的地址进行+操作来得到最后一个节点的地址。


节点的表示

图来自:https://my.oschina.net/yunqi/blog/3039132
  假设基数树中有“abcd”这个键值的节点。那么它的表示形式是像上图这样的。“abcd”这个节点的value-data存储在图片下半部分的节点处,并且下面一个节点iskey设为1.
  为什么不是直接只有图片的上半部分,由图片上半部分那个节点将iskey设置为1并且将值存储在其value·data中呢?
像这样: [iskey:1][isnull: 0][iscompr:1][size:4][abcd] [z-ptr ][value-ptr]

先给出结论: 在rax中一个节点的存在(iskey == 1)是由data中对应的子节点来表示的。

原因很简单:

在这个例子里面,这是一个没有压缩的节点,这一层由a和A两个子节点,如果在当前层次表示,如何分辨你指定的是a还是A?所以用引出子节点来表示。

这是我边看rax边实现的一个小练习,欢迎大家指教:https://github.com/LurenAA/radix_tree ,好想要个star,求求了,兄弟萌?

redis基数树rax源码分析(1)相关推荐

  1. 霸榜巨作、阿里内部顶级专家整理(Redis 5设计与源码分析)

    前言 在开源界,高性能服务的典型代表就是Nginx和Redis.纵观这两个软件的源码,都是非常简洁高效的,也都是基于异步网络I/O机制的,所以对于要学习高性能服务的程序员或者爱好者来说,研究这两个网络 ...

  2. 新书推荐 |《Redis 5设计与源码分析》

    新书推荐 <Redis 5设计与源码分析> 点击上图了解及购买 好未来.滴滴.百度等公司专家联合撰写,掌握Redis 5设计与命令实现,透彻掌握分布式缓存. 编辑推荐 多名专家联袂推荐,资 ...

  3. 【作者面对面问答】包邮送《Redis 5设计与源码分析》5本

    墨墨导读:本文节选自<Redis 5设计与源码分析>,主要为读者分析Redis高性能内幕,重点从源码层次讲解了Redis事件模型,网络IO事件重在使用IO复用模型,时间事件重在限制最大执行 ...

  4. Redis分布式锁解析源码分析

    Redis分布式锁解析&源码分析 概述 实战 简单的分布式锁 Redisson实现分布式锁 Redission源码分析 构造方法 获取锁lock 解锁 锁失效 红锁 案例分析 原始的写法 进化 ...

  5. Redis 过期策略与源码分析

    在 Redis 中我们可以给一些元素设置过期时间,那当它过期之后 Redis 是如何处理这些过期键呢? 过期键执行流程 Redis 之所以能知道那些键值过期,是因为在 Redis 中维护了一个字典,存 ...

  6. Redis集群模式源码分析

    目录 1 主从复制模式 2 Sentinel(哨兵)模式 3 Cluster模式 4.参考文档 1 主从复制模式 主库负责读写操作,从库负责数据同步,接受来自主库的同步命令.通过分析Redis的客户端 ...

  7. redis之十一(Redis 过期策略与源码分析)

    在 Redis 中我们可以给一些元素设置过期时间,那当它过期之后 Redis 是如何处理这些过期键呢? 过期键执行流程 Redis 之所以能知道那些键值过期,是因为在 Redis 中维护了一个字典,存 ...

  8. 树回归源码分析(1)

    线性回归包含了强大的方法,但是需要拟合所有的数据集(局部加权线性回归除外),但是当数据特征复杂时,构建全局模型就难了,况且实际生活很多问题都是非线性的,不可能使用全局线性模型来拟合所有的数据. 现有可 ...

  9. Redis源码分析:基础概念介绍与启动概述

    Redis源码分析 基于Redis-5.0.4版本,进行基础的源码分析,主要就是分析一些平常使用过程中的内容.仅作为相关内容的学习记录,有关Redis源码学习阅读比较广泛的便是<Redis设计与 ...

最新文章

  1. linux ubuntu安装 mono,在Ubuntu 18.04系统中安装Mono及基本使用Mono的方法
  2. jquery操作select取值赋值与设置选中[转]
  3. 一旦上了CRM系统 就期待短期见效?
  4. 指导你成为C++编程高手的魔幻之书——写给大家看的C++书
  5. 计算机硬件的作用论文,计算机硬件的作用论文.doc
  6. [导入]ubuntu全面介绍 与 ubuntu截图
  7. idea 设置识别ini文件
  8. 8.10-11 mount、umount
  9. Log4net使用简介
  10. c++利用windows api遍历指定文件夹及其子文件夹中的文件
  11. 智能优化算法:类电磁机制算法 - 附代码
  12. GitHub配置SSH key
  13. 一阶惯性加纯滞后模型matlab代码,一种镇定一阶惯性加纯滞后系统的线性自抗扰控制器设计方法与流程...
  14. 软考中级网络工程师学习笔记(知识点汇总)普通版
  15. 百度NLP词 语相似度接口Demo
  16. 工作中遇到的小技巧 一(暂停更新)
  17. 小米路由硬盘版搭建ftp服务和博客
  18. 王者荣耀貂蝉唤灵魅影技能特效展示 唤灵魅影何时上架
  19. 微信刷脸支付php后端,2.1 微信刷脸支付初始化
  20. 使用MQTTNet包实现客户端与服务端通讯

热门文章

  1. NandFlash基础知识-K9F2G08
  2. 企业CMS网站建设第二课:CMS模版开发——CMS基础设置与栏目管理
  3. c++ 运行出现0x0000007 错误解决总结
  4. java replace 忽略大小写_java替换字符串时忽略大小写
  5. week09_day0203_CSS
  6. 扫地机器人自动回冲工作原理
  7. (转)任正非对新员工的寄语:烧不死的就是凤凰
  8. html 在线打开pdf文件怎么打开,在HTML中打开pdf文件怎么打开
  9. 【ospf的三类LSA sum-net】(真假ABR、区域间防环机制、vlink)
  10. 不用远程软件,校园网电脑之间如何远程连接