云原生 HTAP -- Cloud-Native Transactions and Analytics in SingleStore

news2024/11/15 17:25:42

文章目录

    • 背景
    • 1 存算分离
    • 2. 统一的表存储 (行列混存)
      • 2.1 二级索引
      • 2.2 行锁
    • 3. 自适应查询引擎
      • 3.1 Segment skipping 实现
      • 3.2 Filtering 选择
    • 4 性能
    • 总结

背景

上篇看了 PolarDB-IMCI 在HTAP的实践,其中提到了其也有借鉴 SingleStore 的实现思路 并加以改进。所以又翻出来了 SingleStore 在 2022 SIGMOD上的论文 学习一下,原文 google 或者 sci-hub一下就好了。

数据库行业 HTAP 大背景就不再赘述了,主要两方面的原因:

  1. 云基础架构的弹性、灵活、低成本(用户 + 开发者)
  2. 数据存储访问需求的多样性,既要、又要、还想要 AP(高性能) + TP(低延时)

SingleStoreDB 论文中简称 S2DB,即 一个DB 服务两种数据库场景 TP + AP。

S2DB 实现HTAP 能力的 主体设计有在三方面:

  1. 存算分离,数据集主要存储在对象存储上,上层的primary节点 负责数据的读写 只读节点负责 AP以及 TP的数据查询,它们本地盘都能提供 数据缓存能力;并且在此基础上实现了 PITR 即 time-travel能力。
  2. 统一的表存储(行列混存)。行存和列存的区分不会对用户暴露(不需要用户指定使用行存还是列存),实现细节在内核内部,默认同时支持行存和列存的存储格式。实现上是 完全in-memory的行存 以及 持久化到 blob storage 的列存。
  3. 自适应的执行引擎。根据用户的query 选择合适的成本评估模型 来生成对应的plan,并且支持了基于 LLVM 的 JIT。

接下来看一看论文中介绍的 S2DB 在这三方面背后的细节

1 存算分离

在存储架构上 S2DB 既支持 shared-everything 即底层是共享存储,又支持 shared-nothing 即底层是单个的服务器节点。
其存储设计主要是利用计算节点的本地盘做缓存,Blob Storage 作为冷数据的存储仓库(类似冷热分离),数据通过 primary 节点 写入到本地之后会异步同步到 Blob Storage。利用本地盘的目的主要是降低事务的commit 延时(还是成本受限啊,Polar IMCI 所有计算以及存储节点都是 RDMA,就可以直接在共享存储上玩了)。
事务的 Durability 特性的保障是通过其存储架构完成的,一个 S2DB 集群内部会有多个副本,数据写入到内存之后无需等待 commit 就可以直接复制到任何一个持久化的的副本中,当一个事务的所有数据在多副本中的一个副本上完成持久化就可以标识这个事务是commit状态,且整个复制过程在 cache节点 支持乱序复制,即无需等待长事务,这样复制的延时在高并发下会非常低。事务的提交则是需要在持久化节点上来完成,通过LSN 保序提交。

基本数据的写入以及同步流程架构如下:
在这里插入图片描述

  1. 数据通过Aggregators( 类似 polardb-IMCI 中的 proxy节点) 聚合节点做完路由以及 负载均衡之后落入 PrimaryWorkspace 的一组主机中的一个服务器(hash 分片),为了降低本地写入的延时,本地存储都采用 较快的SSD – (冷热分离的目的)。

  2. 在当前服务器内存中构建行存以及列存相关的信息之后写入到 本地的redo log中,比如 上图中的 leaf log0 tail - master ,写入方式是 append-only。

  3. 此时虽然是本地盘已经持久化了,但是还不能提交事务,因为云上的高可用以及真正的持久化是一个计算节点下线不会导致数据丢失,但是S2DB 为了 TP的低延时借用了节点的本地盘,所以需要将 当前数据复制到其他 任意 leaf节点的当前log副本,比如 log0-replica, 才能向客户端返回事务提交。这样有一个数据的备份节点来做背书,就能实现高可用了。当然,这个复制策略可以实现为跨机房、数据中心 以及 大洲。
    因为数据需要复制,所以commit / abort 之前需要持久化的数据允许同步 且 支持乱序同步,这样就能降低因为数据复制而增加的延时。

  4. 完成 commit 需求的复制之后, 持久化的数据文件会异步上传到 Blob Storage,而redo-log文件则会按照文件 chunk ,上传某一个lsn/offset之前的数据页到 Blob Storage中,做一个truncate,这个日志的 末尾还会继续接受新的写入。

  5. 因为 Primary workspace 允许读写,为了从计算资源层面分离 AP 和 TP的workload,降低 AP 对 TP的影响,S2DB支持 创建只读工作区,即 Read-Only Workspace(也是一组服务器主机) ,会通过同步机制 从Primary workspace中的 master 服务器 拉取最新写入的 log 文件到自己的 leaf 服务器本地做AP 数据的缓存,这是为了保证数据的新鲜度(没有RDMA,没有数据的实时同步,显然只读副本的数据新鲜度并不高);剩余的历史数据如果有读需求,则会从 Blob Storage上拉取。

    只读 workspace 中的副本节点不会参与保障 commit 操作的数据同步,commit 需要的数据同步都是在 Primary Workspace 的服务器组中完成的。

  6. 为了实现 PITR (Point-In-Time-Recovery),当前时间点内存行存数据快照备份会直接写入到BlobStorage中,创建快照的过程只需要在 Primary WorkSpace完成。之所以需要为 in-memory的行存打快照,是因为其保存了当前集群当前时间点的全量状态的版本数据,只需要保证blobstorage的历史数据不真删除,就能实现 time-travel 到历史快照时间点的数据库状态。

2. 统一的表存储 (行列混存)

S2DB 实现行列混合存储的目的是为了降低用户使用的复杂度,任何workload都能很好的被处理,用户不需要自己分析自己的workload来做复杂的配置调研,S2DB AP TP workload都能适应,直接无脑使用就好了。

在 接受写入的计算节点中,整个行列混存的形态可以看作是一个 LSM-Tree 的实现。
在这里插入图片描述

  • 常驻内存的部分的 row-store 是一个无锁跳表,可以看作 LSM-tree 的 In-Memory数据结构。
  • 当内存中的行较多达到某一个阈值的时候 可以 flush 为列存存储的 segmemt 文件,flush 操作一行则从skiplist中删除改行记录(无锁跳表,页为了防止内存无限膨胀),对于数据文件中某一行的删除则也是 利用bitmap标识某一行被删除 并存储到 segment文件的元数据区域中,方便后续compaction进行清理或者读的时候只需要加载当前segment文件的 meta数据到内存就知道其内部哪一些数据被删除。这其实是为 LSM-tree 的 append-only delete做的改进,因为 delete版本过多本身会影响scan 以及 compaction的性能,现在只需要利用in-memory的 bitmap就能加速这个过程。
  • 为了避免磁盘的频繁写入(本质上不想和传统的LSM tree一样所有的版本都是append-only,不需要这么强的写入,会造成巨量的compaction从而影响读性能;宁愿牺牲写也需要保证 TP 的读),所以这里对于update 和 delete 都会更新 segment 文件的 metadata,这样就避免了过多的版本的写入;但是metadata 并发更新的原子性可能会对写入性能产生影响。

论文中没有详细介绍列存文件的存储格式,不过和IMCI row-group 列存文件格式 差异不大,一个segment文件每一列是一个block,一行的所有列保存到一个 segment文件中。

2.1 二级索引

在这里插入图片描述
为了提升点 TP场景的 查性能,需要在 Segment基础上实现二级索引,S2DB 主要在两方面发力:

  • 内部索引结构:segment 文件级别的 bloom filter,能高效判断要查的数据行的某一个列索引是否一定不存在于当前segment

  • 外部索引结构,在主键索引基础上实现一个外部索引结构(比如 spanner/ wiredtiger)加速查找。比如构造另一个 lsm-tree 或者 btree,有序存储多个segment中相同 主键的offset。首先每一个segment内部构造一个按主键倒排序的主键索引,存储当前索引行的列内偏移。

    如上图的左边部分,segmemt 列存文件内部 的inverted-index,其中存储了 foo: 1, 3 表示 主键列 为 fool 的 行有两个value,其在其他column 存储的便宜地址分别是 1, 3。如果我想查询主键为foo 的正行数据时,只需要找其他列的 1, 3 号偏移地址的内容就能读出 两行foo 的结果了。

    其次,在多个segment 文件之间基于 每一个文件的倒排索引构造一个 global index (可以是lsm-tree 或者 b-tree),其内部节点中保存主键列在不同文件的倒排索引内的偏移地址。比如,对于foo列,能够hash映射到 0x24行,其内容 s1:offset 1, s3: …,则表示 foo 这一行的内容可以先去 s1号segment文件的 inverted-index 的 offset1 去拿段内偏移地址;再去 s3号segment文件的 indverted-index 的 offset…去拿 s3内存储 foo 所在行数据的偏移地址。

global-index 这里有一个细节是说其lsm-tree 节点有序存储 主键的hash值 以及 行的物理偏移地址。但是会受到 segment 文件 compaction的影响,因为compaction 会更改行的偏移地址。这个时候就需要对global-index 中存储的节点进行修改,但是因为 列存有效减少了 update/delete的版本写入,本身compaction量就比较少,这样global-index 更新频率也就比较少了,这也是降低lsm-tree写入的一个额外优势了。加速了TP的读性能。

inverted-index 以及 global-index 实际都可以被放在内存中,寻址很快,能够极位高效得为 TP 场景实现点查功能。

后续S2DB 索引相关的部分介绍了多列索引 如何加速多filter的过滤 以及 如何利用当前二级索引的实现方式支持唯一性检查的(segment文件内部并没有实现LSM-tree的按主键排序)。

2.2 行锁

也是前面提到的 为了减少compaction 而将 update/delete的追加写方式变更为 segment metadata 中 bitmap的标记。这样简单的实现在update/delete场景较多时会出现改bitmap的竞争问题,所以需要通过行锁来保护 update/delete的原子操作,多用户并发操作同一行场景时只能保证一位用户commit/abort之后其他用户才能操作。
S2DB 实现方式较为独特,不是直接去修改 segments的metadata,而是构造一个移动事务,将对segment-metadata 的操作转为对in-memory row-store的操作,这样修改可以立即commit并生效(多了一个版本),不影响用户的读。后续再用行锁来保护对segment-metadata 中bitmap的修改。针对内存 row-store 构造的 一个移动事务 可以batch多个客户端对当前行的操作,减少增加的版本数量。

3. 自适应查询引擎

由于 HTAP的 workload 对 AP 和TP 的界限区分并不明显,查询引擎需要结合不同的访问方式来提供不同workload的最佳性能。比如,一个query 的一个filter可能会使用二级索引,而另一个则可以使用 encoded 的filter。S2DB 不需要用户介入,能够自适应得为用户做出最佳的数据访问决策。

一个 query 从 S2DB 输入到拿出数据会大体经历三个步骤:

  1. 找到要读取的 segments 列表
  2. 运行filter,从每一个segment文件中找到要读取的行
  3. 有选择得解码并输出对应行

论文中介绍的 查询引擎的工作主要集中在前两步,如何动态决策选择要读取的segments列表 以及 选择filter。

3.1 Segment skipping 实现

主要通过全局二级索引 以及 segment-metadata 来尝试跳过要访问的 segments。

  1. 先访问 全局二级索引(global index) 或者 segment metadata 中的 min/max来跳过某一些segment。
  2. 如果要查的键的数目过多,则会动态禁用二级索引。二级索引的自适用禁用在 join场景非常重要,因为join的过程涉及多表数据,会急速增加索引键的数量从而增加索引查找的成本。

3.2 Filtering 选择

选择合适的 Filter也非常重要 (col1 =val1),S2DB 提供了四种 Filter类型用于评估:

  1. Regular filter, 有选择得为上一个filter decode col1,拿着decode 之后的value 去匹配当前filter
  2. Encoded filter 可以直接在压缩数据上执行,比如字典编码场景,可以在不decode的情况下过滤所有可能是col1 的行。不过仅使用tuple 较少的场景。
  3. Group filter,先decode 所有拿到的列,将filter作为小条件(短小的内部循环),不是每一行数据都经历完整的匹配逻辑,方便利用cpu-cache。这个场景对 满足group filter条件的场景优势较大,如果大多数行都不满足filter,其效果还不如regular filter。
  4. Secondary index filter. 利用 global 二级索引的查找,筛选满足filter 的 row-offset;在以 val1为primary-index 的 global-index中,如果有较多的行需要过滤,二级索引filter 效率肯定比regular filter好,行数较少,可能构建二级索引的过程+访问比regular filter 直接顺序遍历segment-metadata 拿对应行 效率更低。

这四种Filter 如何选择,对于两个filter 语句 A AND B则是遵循如下公式:
1 − P ( B ) c o s t ( B ) < = 1 − P ( A ) c o s t ( A ) \frac{1-P(B)}{cost(B)} <= \frac{1-P(A)}{cost(A)} cost(B)1P(B)<=cost(A)1P(A), 其中

  • cost(X) 为 optimizer 为 X 子句评估的cost
  • P(X) 是为当前语句选择的 filter 计算的选择性

满足以上等式,则建议优先 eval A 子句。

至于P(X) 以及 cost(X) 到底如何计算得出来的,论文中基本没说,本身这个也是优化器的核心,论文对optimizer 基本没提,毕竟受篇幅影响以及是核心竞争力,而且项目没有开源,没必要为了顶会全盘抖出来,让大家知道我们牛逼就好了。

因为优化器我也不懂,对于给出的公式以及这一些计算属性也不好推导,也就只能放在这里等日后或者懂的同学解惑:)

4 性能

感觉数据没有特别全面,比如没有详细的混合 workload中 TPC-H 对 TPC-C的影响,polardb-IMCI 今年的数据就测的比较好,毕竟HTAP 大家还是很关注这一方面的影响;还有就是数据新鲜度的测试,Primary workspace的数据多久才能被 Read-only workspace读到呢?

直接看 TPC-C 和 TPC-H(1T)各自的数据如下,也还不错:

在这里插入图片描述

总结

SingleStoreDB 总体架构是 in-memory rowstore + columnstore,单节点行列混存 并用LSM-tree 以及 Global-index 加速数据的更新和读取。利用本地节点缓存降低事务commit 延时,在不同节点之间允许乱序同步redo-log 加速同步效率。

首先与成本 以及 云基础设施,没法像 PolarDB-IMCI 全链路 rdma降低延时,为了 TP 的commit性能 S2DB 在实现过程中也是煞费苦心。本地盘SSD缓存 + 乱序同步 redo-log 到一个副本本地 才能提交, polardb-IMCI 今年将同步部分的实现在论文中详细展开了,只是polardb 因为直接rdma 持久化到共享内存,是异步同步实现的,保证了极高的数据新鲜度。

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

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

相关文章

openresty离线rpm升级至openresty-1.19.9.1版本

注意&#xff1a;此方法步骤仅本人验证通过&#xff0c;要升级的话&#xff0c;需要做备份 1。系统版本是centos7(Linux version 3.10.0-693.el7.x86_64) 2。默认openresty版本是1.15.8.1 3。本次升级到openresty-1.19.9.1 目前系统是没有连接外网&#xff0c;只能进行rpm离…

网络重置后无法上网,以太网和无线网全部丢失,网络适配器出现“56”错误码

文章目录 一、问题描述电脑系统&#xff1a;电脑问题&#xff1a;解决方案 二、问题过程1. IP问题2.网络重置问题3.电脑无法启动问题 三、解决方案1.卸载2.安全模式检查修复3.软件下载1.CCleaner2.驱动精灵万能网卡版 四、参考链接 一、问题描述 电脑系统&#xff1a; Window…

【MySQL高级篇笔记-索引的创建与设计原则 (中) 】

此笔记为尚硅谷MySQL高级篇部分内容 目录 一、索引的声明与使用 1、索引的分类 2、创建索引 1. 创建表的时候创建索引 2. 在已经存在的表上创建索引 3、删除索引 二、MySQL8.0索引新特性 1、支持降序索引 2、 隐藏索引 三、索引的设计原则 1、哪些情况适合创建索引…

Android 应用快捷ShortcutManager与ShortcutManagerCompat详解与实战(二)

一、介绍 之前我已通过一篇文章介绍了应用快捷的接入与Demo。如果还未看过上一篇的文章可以先了解入门。 传送门&#xff1a;Android 应用快捷(shortcut)功能的详解(一)_蜗牛、Z的博客-CSDN博客 有创建自然就会有管理&#xff0c;否则一个完美的方案不应该这么被推荐出来。如何…

红黑树的 概念性质 和 详解实现(插入旋转等)

文章目录 概念满足的条件性质实现红黑树的定义红黑树节点插入操作情况一情况二情况三Insert()总代码 其余操作左右单旋RotateL 左单旋RotateR 右单旋prevCheck 红黑树性质检测isBalance 红黑树平衡判断InOrder 中序遍历 完整代码 概念 红黑树&#xff0c;是一种二叉搜索树&…

HNU-操作系统OS-ucoreLab系列-感悟

谨以此片篇,献给熬夜的8个晚上,以及逝去的时光。 感悟: 今天结束了所有的Lab实验(2023.6.3),感慨万千。 喜是这个实验终于结束了,悲是其实有好多地方我都没有理解。 应该指出,由于验收的助教学长学姐们的宽容,HNU实际上在验收这一块的要求还是比较低的。 但是这个…

第三章 Electron 使用Koa以及Koa-Router

一、Koa是什么 &#x1f447; &#x1f447; &#x1f447; 据网上的资料显示&#xff0c;Koa 是下一代的 Node.js 的 Web 框架。是express原班人马打造,同样用于构建服务端web application的。旨在提供一个更小型、更富有表现力、更可靠的 Web 应用和 API 的开发基础。扯这些…

在输入URL后,前端浏览器的工作流程

这是一个经久不衰的面试题&#xff0c;整理一下。 浏览器 浏览器是一个多进程的架构。 主进程&#xff1a;主要适用于界面的显示&#xff0c;用户的交互&#xff0c;子进程管理。 渲染进程&#xff1a;将HTML&#xff0c;css&#xff0c;JS转换成页面&#xff0c;V8引擎以及…

redisson 随笔 0-入门

0. 虽说时运不佳&#xff0c;仍欲提桶跑路 分布式锁的常见实现方案 常用锁的用例 runoob Lua教程 对于分布式锁的实现方案&#xff0c;本文如标题所言&#xff0c;简单梳理了redisson的实现方案 redisson 也是基于redis的多个命令组合来实现的&#xff0c;为保证执行多个命…

项目实战:基于Linux的Flappy bird游戏开发

一、项目介绍 项目总结 1.按下空格键小鸟上升&#xff0c;不按小鸟下落 2.搭建小鸟需要穿过的管道 3.管道自动左移和创建 4.小鸟撞到管道游戏结束 知识储备 1.C语言 2.数据结构-链表 3.Ncurses库 4.信号机制 二、Ncurses库介绍 Ncurses是最早的System V Release 4.0 (…

F. Editorial for Two(二分答案+反悔贪心)

F. Editorial for Two&#xff08;二分答案反悔贪心&#xff09; F. Editorial for Two 1、问题 给定一个 n n n和 k k k&#xff0c;以及一个长度为 n n n数组。现在从 n n n个数中&#xff0c;挑出 k k k个数&#xff0c;称作个子序列。然后将这个子序列分成两部分&#x…

干翻Mybatis源码系列之第八篇:Mybatis二级缓存的创建和存储

给自己的每日一句 不从恶人的计谋&#xff0c;不站罪人的道路&#xff0c;不坐亵慢人的座位&#xff0c;惟喜爱耶和华的律法&#xff0c;昼夜思想&#xff0c;这人便为有福&#xff01;他要像一棵树栽在溪水旁&#xff0c;按时候结果子&#xff0c;叶子也不枯干。凡他所做的尽…

C++之---树/数据结构

一、树 什么是树&#xff1f; 1.1 树&#xff08;Tree&#xff09;是n&#xff08;n>0&#xff09;个结点的有限集。n0时称为空树。在任意一棵非空树中&#xff1a; &#xff08;1&#xff09; 有且仅有一个特定的称为根&#xff08;Root&#xff09;的结点&#xff1b; &am…

CodeForces..最新行动.[中等].[遍历].[判断]

题目描述&#xff1a; 题目解读&#xff1a; "最近操作"字段会显示最近操作的n个文件。 最初有编号文件1&#xff0c;2&#xff0c;... n在"最近操作"字段&#xff0c;还有其他无限多个文件不在。 当某个文件pi发生操作时&#xff1a; 如果它位于“最近…

小红书账号矩阵优化软件

小红书账号矩阵优化软件 大家有关注过品牌在⼩红书上的打法有哪些吗&#xff1f; #品牌营销#小红书运营#爆文拆解#品牌投放#爆品打造 我们如果确定了我们要去做小红书&#xff0c;那我到底该怎么去做&#xff1f;现在小红书对我们目前这些品牌来说&#xff0c;你们是作为把它…

Allegro16.6详细教程(二)

R.3-D Viewer 3-D Viewer,可以直接在allegro中看到board file的3-D顯示效果。3-D Viewer對於PCB Editor Products,只有環境變數中的OpenGL顯示功能開啟後才有效,而對於APD/SiP是無效的。 2.3-D viewer是在一個獨立的視窗中打開的。3-D environment環境支援多種顯示內容的過…

Spring Cloud Alibaba - Nacos源码分析(二)

目录 一、Nacos服务端服务注册 1、服务端调用接口 2、服务注册 instanceServiceV2.registerInstance EphemeralClientOperationServiceImpl.registerInstance ServiceManager clientManager Client实例AbstractClient ClientOperationEvent.ClientRegisterServiceEven…

2023《中国好声音》全国巡演Channel[V]歌手大赛广州赛区半决赛圆满举行!

2023年5月27-28日&#xff0c;由腾扬广告、Channel[V]、盛娱星汇联合主办的2023《中国好声音》全国巡演Channel[V]歌手大赛广州赛区半决赛在广州番禺天河城正式打响&#xff0c;自广州赛区赛事启动以来&#xff0c;汇集了近五千名音乐人参与其中&#xff0c;历经2个多月、超40场…

【数据库复习】第七章 数据库设计

数据库设计的过程(六个阶段) ⒈需求分析阶段 准确了解与分析用户需求&#xff08;包括数据与处理&#xff09; 最困难、最耗费时间的一步 ⒉概念结构设计阶段 整个数据库设计的关键 通过对用户需求进行综合、归纳与抽象&#xff0c;形成一个独立于具体DBMS的概念模型 ⒊…

基于微信小程序蛋糕店商城管理系统的设计与实现

1&#xff1a;后端采用技术 SpringBoot 、Mybatis、Mybatis-plus、Redis、阿里云短信息服务、Hutool 邮箱服务、WebSocket通讯服务、OSS对象存储服务、支付宝沙箱服务&#xff0c;接口简单限流、简单定时任务。。。。。。 2&#xff1a;前端采用技术 Vue2、Vue2-uploader组件、…