低延时+高并发+强事务丨DolphinDB 交易型内存存储引擎 IMOLTP 使用指南

1. 背景

在一些数据库应用场景中,例如金融行业的交易系统,其主要工作负载来源于对关系表的高频度、高并发的更新和查询操作。这样的应用场景要求数据的读写和计算能够具有低延迟、高并发的特征,同时保证极高的数据一致性,并提供 ACID 事务的支持,是典型的在线事务处理(OLTP)场景

传统的存储引擎由于其架构的设计出发点是将数据存储在磁盘上,在面对上述场景要求时,软硬件层面面临巨大挑战,无法很好地满足上述苛刻的性能要求。而在这些场景中,往往需要维护的数据量实际上没有那么大,那么,能否把所有的数据都维护在内存里呢?这样就可以减少读写磁盘的带宽,能够大大降低数据库的延迟和提升数据库的并发度。

基于这个想法,DolphinDB 设计并实现了一款纯自研的内存 OLTP 数据库,它有以下特点

  • 将所有数据都存储在内存中,省去磁盘 I/O 的开销;
  • 以行存的形式来组织数据,主要适用于 OLTP 的场景;
  • 支持创建 B+ 树索引 (主键索引和二级索引) 来应对高频度、高并发的更新和查询操作;
  • 支持事务,默认为 snapshot isolation;
  • 实现 Write-Ahead-Logging 和 checkpoint 机制以保证数据的持久化和恢复;
  • 为加速重启时的恢复过程,实现了并行恢复机制。

下文将介绍 OLTP 的使用方式。

需要在配置文件里加上  enableIMOLTPEngine=true 来开启 OLTP 引擎。

2. DDL

2.1 建库

使用 database 函数来创建 OLTP 数据库,语法与创建 OLAP/TSDB 数据库一样,但是有以下注意事项:

  • directory 必须以 oltp:// 开头。
  • engine 必须为 IMOLTP
  • OLTP 目前只支持单机版本,分区方式可以任意填写。
dbName = "oltp://test_imoltp"
db = database(dbName, VALUE, 1..100, , "IMOLTP")

2.2 建表

使用 createIMOLTPTable 函数来创建 OLTP 表,语法如下:

createIMOLTPTable(dbHandle, table, tableName, primaryKey, [secondaryKey], [uniqueFlag])

primaryKey 用来指定主键索引的键。主键索引有且只有一个,每个 OLTP 表都必须指定。主键索引是 unique 的,插入数据时会检查是否满足唯一性约束(即不能插入重复元素),若违反则报错。主键可以包含多个字段(字段即为列名)。

secondaryKey 用来指定二级索引的键。二级索引可选,并且每个 OLTP 表可以创建多个二级索引。二级索引有 unique 和 non-unique 两种,两者的区别在于 unique 索引需要满足唯一性约束,而 non-unique 索引没有这个限制。由 uniqueFlag 来指定二级索引是否是 unique 的。二级索引的键同样可以包含多个字段。

// pt1 以 id 为主键,没有二级索引
pt1 = db.createIMOLTPTable(table(1:0, ["id", "val1", "val2", "sym"], [LONG, INT, LONG, STRING]),"test_table_1",primaryKey=`id
)// pt2 以 id,sym 为主键,有一个 unique 二级索引:以 val2,sym 为键
pt2 = db.createIMOLTPTable(table(1:0, ["id", "val1", "val2", "sym"], [LONG, INT, LONG, STRING]),"test_table_2",primaryKey=`id`sym,secondaryKey=`val2`sym,uniqueFlag=true
)// pt3 以 id 为主键,有一个非 unique 二级索引:以 val1 为键;一个 unique 二级索引:以 sym 为键
pt3 = db.createIMOLTPTable(table(1:0, ["id", "val1", "val2", "sym"], [LONG, INT, LONG, STRING]),"test_table_3",primaryKey=`id,secondaryKey=[`val1, `sym],uniqueFlag=[false, true]
)

通常来说,对于查询效率:主键索引优于二级索引优于非索引,如果查询时不能利用任何索引,则只能进行全表扫描。合理地创建二级索引可以提升查询的效率,但是相应地会降低写入的效率,因为写入时 (insert/delete/update) 需要修改相应的索引。

2.3 删库/删表

使用 dropTable 和 dropDatabase 来删表删库,使用方式与 OLAP/TSDB 没有区别。

db.dropTable("test_table_1")if (existsDatabase(dbName)) {dropDatabase(dbName)
}

3. DML

后文的例子假设已经执行过下面的脚本来建库建表:

dbName = "oltp://test_imoltp"
tableName = "test_table"if (existsDatabase(dbName)) {dropDatabase(dbName)
}db = database(dbName, VALUE, 1..100, , "IMOLTP")// pt 以 id 为主键,没有二级索引
pt = db.createIMOLTPTable(table(1:0, ["id", "val1", "val2", "sym"], [LONG, INT, LONG, STRING]),tableName,primaryKey=`id
)

3.1 写入数据

写入数据可以用 append! 和 insert into,使用方式与 OLAP/TSDB 一样。

pt = loadTable("oltp://test_imoltp", "test_table")id = 1..100
val1 = id * 10
val2 = rand(10000, size(id))
sym = take(`aaa`bbb`ccc`ddd`eee, size(id))
pt.append!(table(id, val1, val2, sym))insert into pt values(200, 2000, 1111, `xxx)
insert into pt values(201, 2010, 2222, `yyy)
insert into pt values(211..220, (211..220)*10, take(9527, 10), take(`xxx`yyy`zzz, 10))insert into pt(id, sym) values(1000, `aaa)
insert into pt(id, sym, val1) values(1001, `bbb, 10010)

3.2 查询数据

使用 SQL 来查询数据。where 条件非常重要,如果一次查询无法利用索引,那么性能会大幅降低。

pt = loadTable("oltp://test_imoltp", "test_table")select * from pt where id = 10  // 点查,用主键索引
select * from pt where id > 100, id < 200  // 范围查询,用主键索引select * from pt where val1 = 1000  // 全表扫描,无法利用索引

3.3 更新数据

使用 SQL 来更新数据。

pt = loadTable("oltp://test_imoltp", "test_table")update pt set val1 = 100 where id = 1
update pt set val1 = id + val1 where id < 10

3.4 删除数据

使用 SQL 来删除数据。

pt = loadTable("oltp://test_imoltp", "test_table")delete from pt where id = 1
delete from pt where id >= 100, id <= 110

4. 事务

使用 transaction 语句块可以在一个事务内执行多条 DML 语句,在一个事务范围内,所有的 DML 操作都会一起成功或一起失败。若一个事务执行的时候有异常抛出,会自动撤销本次事务的所有更改。

pt = loadTable("oltp://test_imoltp", "test_table")delete from pttransaction {insert into pt values(0, 0, 0, `aaa)insert into pt values(1, 1, 1, `bbb)insert into pt values(2, 2, 2, `ccc)commit  // 提交事务(可以省略)
}
assert (exec id from pt order by id) == [0,1,2]transaction {insert into pt values(3, 3, 3, `ddd)insert into pt values(4, 4, 4, `eee)delete from pt where id = 1update pt set id = 10 where id = 0assert (exec id from pt order by id) == [2,3,4,10]rollback  // 强制回滚事务,撤销所有修改
}
assert (exec id from pt order by id) == [0,1,2]

commit 表示提交本次事务的所有更改,rollback 表示撤销本次事务的所有更改。不需要显式地写 commit,出了 transaction 语句块的作用域时会自动 commit。

若不显式地使用  transaction 语句块,则每一句 SQL 都是一个事务。

注意:DDL 语句(即建表,删表等)不能放在  transaction 语句块里面,因为 DDL 目前不支持事务。

5. 配置参数

目前 OLTP 有以下配置参数可以设置:

  • enableIMOLTPEngine,bool 类型。表示是否开启 OLTP 引擎。默认为 false。
  • enableIMOLTPRedo,bool 类型。表示是否开启 WAL(Write-Ahead-Log),开启之后才能保证数据不会丢失。默认为 true。
  • IMOLTPRedoFilePath,string 类型。表示 redo 文件(即 WAL 文件)的路径(注意不是目录),可以为绝对路径或者相对路径。当为相对路径时,相对于 home 目录下的 IMOLTP 目录。默认为 home 目录下的 IMOLTP/im_oltp.redo
  • IMOLTPSyncOnTxnCommit,bool 类型。只在 enableIMOLTPRedo 为 true 时(即开启了 WAL)有意义。默认为 false。详细解释见下文。
  • enableIMOLTPCheckpoint,bool 类型。表示是否开启 checkpoint。默认为 true。
  • IMOLTPCheckpointFilePath,string 类型。表示 checkpoint 文件的路径(注意不是目录),可以为绝对路径或者相对路径。当为相对路径时,相对于 home 目录下的 IMOLTP 目录。默认为 home 目录下的 IMOLTP/im_oltp.ckp
  • IMOLTPCheckpointThreshold,long 类型,单位为 MiB。 表示:如果 redo 文件里面的 log 大小达到该阈值后,会触发一次 checkpoint。默认为 100 MiB。
  • IMOLTPCheckpointInterval,long 类型,单位为秒。表示每隔 # 秒之后强制做一次 checkpoint。默认为 60 秒。

关于 IMOLTPSyncOnTxnCommit 的含义:

在开启 WAL 后,事务对数据进行修改之前,会先写日志到持久化存储。系统重启时会回放 redo 文件里的日志,恢复到重启之前的状态。

如果 IMOLTPSyncOnTxnCommit 为 false,事务 commit 成功之后,保证日志写到了操作系统的缓存里,但是不保证日志已经写到了持久化存储上。因此,如果进程崩溃, 数据不会丢失, 但是当操作系统崩溃(机器掉电), 可能会有数据丢失。

如果 IMOLTPSyncOnTxnCommit 为 true,在事务 commit 成功之后,保证日志已经写到了持久化存储上,即使操作系统崩溃,数据也不会丢失。(但是如果存储设备故障, 还是可能有数据丢失)。

如果需要持久化数据,并且对数据的一致性要求较高,绝对无法忍受数据丢失,推荐把 enableIMOLTPRedo 和 IMOLTPSyncOnTxnCommit 都设置为 true。这种模式下,(写入)性能较差。

如果需要持久化数据,并且可以容忍操作系统崩溃(比如机器掉电等小概率事件)导致的数据丢失,推荐把 enableIMOLTPRedo 设置为 true, 把 IMOLTPSyncOnTxnCommit 设置为 false。这种模式下,(写入)性能较好。默认为这种配置。

6. 内置函数 triggerCheckpointForIMOLTP

当开启了 checkpoint 时(即 enableIMOLTPCheckpoint 配置为 true ),系统会在达到以下两个条件之一时自动触发 checkpoint:

  • redo 文件里面的 log 大小达到阈值(IMOLTPCheckpointThreshold MiB);
  • 或者,距离上一次 checkpoint 过去了 IMOLTPCheckpointInterval 秒。

用户也可以手动调用 triggerCheckpointForIMOLTP 函数来触发 checkpoint。函数语法如下:

triggerCheckpointForIMOLTP([force=false], [sync=false])

参数:

  • force,bool 类型,可选。表示是否强制做 checkpoint。如果为 false,并且当前并没有达到做 checkpoint 的条件(即 redo 文件里的 log 大小没有达到 IMOLTPCheckpointThreshold),则忽略这次请求。默认为 false。
  • sync,bool 类型,可选。表示是否异步。如果为 false,则该函数请求一次异步的 checkpoint,并不会等到请求完成再返回;否则该函数会等到请求完成(注意不一定做了 checkpoint)再返回。默认为 false。

7. 总结

DolphinDB 推出的 OLTP 内存数据库适用于高并发、低延迟的在线事务处理场景。该数据库将数据存储在内存中,支持 B+ 树索引、事务、Write-Ahead-Logging 和 checkpoint 机制。事务通过 transaction 语句块实现,保证了操作的原子性。用户还可以通过配置参数的配置以及内置函数 triggerCheckpointForIMOLTP 的使用,手动触发 checkpoint。

总体而言,DolphinDB 的 OLTP 引擎适用于对数据一致性和性能要求较高的场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/815780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

离谱!奇安信人事总监透露:Web安全不会岗位这些就别投简历了

有人的地方就有江湖&#xff0c;有互联网安全的地方&#xff0c;就必然有Web安全工程师的身影。但其实Web安全是近几年才备受关注的&#xff0c;从事这方面的专业人员并不多&#xff0c;这就导致整个市场Web安全研究员的供求严重不平衡。 这种供求不平衡直接反映在Web安全研究…

软考之零碎片段记录(十五)+复习巩固(十)

一、学习 1. 多对多关系模式 举例&#xff1a;学生和课程。顾客和商品等。 多对多关系的确立需要有中间表&#xff0c;需要使用两个外键确认表中的唯一数据。 2. 数据库范式 1nf 表中每个字段都是原子性不可查分的。在关系&#xff08;或表&#xff09;中&#xff0c;每一行…

使用Python的Pillow库进行图像处理书法参赛作品

介绍&#xff1a; 在计算机视觉和图像处理领域&#xff0c;Python是一种强大而流行的编程语言。它提供了许多优秀的库和工具&#xff0c;使得图像处理任务变得轻松和高效。本文将介绍如何使用Python的wxPython和Pillow库来选择JPEG图像文件&#xff0c;并对选中的图像进行调整和…

SpringBoot自动装配

清明前夕&#xff0c;我发表了一篇与Spring Cloud有关的文章&#xff0c;原计划在这篇文章之后&#xff0c;就梳理Eureka注册中心的相关知识。然而在跟踪之后&#xff0c;我才发现上来就谈Eureka组件的实现原理是不现实的&#xff0c;因为我根本不清楚SpringBoot是如何集成Eure…

【笔记】mysql版本6以上时区问题

前言 最近在项目中发现数据库某个表的createTime字段的时间比中国时间少了13个小时&#xff0c;只是在数据库中查看显示时间不对&#xff0c;但是在页面&#xff0c;又是正常显示中国时区的时间。 排查 项目中数据库的驱动使用的是8.0.19&#xff0c;驱动类使用的是com.mysq…

LVGL简单记录

1、 vs中代码旁边有个小锁删除git 2、Visual Studio 试图编译已删除的文件&#xff0c; 如果这个文件也是你不再需要编译的文件&#xff0c;且已经从文件系统中删除&#xff0c;你需要从 .vcxproj 文件中移除或者注释掉这一行&#xff0c;以停止Visual Studio尝试去编译一个不…

Open CASCADE学习|实现Extrude功能

首先定义了一些基本的几何元素&#xff0c;如线、圆和平面&#xff0c;然后使用makeExtrudebydir函数来对一个面进行挤出操作。下面是详细过程&#xff1a; 定义Extrude函数&#xff1a;makeExtrudebydir函数接受一个TopoDS_Shape对象和一个gp_Vec对象作为参数。TopoDS_Shape是…

HashMap与HashSet的不安全问题

HashSet的不安全问题 HashSet与ArrayList一样也存在不安全的问题&#xff0c;当多线程时也会出现ConcurrentModificationException&#xff0c;并发修改异常需要提出解决方案 问题 public static void main(String[] args) {Set<Integer> set new HashSet<>();…

1.MMD模型动作场景镜头的导入及视频导出

界面介绍 MIKUMIKUDANCE926版本 MMD的工具栏模型骨骼帧的窗口&#xff0c;在不同时间做不同动作&#xff0c;可以在这里打帧操作时间曲线操作窗口&#xff0c;控制模型两个动作之间的过渡模型操作窗口&#xff0c;导入模型选择模型相机操作&#xff0c;控制相机远近&#xf…

[ LeetCode ] 题刷刷(Python)-第128题:最长连续序列

题目描述 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 示例 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&#xff1a;4 解释&#xff1a;最长数字连续序列是 [1, 2…

Vol.44 一个分享网站的网站,每个月8.7万访问量

哈咯&#xff0c;各位朋友好啊&#xff0c;我是欧维&#xff0c;今天要给大家分享的网址是Fuun.fun&#xff0c;奇趣网站收藏家&#xff1b; 它的网址是&#xff1a;FUUN.FUN 这是一个我经常逛的网站&#xff0c;为什么我经常逛呢&#xff1f;因为可以从中发现一些有意思的网站…

全量知识系统 程序详细设计“知识”的原则及运用

今天我们聊聊 全量知识系统&#xff08;以下简称“全知系统”&#xff09;中的“知识”的原则及运用。 全知系统“程序”的三个“计算”方面 ”用户消费功能function快照”&#xff08;局部规模scale和点击率&#xff09;&#xff0c;“客户消化能力competence画像”&#xf…

数据库-Redis(8)

目录 36.可以每秒做一次RDB快照吗? 37.AOF是写前日志还是写后日志? 38.什么是AOF重写?

上位机图像处理和嵌入式模块部署(智能硬件的开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 目前&#xff0c;用上位机软件虽然可以部署项目&#xff0c;但是它本身有自己的缺点&#xff0c;那就是稳定性差、价格贵。稳定性这部分&#xff0…

Linux 快问快答

如果对于找 Java 后端开发的话&#xff0c;我感觉会这几个差不多了&#xff0c;面试官应该不会问的这么详细吧。一般就问问 Linux 的几个常用的命令&#xff0c;然后做一些简单的性能排查就好了。如果面试被问到另外的问题&#xff0c;那我再补充进来&#xff0c;现在先掌握这么…

kinit 笔记

介绍&#xff1a; Kinit 是一套开箱即用的中后台解决方案&#xff0c;可以作为新项目的启动模版&#xff0c;前后端分离架构&#xff0c;开箱即用&#xff0c;在线例子&#xff1a;https://kinit.ktianc.top/login。 1. 后端Api应用安装及初始化 # 获取 git clone https://g…

Java 中命令模式,请用代码具体举例

在Java中&#xff0c;命令模式是一种行为设计模式&#xff0c;它允许将请求封装成一个对象&#xff0c;从而使得可以参数化其他对象对请求进行调用、队列化请求、或者记录请求日志&#xff0c;同时支持可撤销的操作。 下面是一个简单的示例代码&#xff0c;展示了如何使用命令模…

CMC学习系列 (8):动态力输出期间的伽马范围皮质相干性

CMC学习系列:动态力输出期间的伽马范围皮质相干性 0. 引言1. 主要贡献2. 方法3. 结果4. 讨论5. 总结欢迎来稿 论文地址&#xff1a;https://www.sciencedirect.com/science/article/abs/pii/S1053811906010238 论文题目&#xff1a;Gamma-range corticomuscular coherence duri…

【面试八股文之操作系统】

1.什么是用户态和内核态&#xff1f; 用户态和内核态是操作系统中的两种运行模式或特权级别。 用户态&#xff1a;在用户态下&#xff0c;应用程序以及用户自己编写的代码运行&#xff0c;其权限受到限制&#xff0c;不能直接访问底层系统资源和执行特权操作。用户态只能受限地…

OSPF动态路由实验(思科)

华为设备参考&#xff1a; 一&#xff0c;技术简介 OSPF&#xff08;Open Shortest Path First&#xff09;是一种内部网关协议&#xff0c;主要用于在单一自治系统内决策路由。它是一种基于链路状态的路由协议&#xff0c;通过链路状态路由算法来实现动态路由选择。 OSPF的…