一、MMDB简介

MMDB(MaxMind Database) 是MaxMind推出的一个数据存储和检索的数据库格式,用于旗下针对IP检索和存储的Geo产品。
IP格式由二进制比特数组组成,很容易想到每个比特对应二叉树一个节点,可以说二叉树检索特别适合于IP格式。
MMDB的构造过程正是把一颗数据位于叶子节点的二叉树进行序列化。
序列化后是字节数组,和其他检索格式都是反序列化为结构化的内存形式不同,MMDB检索时把整个mmdb文件加载为一个字节数组即可。
检索过程在字节数组上操作,由于每个节点大小固定,通过简单内存计算即可完成节点定位,不需要额外生成其他中间结构,可以说非常简洁和高效。
Maxmind的GeoIP产品用于检索以下网段的geo信息,其中最左一列是网段,第二列是geoname_id。根据网段找到geoname_id,再根据geoname_id找到下图的数据。

二、构造过程

构造过程是生成一颗二叉检索树的过程。
假设只存储一个网段“110”的数据,则可以得到二叉树为:

只有叶子节点会存储指向数据的引用。

三、MMDB总体格式

二叉树经过序列化会得到一个字节数组,数据格式如下图:

节点序列存储二叉树的节点,数据信息则存储在数据序列中,数据使用MMDB序列化格式(类似json)。
第三部分为元数据,存储版本号、生成时间、数据库类型、IP版本、语言、节点个数、节点记录规格等。检索过程需要使用这些进行内存寻址来完成节点位置的计算。
第一个分隔符为16字节的"NULL",即16个0。
第二个分隔符为"\xAB\xCD\xEFMaxMind.com"。

四、节点序列说明

节点序列等于一个节点数组,每个节点由两个记录组成,分别对应二叉树的左孩子和右孩子。

在IP检索中,比特0对应第一个记录,比特1对应第二个记录。

如上图所示,包含3个节点,第一个节点的两个记录为3和1,第二个节点为3和2,第三个节点为19和3。

当记录数等于节点数3时,表示没找到数据。当记录数大于节点数3时,则为数据节点的记录值。

数据偏移量的计算公式:数据偏移量 = 记录值 - 节点个数 - 16(分隔符的长度)。

第三个节点记录19表示数据偏移量为0,19-3(节点数)-16。

五、检索算法

在一个总节点数为3的mmdb数据库上,网段“110”的检索过程

六、数据段说明

数据序列由数据头和数据组成,数据头记录数据类型和数据大小,目前MMDB支持多种数据类型,包括int, string, map, bytes等。
程序读到字节数组后通过反序列化得到实际数据。

七、实验例子

1、构造一个网段为“192.2.10.0/3”,对应二进制网络“110”的节点,数据为{"iso":156,"country_name":"China"},生成的节点序列为:

注意:上图每三个字节存储一个记录,中间16个0是分隔符。格式化打印后得到下图,符号“-”表示空节点:

可以看到“110”网段根据二叉树检索算法得到数据段的偏移量19,则数据段偏移量为19-3(节点数)-16=0。

2、再加入一个网段为“64.2.10.0/3”,对应二进制网络“010”的节点,数据为{"iso":826,"country_name":"England"},生成的节点序列为:

格式化打印后得到下图,符号“-”表示空节点:

可以看到“010”网段根据二叉树检索算法得到数据段的偏移量21,则数据段偏移量为21-5(节点数)-16=0。而此时“110”网段的数据段的偏移量变成了50,则数据段偏移量为50-5(节点数)-16=29。

八、总结

1、生成过程使用二叉树。

2、存储和检索都是序列化字节数组格式。

3、MMDB是内存数据库 。

参考链接

MaxMind DB File Format Specification

Enriching MMDB files with your own data using go

Building your own MMDB database for fun and profit

基于二叉树的高效IP检索格式MMDB的更多相关文章

  1. 【转】TCP/IP报文格式

    1.IP报文格式 IP协议是TCP/IP协议族中最为核心的协议.它提供不可靠.无连接的服务,也即依赖其他层的协议进行差错控制.在局域网环境,IP协议往往被封装在以太网帧(见本章1.3节)中传送.而所有 ...

  2. TCP,UDP,IP包头格式及说明(zz)

    一.MAC帧头定义 /数据帧定义,头14个字节,尾4个字节/ typedef struct _MAC_FRAME_HEADER { ]; //目的mac地址 ]; //源mac地址 short m_c ...

  3. [大牛翻译系列]Hadoop(19)MapReduce 文件处理:基于压缩的高效存储(二)

    5.2 基于压缩的高效存储(续) (仅包括技术27) 技术27 在MapReduce,Hive和Pig中使用可分块的LZOP 如果一个文本文件即使经过压缩后仍然比HDFS的块的大小要大,就需要考虑选择 ...

  4. [大牛翻译系列]Hadoop(18)MapReduce 文件处理:基于压缩的高效存储(一)

    5.2 基于压缩的高效存储 (仅包括技术25,和技术26) 数据压缩可以减小数据的大小,节约空间,提高数据传输的效率.在处理文件中,压缩很重要.在处理Hadoop的文件时,更是如此.为了让Hadoop ...

  5. 以太网帧、TCP与UDP段以及IP数据报格式总结

    传输层及其以下的机制由内核提供,是操作系统的一部分,应⽤层由⽤户进程提供应⽤层数据通过协议栈发到⽹络上时,每层协议都要加上⼀个数据⾸部(header),称为封装.不同的协议层对数据包有不同的称谓,在传 ...

  6. 计算机网络(3)-----IP数据报格式

    IP数据报(IP Datagram) 格式 解析 (1)版本 占4位,指IP协议的版本.通信双方使用的IP协议版本必须一致.目前广泛使用的IP协议版本号为4(即IPv4). (2)首部长度 占4位,可 ...

  7. TCP/IP包格式详解

    文章参考地址:http://blog.chinaunix.net/uid-20698826-id-4700710.html http://blog.csdn.net/mrwangwang/articl ...

  8. 一种基于重载的高效c#上图片添加文字图形图片的方法

    在做图片监控显示的时候,需要在图片上添加文字,如果用graphics类绘制图片上的字体,实现图像上添加自定义标记,这种方法经验证是可行的,并且在visual c#2005 编程技巧大全上有提到,但是, ...

  9. 基于二叉树和数组实现限制长度的最优Huffman编码

    具体介绍详见上篇博客:基于二叉树和双向链表实现限制长度的最优Huffman编码 基于数组和基于链表的实现方式在效率上有明显区别: 编码256个符号,符号权重为1...256,限制长度为16,循环编码1 ...

  10. 【转】以太网帧、IP报文格式

    原文:https://www.cnblogs.com/yongren1zu/p/6274460.html https://blog.csdn.net/gufachongyang02/article/d ...

随机推荐

  1. 删除redis对应key的缓存

    [root@zhyly-pre-002 ~]# /usr/local/redis/bin/redis-cli -p 6379 #登录redis 127.0.0.1:6379> auth 'Red ...

  2. Dive into TensorFlow系列(2)- 解析TF核心抽象op算子

    本文作者:李杰 TF计算图从逻辑层来讲,由op与tensor构成.op是项点代表计算单元,tensor是边代表op之间流动的数据内容,两者配合以数据流图的形式来表达计算图.那么op对应的物理层实现是什 ...

  3. zabbix6.0安装

    一.简述 zabbix6.0 对相关软件版本要求较高,需要php7.25以上php8.0以下版本支持,若使用mysql数据库,其最低要求为mysql8.0,本此搭建采用的是使用较广的lnmp架构 za ...

  4. 互联网最全cka真题解析-2022

    1.CKA真题解析kubectl自动补全及帮助信息1.配置kubectl自动补全apt install bash-completion source <(kubectl completion b ...

  5. TransmittableThreadLocal和@Async优雅的记录操作日志

    此文主要讲解: 如何实现操作记录 如何将TransmittableThreadLocal和@Async搭配使用 TransmittableThreadLocal阿里的一个开源组件,为了在使用线程池等会 ...

  6. Blazor 部署 pdf.js 不能正确显示中文资源解决办法

    在Blazor项目嵌入 pdf.js 时不能正确显示中文,浏览器F12显示如下错误 错误 l10n.js /web/locale/locale.properties not found. 我找到了解决 ...

  7. 《HTTP权威指南》– 4.HTTP连接管理

    浏览器解析URL流程: 浏览器解析出域名: 浏览器查询这个主机名的IP地址: 浏览器获得端口号: 浏览器发起到主机名IP地址端口的80连接: 浏览器向服务器发送一条HTTP–GET报文: 浏览器从服务 ...

  8. 读python代码-学到的python函数-2

    1.zip函数 zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表. 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * ...

  9. RocketMQ消息短暂而又精彩的一生

    大家好,我是三友~~ 这篇文章我准备来聊一聊RocketMQ消息的一生. 不知你是否跟我一样,在使用RocketMQ的时候也有很多的疑惑: 消息是如何发送的,队列是如何选择的? 消息是如何存储的,是如 ...

  10. CVE-2022-32532 Apache Shiro 身份认证绕过

    漏洞名称 CVE-2022-32532 Apache Shiro 身份认证绕过 利用条件 Apache Shiro < 1.9.1 漏洞原理 使用RegexRequestMatcher进行权限配 ...