从一到无穷大 #17 Db2 Event Store,A Purpose-Built IoT Database Engine
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。
文章目录
- 引言
- Architectural overview
- Data format and meta-data
- Ensuring fast ingestion
- Multi-tiered caching
- Optimized query processing
- Continuous Availability
- 总结
引言
给我的感觉Db2 Event Store是一个私有的InfluxDB IOX,只不过没有InfluxDB IOX功能那么强大而已,其在写入流程,COS的利用,存储格式,以及架构上给我的感觉是后者好像也可以这么实现,只不过后者计算节点可以不挂盘,且控制面更为强大而已。
Db2 Event Store设计原则如下:
- 尽可能快地写入数据: 最小化完成持久化数据所需同步工作,确保节点故障时的持久性,并将数据提供给查询处理。
- Asynchronously refine and enrich data: 数据被写入后会以异步方式进一步优化数据格式,从而提高查询处理的效率。
- 高度优化查询处理: 利用了高度优化的数据格式Parquet;允许跳过部分数据的元数据;强大的查询优化器和runtime;通过在集群中的所有节点上并行运行以及在每个节点内多线程运行,充分利用所有可用硬件;
- 可用性: 最大限度减小单机故障时对于读写的影响
我认为的Db2 Event Store的优劣势如下:
优势:
- 基于IOT场景完全利用了云上廉价的基础设施,并设计多集缓存消除性能影响。
- 高效的写入流程,来源于创新的数据多级流转(这个思路类似于BytesSeries)。
- 重复使用已经构建和优化了几十年的
Db2 SQL compiler,optimizer以及runtime,极大地减少了开发工作量,并立即提供了丰富的 SQL 支持和出色的运行时查询性能。 - 混合
MPP shared nothing/shared disk cluster architecture,这样做的好处是将传统MPP shared nothing的线性可扩展性与shared everything的高可用性结合,存算分离,在公有云上售卖模型也清楚,隔离也简单,计费也容易。 - 天然支持高基数,因为不同的数据存储在不同的Parquet文件,index分离,还有
synopsis文件记录表级别概要信息,允许在共享存储中合并,compact过程不影响查询。
劣势:
- 没有提到控制面,元数据完全基于Zookeeper,风险较高,能力相对较弱,无法适应复杂调度。
- 可用性差,单点故障会导致读短暂不可用。
Architectural overview

DB2混合了 MPP shared nothing / shared disk cluster architecture,这样做的好处是将传统 MPP shared nothing 的线性可扩展性与shared everything的高可用性结合。
如上图所示,Table数据根据用户定义的hash key被划分为micro-partitions,存储在可靠的共享存储介质上。集群中所有的计算节点都能完全访问整个数据集,从而实现存储与计算的解耦,并使每个节点都能独立扩展。
Zookeeper作为协调节点,在逻辑上将micro-partitions的归属划分给可用的计算节点。逻辑上每个micro-partitions在任何给定时间点都由一个计算节点拥有,任何该micro-partitions的读写请求都通过拥有该micro-partitions的计算节点,实现集群级别的读写并行化。在处理计算节点故障时,受影响的micro-partitions会在计算节点上重新分配映射关系,与需要进行数据迁移的模式相比,大大缩短了故障转移时间。
为确保元数据没有单点故障,系统采用了floating catalog的概念,将目录信息存储在可靠的共享存储中,并通过任意一台计算节点提供服务,一旦发生故障在任何计算服务器上重新启动。
数据首先被写入计算节点上本地存储介质(SSD 或 NVMe),并在提交之前进一步复制和写入至少另外两个计算节点的本地存储。这确保了数据在计算节点发生故障时的可用性。然后数据异步写入共享存储。这种模式可以避免了共享存储介质可能产生的任何额外延迟(尤其是在高延迟云对象存储的情况下),高效的处理各种负载的写入。
该架构通过并行和优化存储技术的结合实现快速摄取。该系统采用headless集群架构,所有计算节点都扮演着head nodes 以及 data nodes(类似multi raft?)。在单独一个计算节点内部通过表级别hash partitioning将写入row映射到特定的micro-partitions,然后发送给拥有该分区的计算节点。(这里提一个问题,为什么不是每个计算节点都可以做写入呢?原因是为了保证一致性,这里的写入不是基于raft的,而是写三份,如果不存在一个单点写入的话可能存在三副本不一致)
数据格式为Parquet,Parquet利用压缩的 PAX 存储格式,可被 Db2 的 BLU 列式runtime引擎用于分析处理,也可以允许Hive、Spark、Presto等直接查询数据。
云对象存储无法为可修改的数据提供强有力的一致性保证,为了利用对象存储的成本和可扩展性优势,db2利用了一种append-only immutable 存储模型,在这种模型中数据块永远不会被重写。Synopsis metadata允许在查询处理过程中跳过数据(时间?first/last/min/max/count?),作为写入过程的一部分自动生成,并写入单独的 Parquet 文件,从而允许元数据与表数据分开访问和缓存。
索引利用 LSM 树风格的格式来满足append-only的要求。索引作为数据共享流程的一部分异步生成的,以尽量减少写入处理的延迟。所以异步生成意味着在异步共享处理过程中需要消除重复键,这里其实就是多写处理冲突,以前我做multi region写冲突处理时方案时做过这个,方案很多,LWW是最简单有效的一种。
高效的数据访问是通过多层缓存层实现的,该层将频繁访问的数据、元数据和索引缓存在内存中和计算节点本地存储介质中,以防止云对象存储可能产生的延迟。
Data format and meta-data
数据存储格式主要基于两个方面考虑:
- 考虑到处理分析工作负载时的性能优势,最好使用列式数据存储格式
- 使用开源格式,允许外部系统访问
所以最终选择Parquet作为存储格式。
Db2 Event Store 架构下表的最小粒度是micro-partitions。Parquet 文件属于micro-partitions,因此给定的 Parquet 文件正好包含一个micro-partitions的数据。Parquet 文件一旦写入就不可更改。micro-partitions的每个 Parquet 文件都分配有一个单调递增的数字,称其tablet identifier。Db2 Event Store runtime engine 以及 external readers 利用这一点来判断较新的数据。共享存储中 Parquet 文件的元数据由 Zookeeper 维护,比如每个micro-partitions的最新tablet identifier。
在 Db2 Event Store,tuples 通过 Tuple Sequence Number (TSN)识别,TSN 是一个整数,可用于定位表中的tuple。Db2 Event Store 中的 TSN 包括tablet identifier, the zone,以及tuple在 Parquet 文件中的偏移量。
另外Db2 Event Store还为Parquet贡献了一项特性 Parquet Modular Encryption[1], 这个特性对每个模块分别加密,从而保留了加密数据的过滤功能和分析效率。它利用 CPU 硬件支持的 AES GCM 密码[2],在不减慢整体工作流程的情况下执行模块加密操作。AES GCM 还能保护存储数据的完整性,使其不会被恶意篡改文件内容。db2使用其他模块保存密码,Parquet 文件在发送到共享存储前已加密,这样做有两个好处:
- 存储后端无法查看加密密钥和明文数据
- 从共享存储检索加密文件后,DB2 Even Store 会使用 Parquet 模块化加密库验证已处理数据的加密完整性,SSD/NVMe 缓存层也使用 Parquet 加密格式,确保本地持久化文件免受内部人员攻击和硬件故障。
这样的做法可以看出db2的工程实现足够优秀,没有经验的团队不会有这样的决策的,因为很多现有的云系统因为性能的考究不会做全链路CRC,这意味着可能发生内存/CPU错误而导致比特跳变,进而导致数据损坏,如果用户侧不自己校验,很多时候根本无法感知这种问题(以我们团队的经验来看,基本几年就会发生一次)。
Ensuring fast ingestion

关键思路和现有的几个系统一样,减少写入流程上的开销,重操作异步执行,基本写入流程如下:
- 客户端可以连接到任何一个节点(连接的节点称为
ingest coordinator)来执行写入,如果发生故障,会自动将批量插入重新写到任何其他计算节点。ingest coordinator将batch中数据哈希分割到对应的micro-partitions,然后将数据写入其中一个副本。 - 对应副本收到写后,会以log的形式将其放入
Log Zone,持久化的同时会复制到其他计算节点,以确保数据的持久性和高可用性。没有索引。 Log Zone to the Pre-Shared Zone:Log Zone可实现快速写入和持久性,但并不是查询的最佳选择。因此必须尽快将最近写入的数据转换为更便于查询的格式,并使用indexes和synopsis来提高提高查询效率,这个过程有几秒的延迟。写入Pre-Shared Zone的数据较小,因为每次只会把上一次持久化到现在的数据持久化到共享存储,因此对于查询并不理想。这个过程异步维护索引 Parquet文件。Pre-Shared Zone to the Shared Zone:Pre-Shared Zone数据量足够时小文件便会合并,在所谓的Shared Zone生成更大的 Parquet 文件。文件越大代表查询处理效率越高,整体数据压缩效果也越好,因此合并后的文件大小一般在 64MB 左右。这个过程会合并索引。
数据的轮转对用户是透明的,所有这些Zone的数据都是不可变的。关键点是Log Zone不仅要写入本地存储(以保证持久性),还要直接用于处理查询结果。(log is database)
由于计算节点的micro-partitions分配是动态的,因此需要将索引数据都持久化到共享存储中,以便将micro-partitions从一个节点转移到另一个节点,当一个micro-partitions被重新分配给一个新的计算节点时时,数据库引擎会启动一个后台进程,为新的micro-partitionsleader做缓存预热,从而使索引访问能够尽快恢复到最高性能。
另外还有一个常规优化手段,为了表扫描时跳过不必要的数据,Db2 Event Store 会为每个表创建一个synopsis table ,synopsis table的每一行都涵盖相应用户表的行范围,并包含该行范围内列的最小值和最大值。数据synopsis块也采用 Parquet 格式。synopsis在数据合并到Shared Zone时填充,因此不包括预共享区和日志区的数据。维护这些区域的数据概要内容需要大量额外成本(对共享存储的额外写入),而且由于这些区域的数据量较小,数据跳过带来的价值不大。
Multi-tiered caching
一个通用的优化思路,即对象存储延迟较高(很好理解,COS本身分为三个模块COS前端,Partition layer,Stream layer,一个上传下载内部系统可能多达数十次网络通信,当然COS存小对象另说),价格低;而高性能存储延迟低,价格高(以腾讯云举例基于SSD的系统价格比COS高几十倍),所以如何利用价格低廉的存储并同时提供最佳性能?Db2 Event Store 选择多级缓存,既能利用内存,又能利用本地存储,使系统免受对象存储的高延迟影响。
Db2 Event Store使用了五种缓存机制:
Multi-layered Caching: SSD/NVMe,RAM 均用于缓存数据块,索引以及synopsis。Directed Caching:缓存访问可根据请求类型只定向到 RAM,或定向到本地 SSD/NVMe 设备(可选择放置在 RAM 缓存中);或者可以完全绕过缓存层直接访问云存储(确定冷数据)。Probabilistic Caching:利用被访问对象的不同表和索引数据总大小的统计数据,并计算相对于给定查询所使用数据被缓存的概率。常常与Directed Caching结合使用。Soft & Hard Limits:内存的限制。Epoch based eviction:一种巧妙的驱逐方式,我没太看明白。
Optimized query processing
在查询处理方面,Db2 Event Store 利用 Db2 的 BLU MPP 集群查询引擎,将 Db2 基于成本的 SQL 优化器和 Db2 的 BLU 加速列引擎的加速分析处理功能与 Db2 Event Store 数据管理层的快速写入和云本地存储功能相结合。这个确实不可模仿,这就是公司的底蕴吧。
计算引擎的优化我并不熟悉,很多内容没看懂。
不过Db2 Event Store 利用过去 30 年中开发和完善的 Db2 SQL compiler, optimizer 以及 runtime,证明了为公共云重新架构并不需要重写所有组件。也证明了计算引擎就根本不应该自己写,直接用现成的最好(Lindorm就使用了Apache Calcite作为计算引擎,InfluxDB IOX使用了DataFusion)。
Continuous Availability
其实对于文中Continuous Availability这个词我很疑惑,不知道怎么理解,用高可用性看吧,也不对,因为Db2 Event Store在计算节点宕机期间会影响读,也不可用,所以我暂且称它为基本可用吧。
- 写入:
micro-partitions的所有副本都能处理写入,因此只要大部分副本仍然可用,当一个副本节点丢失时,摄取处理受到的影响不大,客户端处理这种故障在在不同的节点重新尝试操作就可以。 micro-partitions上的其他操作对表leader的可用性有很高的依赖性。比如:查询,data movement between zones,data enrichment,index optimization processes。前面提到过data enrichment和index optimization processes可以通过foller提供服务,所以调度算法只要让主从不要在一台机器上,后台任务就可以继续。读只能通过系统能够快速识别不可用的leader,并将故障计算节点micro-partitions等leader转移到其他节点,以继续处理查询。- catalog:当catalog节点宕机时,系统仍能继续处理写入和查询,因为metadata数据是由数据节点本身缓存的,它们只依赖目录节点来执行初始缓存,而目录节点使用共享存储进行持久化,这使它可以故障转移到集群中的任何一台主机上,进而为新上架的节点提供缓存服务。(我们曾经有一次故障导致一个集群1000多个接入机70%不可用)
- Zookeeper :只要大部分 Zookeeper 节点存活,它就能持续可用。(我们曾遭遇过五副本mongo宕机的情况)

可以看到单点故障是影响查询的。
最后利用TSBS评估了 Db2 Event Store 与 Druid和TimecaleDB的读写性能,又是遥遥领先!
总结
参考:
5. https://issues.apache.org/jira/browse/PARQUET-1300
6. https://datatracker.ietf.org/doc/html/rfc5288
相关文章:
从一到无穷大 #17 Db2 Event Store,A Purpose-Built IoT Database Engine
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。 文章目录 引言Architectural overviewData format and meta-dataEnsuring fast ingestionMulti…...
9月16日,每日信息差
今天是2023年09月16日,以下是为您准备的15条信息差 第一、天猫超市首单“茅小凌”已由菜鸟送达,首单已由菜鸟供应链完成履约,18分钟送达消费者手中 第二、软银考虑对OpenAI进行投资。此外,软银还初步拟收购英国人工智能芯片制造…...
准备篇(二)Python 教程
Part 1 Python 基础语法区分输入与输出注释文本列表if 语句for 语句range() 函数走向编程的第一个例子Part 2 函数 和 数据结构函数数据结构del 语句列表详解元组集合字典循环的技巧Part 3 输入与输出读写文件打开文件 open()读文件写文件...
HTML+CSS画一个卡通中秋月饼
HTMLCSS画一个卡通中秋月饼🥮🥮🥮 中秋活动水个文章 整个divcss实现个月饼,给前端初学者一个练手的demo 效果图 思路 HTMl 先来个轮廓画脸上的东西:眼睛、眉毛、腮红、嘴巴眼睛丰富下瞳孔画20个花瓣 CSS 轮廓是要外…...
echarts的折线图,在点击图例后,提示出现变化,不报错。tooltip的formatter怎么写
在点击图例的年后,提示框会相应的变化,多选和单选都会响应变化。tooptip的重度在formatter tooltip:{show:true,trigger:"axis",alwaysShowContent:true,triggerOn:"mousemove",textStyle:{color:"#fff"},backgroundColor…...
C++中的auto是一个关键字,用于在编译时自动推导变量的类型
C中的auto是一个关键字,用于在编译时自动推导变量的类型。通过使用auto关键字,编译器可以根据变量的初始化表达式来确定其类型,从而省略了显式地指定类型的步骤。 使用auto关键字声明的变量必须在定义时进行初始化,以便编译器可以…...
VUE build:gulp打包:测试、正式环境
目录 项目结构 Gulp VUE使用Gulp Vue安装Gulp Vue定义Gulp.js package.json build文件夹 config文件夹 static-config文件夹 项目结构 Gulp Gulp是一个自动化构建工具,可以帮助前端开发者通过自动化任务来管理工作流程。Gulp使用Node.js的代码编写ÿ…...
1.使用turtle换一个五环2.设计这样一个程序:输入一个数字 判断它是不是一个质数
1.使用turtle换一个五环 import turtle turtle.pensize(15) turtle.penup() turtle.color(blue) turtle.goto(-150,-35) turtle.pendown() turtle.circle(60) turtle.penup() turtle.color(black) turtle.goto(0,-35) turtle.pendown() turtle.circle(60) turtle.penup() turtl…...
C语言希尔排序
希尔排序(Shell Sort)是插入排序的一种,也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。 希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列(由…...
KubeSphere 在互联网医疗行业的应用实践
作者:宇轩辞白,运维研发工程师,目前专注于云原生、Kubernetes、容器、Linux、运维自动化等领域。 前言 2020 年我国互联网医疗企业迎来了“爆发元年”,越来越多居民在家隔离期间不方便去医院看诊,只好采取在线诊疗的手…...
物联网:用python调入机器学习分析物联网数据入侵检测模块
要使用Python调用机器学习分析物联网数据入侵检测模块,您需要以下步骤: 安装Python和相关的机器学习库,如scikit-learn、pandas、numpy等。您可以使用pip命令来安装这些库。 准备输入数据。这些数据可以是来自物联网设备的原始数据ÿ…...
使用scss简化媒体查询
在进行媒体查询的编写的时候,我们可以利用scss与与编译器,通过include混入的方式对代码进行简化,从而大大提高了代码的可维护性,也减少了代码的编写量,废话不多说,直接上代码: // 断点列表 相当…...
win部署CRM
win部署crm) 1.phpstudy2.composer3.代码4.其他配置 周末锴哥让我帮他部署了一个CRM,写个教程,方便之后他用。锴哥用的是 NxCrm,先把代码下下来。 1.phpstudy 1.首先是下载小皮面板,配置php的环境。这里面下载了php8…...
Linux命令200例:dip用于用户与远程主机建立通信连接
🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌。CSDN专家博主,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆数年电商行业从业经验,历任核心研发工程师࿰…...
【每日一题】981. 基于时间的键值存储
981. 基于时间的键值存储 - 力扣(LeetCode) 设计一个基于时间的键值数据结构,该结构可以在不同时间戳存储对应同一个键的多个值,并针对特定时间戳检索键对应的值。 实现 TimeMap 类: TimeMap() 初始化数据结构对象void…...
IMU姿态解算,从IMU数据中计算旋转、速度、位置,IMU测量的原理
0. 预备 a. IMU测量值解释 IMU在测量时,得到的角速度或者加速度均是相对于地心惯性系结果,并且将该结果表示到Body坐标系下,就形成了最终的IMU输出。 记作: ω i b b \omega_{ib}^b ωibb,表示body系相对于惯性系的…...
【Qt-17】Qt调用matlab生成的dll库
matlab生成dll库 1、matlab示例代码 function BDCube(x,y)[x,y,z] cylinder(x,y);t1 hgtransform;s1 surf(3*x,3*y,4*z,Parent,t1);grid onview(3)shading interp end 2、matlab环境配置 首先检查自己的mcc编译器是否可用,输出以下命令: &#x…...
css经典面试题(二)
文章目录 1、清除浮动2、opacity: 0、visibility: hidden、display: none 的区别3、css画一个三角形4、常见的主流浏览器前缀5、重绘与重排的区别?6、如何优化图片7、CSS3 中 transition 和 animation 的属性分别有哪些8、居中为什么要使用 transform(为…...
jira搜索search issue条目rest实用脚本
官方文档链接地址: The Jira Cloud platform REST API 实用json请求脚本如下: {"fields": ["summary","status"],"jql": "project abc AND summary ~ 【%s】【coverity】 AND componentCoverity"…...
《C++ primer plus》精炼(OOP部分)——对象和类(5)
“学习是照亮心灵的火炬,它永不熄灭,永不止息。” 文章目录 类的自动和强制类型转换原始类型转换为自定义类型将自定义类型转换为原始类型 类的自动和强制类型转换 原始类型转换为自定义类型 可以用一个参数的构造函数来实现,例如ÿ…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
