存储引擎的介绍
数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)通过数据引擎,对数据进行创建、查询、修改和删除的操作。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以获得数据库特定的功能。
作为数据库的支撑底盘,一个成熟的存储引擎必须要考虑各个方面,包括数据读写的效率,包括如何成本最低风险最小地运作,而TcaplusDB在考虑了以上这些因素后,结合我们是一个键值型数据库的特点,我们选择了腾讯完全自研的TXHDB存储引擎来落地TcaplusDB的数据。 下面介绍一下TXHDB存储引擎的格式和优势所在。
存储引擎格式
TcaplusDB的数据文件大致可以分为3个区,头部区、内存映射区和文件访问区,见下图。其中内存映射区和文件访问区是用于存放真实数据的。
![[TcaplusDB知识库]TXHDB存储引擎的介绍-图片1](https://www.it2021.com/wp-content/themes/begin/img/loading.png)
其中:
- 头部区,用于存放元数据、统计数据、Hash桶、空闲块链表头,扩展数据等信息。
- 内存映射区,这部分空间会在数据文件加载时,通过mmap的方式映射到内存地址空间中,使用读写内存的方式读写该区域,间接地达到缓存在内存中的效果。该区域位于数据文件的前部,默认大小为1G。
- 文件访问区,紧接着内存映射区后面就是所谓的文件访问区,该区域的数据读写通过普通的文件读写接口进行。
更详细的格式内容如下:
![[TcaplusDB知识库]TXHDB存储引擎的介绍-图片2](https://www.it2021.com/wp-content/themes/begin/img/loading.png)
整个文件分为头部控制信息区和数据区域;
数据文件打开时,从文件最开始建立文件映射对象,对于写操作,至少将控制头部区域放入内存映射范围;
Key-value数据记录通过hash表进行组织,hash冲突解决策略有二叉平衡树和线性链两种,通过引擎文件创建时通过参数可以决定使用哪种冲突解决策略;二叉树平衡树通过对key计算另外一个hash值(称为二次hash)建立;
数据在mmap区域外时,对数据的访问通过基于文件起始位置的偏移,使用pread/pwrite来访问。
头部控制区域分为以下几个部分:
- 基本控制信息区:包含magic、版本信息、文件类型、记录对齐参数、空闲块参数、压缩属性、桶数、记录数、文件大小、首条记录位置、桶信息、空闲块信息等。
- Hash桶信息区:存储hash每个桶首条记录的存储偏移;
- 内存空闲链表头:此文件中处于mmap区域范围内的空闲数据块链表表头;
- 文件空闲块表头:mmap区域外空闲数据块链表的表头;
- LRU信息区域:跟踪mmap区域数据记录访问情况的LRU链;
- 扩展区域:对txhdb透明存储区域,tcapsvr通过此区域存储数据表描述信息;
空闲块管理
数据记录的大小不一,数据记录在存储过程中,大小改变或删除会导致文件中出现一些空闲块,为减少大小不一空闲块的整理利用的开销。TXHDB采用块空间来存储数据记录,块空间通过一个apow的参数设定其对齐方式,即通过apow定义数据块的最少大小;整个存储块由按照最小对齐单元进行逐层线性增长的块数组组成,数据块的级数通过fpow参数决定,如果apow为8,fpow为10,则空闲数据块起示意图如下:
![[TcaplusDB知识库]TXHDB存储引擎的介绍-图片3](https://www.it2021.com/wp-content/themes/begin/img/loading.png)
实际数据key或value通过某一级别的一个或多个空闲块来存储,空闲块分配原则:
- 优先使用内存空闲块,然后使用文件块
- 基于内存优先使用连续块,然后使用离散块
- 基于文件只能使用连续块
如果记录均为小记录,那么整个文件可能会存在过多的离散记录,可以通过数据搬迁整理的方式定期对数据做整理。
Key Value分离
基于HASH表存储数据记录,每个数据的读写都必须访问数据的Key,TXHDB采用Key-value分离的思路,优化数据检索效率,具体如下:
将Key和Value分离存储,分别存储到Key结点和Value结点,Hash值映射到Key结点,Key结点再映射到Value结点。Key结点优先存储在内存中,Value结点有可能存储在内存中也有可能存储在磁盘中。
![[TcaplusDB知识库]TXHDB存储引擎的介绍-图片4](https://www.it2021.com/wp-content/themes/begin/img/loading.png)
具体说明如下:
- 一条记录的key,可能有多个块组成, 一个Head块, 多个split块,每一个块中记录下一个块的offset. 同时key head块中记录的有value头块的offset。
- 一条记录的val, 也可能有多个块组成, 一个head块, 多个spl块,val的offset,记录再key的head中。
- 通过将key的offset记录在hash桶中, 冲突的记录,offset记录在keyHead的left和right中以实现链表或二叉树。
- 线上业务通常width_等于32,即4B。 则 keyHead默认最小块为64B(apow的取值最小为6,2**6=64B), 其中引擎自有信息需要占用32B – 33B, 业务可用为31B到32B, 业务据此可设计更有效的key,使key占用的块尽可能少。
多级LRU链 进行数据热度管理
为记录数据的访问热点,对mmap区域内的数据建立多级LRU链来跟踪,LRU链的级数通过参数可以定制,采用多级LRU而非一级LRU链主要是淘汰时除考虑最近访问时间外,还评估最近访问次数。
![[TcaplusDB知识库]TXHDB存储引擎的介绍-图片5](https://www.it2021.com/wp-content/themes/begin/img/loading.png)
- 多级LRU,综合考虑最近访问时间和访问次数
- 读写访问时增加访问计数,定位扫描时减访问次数
- 优先淘汰访问次数为1的LRU链中的记录
- 换出条件:剩余内存低于一定阀值
- 换入条件:剩余内存高于一定阀值
最后
我们已经了解了 TcaplusDB 个分布式的 NoSql数据库搜素引擎的基本结构,后续我们将揭开更多TcaplusDB设计的特殊奥秘。

日本 1F
这引擎设计得还挺细的,key-value分离确实能提速吧?
印度 B1
@ 虚空涟漪 分离存储肯定能减少读放大,提速是有的。
台湾省 2F
这种设计对SSD友好吗?
北京市 3F
二叉平衡树在数据量大的时候会不会成为瓶颈?
印度 4F
内存空闲块和文件块优先级策略在实际场景中效果如何?
菲律宾 5F
压缩属性支持哪些算法?
韩国 6F
默认1G的mmap区域能根据负载动态调整吗?
浙江省 7F
apow和fpow参数推荐配置是多少?
美国 8F
key压缩空间能省多少内存?
河南省平顶山市 9F
这种架构适合物联网时序数据场景吗?
上海市 10F
空闲块链表维护开销大不大?
山东省东营市 11F
LSM树索引空间和传统B+树比有什么优势?
江苏省 12F
fpow和apow参数调起来麻烦吗?线上调优有啥经验?
韩国 13F
前几天刚搞完类似存储结构,空闲块管理真是个坑。
北京市 14F
内存映射区默认1G会不会太大了?小机器扛不住啊🤔
新加坡 B1
@ SableSage 默认1G是大了点,不过现在服务器内存都大,问题不大吧。
江西省南昌市 15F
说白了还是为了高并发读写优化,腾讯这套自研挺硬核。
北京市 16F
hash冲突用二叉树还是链表,实际性能差多少?
印度 17F
感觉一般,现在很多引擎都做key-value分离了。
江苏省泰州市 18F
mmap区域外的数据访问全靠pread/pwrite?IO压力不小吧
韩国 19F
LRU多级淘汰逻辑看着合理,但实现复杂度估计不低。
北京市 B1
@ 奶盖小熊崽 多级肯定比单级复杂,但为了精准淘汰也值了。
日本 20F
value可能在磁盘这点有点劝退,延迟怎么压?
山东省滨州市 21F
这个mmap默认1G的设定,实际部署的时候能动态调吗?
陕西省延安市 22F
哈希桶用二叉平衡树,查找效率应该比链表强不少。
日本 23F
腾讯自研引擎稳定性咋样,有线上大规模使用的案例吗?
中国 24F
key头块才31B可用,业务设计key得好好抠长度了。
山东省临沂市 25F
多级LRU听着比单纯LRU靠谱,热点数据能留住。
澳大利亚 26F
离散块多了就得整理,运维成本上来了。
安徽省六安市 27F
文件访问区用pread/pwrite,感觉像直接操作裸设备啊。
江苏省泰州市 28F
这种底层设计对普通开发者太远了,关心怎么用就好。
澳大利亚 29F
空闲块管理那套参数看着就头大,调不好性能掉得厉害。
浙江省绍兴市 30F
key-value分离是趋势,但实现得好不好还得看实测。
印度 31F
这个mmap映射方式挺巧妙的,省了缓存管理的事儿。
湖北省武汉市 32F
key-value分离确实能提升检索效率,实测过吗?
重庆市 33F
hash桶用二叉树处理冲突,比链表快多少有人测过?
浙江省 34F
空闲块管理参数调优文档能分享下不?
印度 35F
LRU多级链这个设计挺细,比单级靠谱多了。
印度尼西亚 36F
这存储引擎的设计思路挺清晰,适合键值数据库场景。
宁夏银川市 B1
@ 旧时光书页 设计上确实考虑了键值场景的特性
中国 37F
文件访问区用pread/pwrite,IO瓶颈怎么解决?
韩国 38F
头部控制信息区字段也太多了,维护起来麻烦吧。
马来西亚 39F
key-value分离这思路可以啊,效率应该能提不少。
贵州省贵阳市 B1
@ The Woodcarver 感觉读写会快不少
上海市 40F
小机器部署的话1G内存映射区确实有点吃内存。
安徽省合肥市 41F
自研引擎稳定性如何?有生产环境数据吗?
新西兰 42F
离散块整理频率一般设置多少合适?
广东省深圳市 43F
key头块只有31B可用,长key怎么处理?
日本 44F
value在磁盘时延迟能控制在什么水平?
印度尼西亚 45F
这种底层优化对业务层透明吗?
日本 46F
腾讯这套方案和RocksDB比优势在哪?
日本 47F
多级LRU的阈值设置有什么讲究?