Hologres(中文名交互式剖析)是阿里云自研的一站式实时数仓,这个云原生零碎交融了实时服务和剖析大数据的场景,全面兼容 PostgreSQL 协定并与大数据生态无缝买通,能用同一套数据架构同时反对实时写入实时查问以及实时离线联邦剖析。它的呈现简化了业务的架构,与此同时为业务提供实时决策的能力,让大数据施展出更大的商业价值。从阿里团体诞生到云上商业化,随着业务的倒退和技术的演进,Hologres 也在继续一直优化核心技术竞争力,为了让大家更加理解 Hologres,咱们打算继续推出 Hologers 底层技术原理揭秘系列,从高性能存储引擎到高效率查问引擎,高吞吐写入到高 QPS 查问等,全方位解读 Hologers,请大家继续关注!
往期精彩内容:
2020 年 VLDB 的论文《Alibaba Hologres: A cloud-Native Service for Hybrid Serving/Analytical Processing》
本期咱们将介绍 Hologers 的存储引擎
一、背景介绍
MaxCompute 交互式剖析(Hologres)是阿里云自研开发的 HSAP(Hybrid Serving/ Analytical Processing)服务 / 剖析一体化零碎,交融了实时服务和剖析大数据的场景,全 面兼容 PostgreSQL 协定并与大数据生态无缝买通。它的呈现简化了业务的架构,与此同时为 业务提供实时做出决策的能力,让大数据施展出更大的商业价值。对于架构更具体的介绍,请看文末 VLDB 论文。
跟传统的大数据和 OLAP 零碎相比,HSAP 零碎面临着如下的挑战:
- 高并发的混合工作负载:HSAP 零碎须要面对远远超出传统的 OLAP 零碎的并发查问。在实践中,数据服务的并发远远超出 OLAP 的查问。例如,咱们在事实的利用中见到数据服务须要解决高达每秒钟数千万个查问,这比 OLAP 查问的并发高出了 5 个数量级。同时,和 OLAP 查问相比,数据服务型查问对提早有着更加刻薄的要求。简单的混合查问负载对系统的提早和吞吐有着十分不同的取舍。如何在高效地利用零碎的资源同时解决好这些十分不 一样的查问,并且保障每个查问的 SLO 是个微小的挑战。
- 高吞吐实时数据导入:在解决高并发的查问负载的同时,HSAP 零碎还须要解决海量的实时数据导入。从传统的 OLTP 同步过去的数据只是这其中的一小部分,其余还有大量的数据来自日志等没有强事务语意的零碎。实时导入的数据量远远超过了传统的 HTAP 或者 OLAP 零碎。和传统的 OLAP 零碎的另外一个区别是对数据的实时性有着很高的要求,导入的数据须要在秒级甚至亚秒级可见,这样能力保障咱们服务和剖析后果的时效性。
- 弹性和可扩展性:数据导入和查问负载可能会有突发的顶峰,这对 HSAP 零碎提出了很高的弹性和可扩展性的要求。在事实的利用中,咱们留神到数据导入峰值能达到是均匀的 2.5 倍,查问的峰值可能达到均匀的 3 倍。数据导入和查问的峰值可能不肯定同时呈现,这也须要零碎有依据不同的峰值做迅速调整的能力。
基于上诉背景,咱们自研了一款存储引擎(Storage Engine),次要负责管理和解决数据,包含创立,查问,更新,和删除(简称 CRUD)数据的办法。存储引擎的设计和实现提供了 HSAP 场景所须要的高吞吐,高并发,低提早,弹性化,可扩展性的能力。依据阿里团体业务和云上客户的需要,咱们不断创新和打磨,倒退到明天,能反对单表 PB 级存储,并完满撑持 2020 年天猫双 11 外围场景千亿个级别的点查问和千万个级别的实时简单查问。
上面,咱们将会对 Hologres 底层的存储引擎做具体的介绍,并介绍存储引擎落地 Hologres 的具体实现原理和技术亮点。
二、数据模型
Hologres 存储引擎的根本形象是分布式的表,为了让零碎可扩大,咱们须要把表切分为 分片(shard)。为了更高效地反对 Join 以及多表更新等场景,用户可能须要把几个相干的 表寄存在一起,为此 Hologres 引入了表组(Table Group)的概念。分片策略齐全一样的一 组表就形成了一个表组,同一个表组的所有表有同样数量的分片。用户能够通过“shard_count”来指定表的分片数,通过“distribution_key”来指定分片列。目前咱们只反对 Hash 的分片形式。
表的数据存储格局分为两类,一类是行存表,一类是列存表,格局能够通过“orientation” 来指定。
每张表里的记录都有肯定的存储程序,用户能够通过“clustering_key” 来指定。如果没有指定排序列,存储引擎会依照插入的程序主动排序。抉择适合的排序列可能大大优化一些查问的性能。
表还能够反对多种索引,目前咱们反对了字典索引和位图索引。用户能够通过“dictionary_encoding_columns” 和“bitmap_columns” 来指定须要索引的列。
上面是一个示例:
这个例子建了 LINEITEM 和 ORDERS 两个表,因为 LINEITEM 表还指定了主键(PRIMARY KEY),存储引擎会主动建设索引来保障主键的惟一。用户通过指定“colocate_with“把这两个表放到了同一个表组。这个表组被分成 24 个分片(由 shard_count 指定)。LINEITEM 将依据 L_ORDERKEY 的数据值来分片,而 ORDERS 将依据 O_ORDERKEY 的数据值来分片。LINEITEM 的 L_SHIPINSTRUCT 以及 ORDERS 的 O_ORDERSTATUS 字段将会创立字典。LINEITEM 的 L_ORDERKEY, L_LINENUMBER, L_SHIPINSTRUCT 字段以及 ORDERS 的 O_ORDERKEY,O_CUSTKEY,O_ORDERSTATUS 字段将会创立位图索引。
三、存储引擎架构
1)总体架构
每个分片(Table Group Shard,简称 Shard)形成了一个存储管理和复原的单元(Recovery Unit)。上图显示了一个分片的根本架构。一个分片由多个 tablet 组成,这些 tablet 会共享一个日志(Write-Ahead Log,WAL)。存储引擎用了 Log-Structured Merge(LSM)的技术,所有的新数据都是以 append-only 的模式插入的。数据先写到 tablet 所在的内存表 (MemTable),积攒到肯定规模后写入到文件中。当一个数据文件敞开后,外面的内容就不会变了。新的数据以及后续的更新都会写到新的文件。与传统数据库的 B±tree 数据结构相比,LSM 缩小了随机 IO,大幅的进步了写的性能。
当写操作一直进来,每个 tablet 里会积攒出很多文件。当一个 tablet 里小文件积攒到肯定数量时,存储引擎会在后盾把小文件合并起来(Compaction),这样零碎就不须要同时关上很多文件,能缩小应用系统资源,更重要的是合并后文件缩小了,进步了读的性能。
在 DML 的性能上,存储引擎提供了单条或者批量的创立,查问,更新,和删除(CRUD 操作)拜访办法的接口,查问引擎能够通过这些接口拜访存储的数据。
2)存储引擎组件
上面是存储引擎几个重要的的组件:
- WAL 和 WAL Manager
WAL Manager 是来治理日志文件的。存储引擎用预写式日志(WAL) 来保证数据的原子性 和持久性。当 CUD 操作产生时,存储引擎先写 WAL,再写到对应 tablet 的 MemTable 中,等 到 MemTable 积攒到肯定的规模或者到了肯定的工夫,就会把这个 MemTable 切换为不可更改的 flushing MemTable,并新开一个 MemTable 接管新的写入申请。而这个不可更改的 flushing MemTable 就能够刷磁盘,变成不可更改的文件;当不可更改的文件生成后,数据就能够算长久化。当零碎产生谬误解体后,零碎重启时会去 WAL 读日志,复原还没有长久化 的数据。只有当一个日志文件对应的数据都长久化后,WAL Manager 才会把这个日志文件 删除。 - 文件存储
每个 tablet 会把数据存在一组文件中,这些文件是存在 DFS 里(阿里巴巴盘古或者 Apache HDFS)。行存文件的存储形式是 Sorted String Table(SST)格局。列存文件反对两种存储格局:一种是相似 PAX 的自研格局,另外一种是改进版的 Apache ORC 格局(在 AliORC 的根底上针对 Hologres 的场景做了很多优化)。这两种列存格局都针对文件扫描的场景做了优化。 - Block Cache (Read Cache)
为了防止每次读数据都用 IO 到文件中取,存储引擎通过 BlockCache 把罕用和最近用的数据放在内存中,缩小不必要的 IO,放慢读的性能。在同一个节点内,所有的 Shard 共享一个 Block Cache。Block Cache 有两种淘汰策略:LRU(Least Recently Used,最近起码应用)和 LFU(Least Frequently Used, 最近不罕用)。顾名思义,LRU 算法是首先淘汰最长工夫未被应用的 Block,而 LFU 是先淘汰肯定工夫内被拜访次数起码的 Block。
3)读写原理
Hologres 反对两种类型的写入:单分片写入和分布式批量写入。两种类型的写入都是原子的(Atomic Write),即写入或回滚。单分片写入一次更新一个 shard,然而须要反对极高 的写入频率。另一方面,分布式批写用于将大量数据作为单个事务写到多个 shard 中的场景,并且通常以低得多的频率执行。
单分片写入
如上图所示,WAL 管理器在接管到单分片写申请后,(1)为写申请调配一条 Log Sequence Number(LSN),这个 LSN 是由工夫戳和递增的序号组成,并且(2)创立一条新的日志,并在文件系统中的长久化这条日志。这条日志蕴含了复原写操作所需的信息。在齐全保留这条日志后,才向 tablet 提交写入。之后,(3)咱们会在相应 tablet 的内存表(MemTable) 中执行这个写操作,并使其对新的读申请可见。值得注意的是,不同 tablet 上的更新能够并行化。当一个 MemTable 满了当前,(4)将其刷新到文件系统中,并初始化一个新的 MemTable。最初,(5)将多个分片文件在后盾异步合并(Compaction)。在合并或 MemTable 刷新完结时,治理 tablet 的元数据文件将相应更新。
分布式批量写入
接管到写入申请的前台节点会将写申请散发到所有相干的分片。这些分片通过两阶段提交机制(Two Phase Commit) 来保障分布式批量写入的写入原子性。
多版本读
Hologres 反对在 tablet 中多版本读取数据。读申请的一致性是 read-your-writes,即客户端始终能看到本人最新提交的写操作。每个读取申请都蕴含一个读取工夫戳,用于结构读的 snapshot LSN。如果有一行数据的 LSN 大于 snapshot LSN 的记录,这行数据就会被过滤掉,因为他是在读的 snapshot 产生后才被插入到这个 tablet 的。
四. Hologres 存储引擎技术亮点
1)存储计算拆散
存储引擎采纳存储计算拆散的架构,所有的数据文件存在一个分布式文件系统(DFS, 例如阿里巴巴盘古或者 Apache HDFS)的外面。当查问负载变大须要更多的计算资源的时候能够独自扩大计算资源;当数据量快速增长的时候能够疾速独自扩大存储资源。计算节点和存储节点能够独立扩大的架构保障了不须要期待数据的拷贝或者挪动就能疾速扩大资源;而且,能够利用 DFS 存多正本的机制保证数据的高可用性。这种架构岂但极大地简化了运维,而且为零碎的稳定性提供了很大的保障。
2)异步执行流程
存储引擎采纳了基于事件触发, 非阻塞的纯异步执行架构, 这样可能充分发挥古代 CPU 多 core 的解决能力,进步了吞吐量,反对高并发的写入和查问。这种架构得益于 HOS(HoloOS) 框架,HOS 在提供高效的异步执行和并发能力的同时,还能主动地做 CPU 的负载平衡晋升零碎的利用率。
3)对立的存储
在 HSAP 场景下,有两类查问模式,一类是简略的点查问(数据服务 Serving 类场景),另一类是扫描大量数据的简单查问(剖析 Analytical 类场景)。当然,也有很多查问是介于两者之间的。这两种查问模式对数据存储提出了不同的要求。行存可能比拟高效地反对点查问,而列存在反对大量扫描的查问上有显著的劣势。
为了可能反对各种查问模式,对立的实时存储是十分重要的。存储引擎反对行存和列存的存储格局。依据用户的需要,一个 tablet 能够是行存的存储格局(实用于 Serving 的场景);也能够是列存的存储格局(实用于 Analytical 的场景)。比方,在一个典型 HSAP 的场景,很多用户会把数据存在列存的存储格局下,便于大规模扫描做剖析;与此同时,数据的索引存在行存的存储格局下,便于点查。并通过定义 primary key constraint(咱们是用行存来实现的)用来避免数据反复·。不论底层用的是行存还是列存,读写的接口是一样的,用户没有感知,只在建表的时候指定即可。
4)读写隔离
存储引擎采纳了 snapshot read 的语意,读数据时采纳读开始时的数据状态,不须要数据锁,读操作不会被写操作 block 住;当有新的写操作进来的时候,因为写操作是 append-only,所有写操作也不会被读操作 block 住。这样能够很好的反对 HSAP 的高并发混合工作负载场景。
5)丰盛的索引
存储引擎提供了多种索引类型,用于晋升查问的效率。一个表能够反对 clustered index 和 non-clustered index 这两类索引。一个表只能有一个 clustered index,它蕴含表里所有的列。一个表能够有多个 non-clustered indices。在 non-clustered indexes 里,除了排序用的 non-clustered index key 外,还有用来找到全行数据的 Row Identifier (RID)。如果 clustered index 存在,而且是独特的,clustered index key 就是 RID;否则存储引擎会产生一个独特的 RID。为了进步查问的效率,在 non-clustered index 中还能够有其余的列,这样在某些查问时,扫一个索引就能够拿到所有的列的值了(covering index)。
在数据文件外部,存储引擎反对了字典和位图索引。字典能够用来进步解决字符串的效率和进步数据的压缩比,位图索引能够帮忙高效地过滤掉不须要的记录。
五. 结语
存储引擎的设计思路和研发方向是为了更好的反对 HSAP 的场景,能高效的反对高吞吐的实时写入和交互式查问,而且对离线的批量写入做了优化。在写入量和存储量每年都成倍的增长下,Hologres 禁受住了严苛的考验,完满地度过了多个双 11。“Hologres 顶住了 5.96 亿每秒的实时数据洪峰,单表存储高达 2.5PB。基于万亿级数据对外提供多维分析和服务,99.99%的查问能够在 80ms 以内返回后果”。这组数据充沛显示了存储引擎的技术能力,同时也印证了咱们技术架构和实现的劣势。
当然,Hologres 还是一个新产品,HSAP 是个新理念,“明天的最好只是今天的开始”,咱们还在一直地精益求精,凝听客户的反馈,今后会在稳定性,易用性,以及性能和性能上继续晋升。
作者:江渊,阿里巴巴资深技术专家,在数据库和大数据畛域有多年丰盛的教训。
后续咱们将会陆续推出无关 Hologres 的技术底层原理揭秘系列,具体布局如下,敬请继续关注!
Hologres 揭秘:首次公开!阿里巴巴云原生实时数仓核心技术揭秘
Hologres 揭秘:首次揭秘云原生 Hologres 存储引擎(本文)
Hologres 揭秘:深度解析高效率分布式查问引擎
Hologres 揭秘:通明减速 MaxCompute 查问外围原理
Hologres 揭秘:如何实现 MaxCompute 与 Hologres 数据同步速度快百倍
Hologres 揭秘:如何反对高吞吐 Upsert
Hologres 揭秘:如何反对在线服务场景的超高 QPS
Hologres 揭秘:如何反对高并发查问
Hologres 揭秘:如何反对高可用架构
Hologres 揭秘:如何反对资源隔离,反对多种负载
Hologres 揭秘:向量检索引擎 Proxima 原理与应用实际
Hologres 揭秘:读懂执行打算,查问性能翻十倍
Hologres 揭秘:分布式系统如何设计 Shard 与 Table Group
Hologres 揭秘:如何反对更多 Postgres 生态扩大包
Hologres 揭秘:高吞吐写入 Hologres 的 N 种姿态
……