AnalyticDB for MySQL:AI时代实时数据分析的最佳选择

简介: 阿里云云原生数据仓库AnalyticDB MySQL(ADB-M)与被OpenAI收购的实时分析数据库Rockset对比,两者在架构设计上有诸多相似点,例如存算分离、实时写入等,但ADB-M在多个方面展现出了更为成熟和先进的特性。ADB-M支持更丰富的弹性能力、强一致实时数据读写、全面的索引类型、高吞吐写入、完备的DML和Online DDL操作、智能的数据生命周期管理。在向量检索与分析上,ADB-M提供更高检索精度。ADB-M设计原理包括分布式表、基于Raft协议的同步层、支持DML和DDL的引擎层、高性能低成本的持久化层,这些共同确保了ADB-M在AI时代作为实时数据仓库的高性能与高性价比


1. 引言

在今年6月21日OpenAI官宣了收购实时分析数据库公司 Rockset,以进一步提升其在AI 领域的服务和产品,为客户提供更加高效和智能的数据处理解决方案。当我们去深入分析Rockset有何独特能力让其被AI时代的领头羊OpenAI看中时,发现Rockset的设计与阿里云云原生数据仓库AnalyticDB for MySQL(以下简称ADB-M)“英雄所见略同”:两者在整体架构、存储及索引实现、存算分离、实时增删改能力等方面惊人的相似,但是ADB-M实现的更早、更超前且历经了海量业务的线上生产验证。ADB-M在阿里巴巴内部、阿里云上历经多年研发,伴随业务发展不断解决海量数据分析的种种挑战、不断满足客户多种多样的差异化需求,最终使其演化成了最适合AI时代的实时数仓。本文将深入介绍ADB-M的设计及实现原理,并适当将其与Rockset进行比较。

2. ADB-M简介及与Rockset特性比较分析

云原生数据仓库AnalyticDB MySQL版是阿里巴巴自主研发、经过超大规模以及核心业务验证的PB级实时数据仓库。服务了包括传统大中型企业、政府机构和互联网公司等各类在线分析系统,覆盖电商、广告、物流、文娱、旅游、风控等众多行业。AnalyticDB MySQL版采用云原生架构,所有组件可以横向/纵向扩展,计算存储分离、冷热数据分层,支持高吞吐实时写入和数据强一致,兼顾高并发查询和大吞吐批处理的混合负载。ADB-M底层的玄武存储引擎是ADB-M的自研列存,具备高吞吐的实时写入、高性能的实时查询、超大规模的数据体量、完备DML和OnlineDDL的数据库体验、自动冷热分层和生命周期淘汰的低成本选择,是AnalyticDB MySQL的基础支撑。

Rockset是从2016年开始投入研发的实时数仓公司,基于RocksDB提供了对外的云服务,具体应用覆盖了推荐引擎、物流跟踪、金融科技、电子商务等多个领域。其主要特点包括存算分离、实时写入、全索引、schemaless、低成本存储、向量融合检索等。

AI时代,大模型的模型训练、精调、部署、迭代,都极其依赖高质量的海量数据作为基础。而这些数据的多源采集、海量存储、低成本管理、快速导入、极速检索是AI时代的核心竞争力所在。ADB-M及Rockset作为实时数仓的典型代表在这些数据处理方面提供了强大的能力支撑,但是又有所区别,下文将展开详述。

2.1 存算分离架构

ADB-M与Rockset类似,都将计算及存储完全分离。ADB-M底层存储节点基于阿里云对象存储OSS、阿里云块存储EBS,上层计算节点基于ECS、K8S,存储及计算资源能够独立拓展;且计算层又进一步支持多个资源组,不同资源组之间完全隔离,可以用于不同业务避免相互干扰。

与Rockset不同的是,ADB-M支持了更丰富多样的弹性能力:

  • 分时弹性:可以根据业务特征显示配置计算资源的定时升配、降配规则;
  • 按需弹性:当收到ETL SQL时才进行资源拉起,最大程度降低成本;
  • 单个资源组内的自动弹性Multi-Cluster:根据实时资源使用率(如CPU、Memory等)来实时调整资源规模。

AI大模型的训练需要海量数据,且伴随时间推移需要的数据体量将会越来越大,其耗费的存储资源、计算资源、电力资源极其惊人。据研究统计,到2027年AI将消耗掉荷兰整个国家的年度用电量。

而结合ADB-M提供的存算分离架构,在持续提供、增加存储资源的同时,不需要同步增加计算资源,大幅度降低了CPU/Memory的消耗;而且相比于Rockset,由于ADB-M提供了分时弹性、按需弹性、Multi-Cluster等Rockset不具备的能力,将能够最大限度使资源消耗等同于实际需要,最大化降低AI企业的成本。

2.2 实时一致性

ADB-M是同步写入模型,支持强一致性,高吞吐写入后立即可见。在ADB-M内部基于日志同步、实时引擎、主键、DeleteSet和行级MVCC进行实现,在超大规模数据集下仍然做到所有DML的行级实时可见。查询时各个Shard各自取Leader最新位点所对应的行级快照,即可满足完全实时可见并保证强一致。

而Rockset的写入是异步动作,只保证最终一致性,写入后1-5S才可查。

AI模型训练所需要的数据,来自于多种多样的数据源,传统的离线导入能力往往需要隔天T+1导入,损失了数据新鲜度。在类似智能问答机器人、新闻智能推荐等AI场景中,数据新鲜度的降低会严重降低业务价值。ADB-M提供了比Rockset更好的、具备强一致性的实时数据读写能力,通过数据实时可见确保数据新鲜度;且强一致性也极大简化了上层数据系统的开发难度,提升了数据清洗、提取、转换的工作效率,确保模型训练的每一个环节都能够得到加速。

2.3 全类型全索引

在索引方面,ADB-M与Rockset的相似之处在于两者都自动对所有列建立了索引。不同之处在于:

1)Rockset对于每一列都做了3种索引:适用于点查的倒排索引,适用于聚合的列存索引,适用于数据获取的行存索引;在提供丰富访问模式的同时,也进入了较大的存储开销。

2)ADB-M则提供了更丰富、更细粒度的索引能力。

ADB-M面向极致的查询下推和延迟物化设计,支持了包括倒排索引、BKD索引、Bitmap索引、向量索引、全文索引、JSON索引等几乎全类型的列级索引实现,覆盖结构化数据和半结构化数据,适用于不同场景的查询性能。全索引的默认设置,玄武引擎会自动为不同列类型选择不同的索引实现,用户无需干预只需专注业务对SQL的使用。

除列级二级索引外,还支持聚集索引(Clustering Key),是一种行数据排序键,使得数据按定义的列顺序分布,使得IO基于排序列聚集,能极大提升在这些排序列上的数据读取效率。ADB-M进一步提供了智能索引能力,结合用户的SQL Pattern提供了自动索引推荐、无用索引删除的功能。

RAG(Retrieval-agumented-generation)是AI大模型最为典型的应用场景,也是ChatGPT等问答机器人的关键前置条件。高质量、高效的retrieval能够极大程度上提升问答准确性,是整个AI时代的必备基础设施。ADB-M相比Rockset提供了更细粒度、更多类型的不同索引,在数据搜索上有更高性能;提供了聚集索引,使得数据存储更有序,进一步提升了压缩比及IO性能;最终能够降低客户侧的E2E响应延时。

2.4 高吞吐写入

两者都能够支持高吞吐数据导入。ADB-M基于主键和DeleteSet的AppendOnly + 后台Compaction设计实现,能够满足引擎级高性能实时写入;同时在架构上的分片使得写并发可横向拓展,整个实例以多表多并发同时写入的方式,支撑实例级的高吞吐实时入库。Rockset采用Tailer-Leaf-Aggregator架构,使用独立的Tailer资源来支撑数据写入。

此外除了实时写入,两者都支持bulk load的批量导入行为。ADB支持利用第三方资源如spark等进行更大规模的弹性数据批量导入。

高质量模型的训练依赖高质量的数据输入,而大体量训练数据集的清洗、转换、加载工作往往需要反复试错、不断调整清洗策略,非常耗时。高吞吐的实时写入、批量导入则是提升效率的利器。ADB-M基于mark-for-delete的实时写入技术,使得PB级数据上进行任意更新/删除都能在ms内完成;弹性数据导入能力,使得在需要导入海量数据时,可以很容易的无限水平拓展资源以确保导入效率。

2.5 完备DML和OnlineDDL

ADB-M在分片分区的设计下,在超大规模数据集基础上仍然实现了数据库完备的行级DML语义。此外,对于目前所支持的丰富DDL(加减列、加减索引、修改列类型、修改分区格式和修改存储策略等等)都是完全Online的,用户可以灵活的按需使用,而不用做额外维护甚至担心锁表对线上业务产生影响等。

而Rockset则提供了Document数据模型,不需要事先指定每个字段的类型,后期根据写入数据自动进行列的新增和类型推断,甚至支持同一列写入不同类型的数据。

相比之下,ADB-M是强类型系统但支持灵活的后期变更。前期的数据建模设计会有一定学习成本,但是对于后期的数据治理、数据质量、查询性能则提供很大帮助;而Rockset则是弱类型系统,在前期上手很快,但后期的数据治理、数据管理上则有较大难度。

对于AI时代需要管理的海量数据集而言,往往在很长的生命周期内都需要反复进行数据治理以保证数据质量,ADB-M的强类型系统能够极大简化管理负担。

2.6 分层存储及数据生命周期自动管理

两者都支持冷热分层存储,并且都支持数据的TTL生命周期管理。不同之处在于:

  • Rockset将所有数据存储到对象存储上,再额外将热数据缓存到SSD。而ADB-M允许只将冷数据存储到对象存储,热数据直接放在SSD上,从而降低了存储成本。ADB-M支持指定混合存储策略,指定最近的若干个分区作为热分区,历史分区作为冷分区。热分区存储在[E]SSD上进行在线分析,冷分区自动归档到DFS上降低成本,归档动作在后台自动进行,无需用户干预。对于低频的冷数据访问,还提供缓存用于加速高频访问。冷热分区都是按实际使用量计费,无需为已分配未使用的磁盘空间承担成本。
  • Rockset只能根据_event_time字段进行数据淘汰,而ADB-M则支持灵活的指定任意字段做分区列,并进行分区级的淘汰。

在金融时序数据预测、人体健康监测、网络安全防护等AI场景中,数据天然具备冷热特征,冷数据必须存储但是极少访问。而且海量数据的存储成本往往是数据基础设施的成本大头,这种情况下低廉可靠的存储介质、用户透明的自动转储机制是必不可少的能力,且同时要确保不降低热数据查询性能。相比于Rockset只能基于时间进行生命周期管理,ADB-M提供的基于任意列进行数据淘汰、转储能力,可以适应多样化的AI业务场景需要,更加灵活。

2.7 向量检索与融合分析

ADB-M及Rockset都提供向量检索能力,支持将vector与基本数据类型的数据进行融合检索。

不同之处在于ADB-M在向量索引、倒排索引之外,额外提供了专门针对文本的fulltext index,且提供了自定义分词器、自定义词典、关键字高亮等功能,让业务可以结合知识域进行灵活调整,提供了更高精度的检索能力。

如前所述,高质量Retrieval对于AI问答模型的准确性十分重要。ADB-M不仅能够提供与Rockset相当的向量、基本数据类型融合检索能力,而且能够针对如安防、技侦、医疗等特殊领域的文本进行自定义token分词、自定义dictionary配置,为领域AI模型提供更精确的文本检索结果作为模型输入。

3. ADB-M设计原理及深度解析

上文将ADB-M与Rockset的关键特性进行了对比,下文将详细阐述ADB-M的设计及实现原理。


3.1 数据模型

玄武引擎的数据抽象是分布式的表,表的数据基于分布键的值Hash到对应分片(子表),在分片内进一步基于日期(典型的)分区。与数据分布相关的概念包括数据库、物理库、表、Hash分布、分区

                                      image.png

  1. 物理库(分片)。在创建实例时会根据资源情况分配若干分片,每个分片对应一个物理库。整个实例相当于是所有物理库(分片)组成的分布式数据库,扩缩容以分片为单位在节点间进行热数据的迁移
  2. 数据库。即用户数据库,是逻辑意义上的,无实际物理分布意义
  3. 表。用户表也是逻辑意义的,真正的数据会分布到各个物理库当中,每个物理库下面都会有一张子表。如上Table2在物理库下面的分布(物理库1没有展开)
  4. Hash分布。表定义时通过Distributed by Hash(column_name,...)指定分布键,在数据写入时,根据分布键计算Hash并模实例的分片数,得到该条记录要写入的分片(物理库)
  5. 分区。一条记录落入到具体分片后,根据表定义时指定的分区方式算得这条记录应该落入具体的分区。分区是在分片的基础上,对数据做进一步拆分,一般根据日期按年、月、日进行分区组织。从定义看目前支持两种,根本上都是按值(PARTITION BY VALUE)分区,区别在于值的来源不一样
  1. Partition By Value(column_name),根据分区列column_name的值进行分区,如column_name的值类似20240101这种数据,逻辑上按天分区,这种方式要求数据入库前已经格式化为需要的分区值了
  2. Partition by Value(date_format(column_name,'format')),取分区列column_name的值date_format格式化后的值进行分区,如column_name为日期类型,可以格式化为年、月、日等

这里仅简单介绍宏观上的数据分布方式,通过Hash分布 + 值分区的方式,将数据打散在整个实例的各个节点,并按日期进行组织,能够满足超大规模数据量的业务需求。更多关于表结构的定义详见官方文档

3.2 存储架构

                                                  image.png

从逻辑视角看,玄武引擎从上到下可以大致分为同步层、引擎层和持久化层。

  1. 同步层。遵循日志先行的原则,同步层负责数据入库的临时持久化。实现上基于Raft协议,通过多副本来保障数据可靠性和一致性
  2. 引擎层。引擎层管理数据整个生命周期,将从Raft进来的日志数据分发到各个表引擎中,消费并适时持久化,对外提供查询服务。在节点级还维护了不同用途的各类内存缓存,加速高频访问的查询性能
  3. 持久化层。出于对性能和成本的权衡,有面向高性能的块存储设备,也有面向低成本吞吐型的对象存储选择,并针对对象存储访问提供自动的缓存加速

同步层

                                        image.png

同步层基于Raft协议。

  1. Multi-Raft。在表引擎Hash分片的模型下,一个分片对应一个Raft集群,整个实例由若干个Raft集群组成同步复制层
  2. Shard分布。实例的所有分片(又称Shard)均匀分配在所有的EIU中,以Shard为粒度进行横向的扩缩。如上,假设4个Shard,两组EIU,则每组EIU分配两个Shard
  3. Raft Leader。对于EIU分配到的某一个Shard来说,在每个副本上创建一个RaftServer组成Raft集群,并选举出Leader
  4. Leader写入。写入时先写Leader副本,然后由Leader同步日志给其他副本,数据写入可靠性由多数派写入成功来保证
  5. 查询一致性。查询时优先查询Leader副本,来保证查询的强一致性。因其他原因下发到Follower的查询,也可通过同步获取Leader最新位点并等待来保证一致性
  6. 负载均衡。Leader负责读写服务来保证实时可见和一致性,也因此需要在所有EIU中能够均匀打散Leader来保证负载均衡,如上EIU1中第一个副本Shard1为Leader,第二个副本Shard3为Leader
  7. 日志清理。日志写入后即消费到表引擎,表引擎定期进行Checkpoint数据持久化,持久化位点之前的日志数据可清理避免占用过多空间
  8. 重启恢复。重启基于引擎持久化状态和维持久化日志回放来达到恢复的目标,因此重启时从表引擎持久化位点回放日志

引擎层

                                                          image.png

表引擎整体基于"追加写" + "后台合并修改"的设计来减少写入过程的随机IO开销,提升写入性能。支持完备的DML和OnlineDDL,在超大规模数据集下仍然能获得数据库的数据管理体验。

  1. 主键。通过主键(索引)来实现重复记录的快速定位,再基于DML语义进行数据的实时增删改
  2. DeleteSet。在面向追加写操作设计下,历史数据是只读的,对只读数据的更新,会映射为标记删除只读数据并追加写入新记录。因此对只读数据的修改仅仅意味着删除,删除这一修改通过DeleteSet来记录,并在查询时过滤掉被删除的历史数据行
  3. DML。DML先检查主键来确认记录是否存在,并根据DML语义决定不同的行为。如当主键存在(存在旧记录)时,Insert Into会跳过新纪录写入,Replace Into会标记删除旧记录然后写入、Delete会标记删除旧记录、Update会标记删除旧记录并填充写入新纪录、InsertDuplicate会在旧记录存在时执行更新的语义操作。依赖主键和DeleteSet的设计,目前支持了完备的实时行级DML
  4. 内存数据。追加的数据首先在内存缓存,在达到阈值后持久化到磁盘中,持久化时收集基础的轻量级统计信息
  5. 磁盘Layout。玄武引擎主要面向分析场景,如内存数据所示,以列存为数据分布方式,能充分利用列存的高压缩率且只读取查询列的数据。存储上可选纯列存和类PAX的RowGroup组织方式,适用不同场景
  6. Meta。在批量落盘时做一些简单的统计信息收集,如min/max/cnt/nullCnt,能在没有索引时进行简单的粗糙过滤,对齐典型数仓的粗糙过滤能力,降低扫描数据量
  7. RealtimeEngine。实时引擎是追加的可修改引擎,起到一个实时Buffer的作用,为了提升写性能默认没有索引,查询通过收集的Meta来进行粗糙过滤。相对应的有些系统设计为单次写入落盘一个/多个独立的小文件,在大量小批写时会导致小文件多合并不及时的问题。实时引擎超过一定阈值时,后台自动调度与全量(PartitionEngines)进行合并,追加新增并移除之前被标记删除的记录
  8. PartitionEngine。分区引擎按照定义的分区格式进行数据拆分,相较于实时引擎多了额外的索引部分。通过后台异步合并构建索引,能提升查询性能
  9. 索引。玄武引擎目前支持全类型的索引实现,包括普通列类型索引、向量索引、全文索引和JSON索引
  10. OnlineDDL。玄武引擎所有支持的DDL都是Online的,不会对在线业务产生影响

持久化层

出于对性能和成本的权衡,持久化层有高性能低延迟的[E]SSD云盘,主要面向热数据,也有高吞吐低成本的DFS选择,主要面向冷数据。且用户数据都是按使用量收费,无需干预磁盘的扩缩

  1. 云盘(热)。[E]SSD云盘有高性能低延迟的特点,适合于对延迟比较敏感的热数据场景,典型的如在线分析。为了满足高性能的写入需求,玄武引擎实时写入部分也是基于云盘,之后在Compaction时根据分区冷热定义异步的进行归档
  2. DFS(冷)。DFS面向成本敏感场景,适合离线吞吐型场景,对应我们常说的冷存
  3. 自动归档。玄武引擎支持指定存储策略为混合模式,同时设定保留的热分区个数,在后台Compaction时自动将历史分区归档到冷存中降低成本
  4. 缓存(温)。对冷存中数据的偶尔访问,直读DFS查询性能会受限访问延迟和总带宽吞吐。玄武引擎支持基于访问热度自动将访问的冷存数据缓存在本地,能够在性能和成本之间取得折中

3.3 查询流程

查询时每个Shard选择Leader来保证强一致性,对Shard内部的表引擎查询,由实时引擎的虚拟行号和DeleteSet组成轻量级快照,对快照之前所有的数据和删除可见,并忽略之后并发新增的数据和删除,实现了行级MVCC的语义保证。

玄武引擎在查询中负责ScanFilterAndProject,作为数据的Source端,其输入为带索引的谓词条件和投影列,输出为满足谓词条件的精确投影列数据,基于列存和索引将Project和Filter下推到存储,尽可能减少参与计算的数据量大小,除了常见列下推外,还支持半结构化数据函数等更丰富的下推,极致的近存储下推提供了超高性能的查询体验

                                                  image.png


如上为一个查询示例,ScanFilterAndProject可表示为示例中的SQL。在这个SQL中,对于玄武引擎需要去匹配满足在"HangZhou"、"ShangHai"且年龄在[15,30]范围结果,或者是面部特性与目标特性距离在常量值以内或同时包含某些标签的结果,最终取出满足这些条件的id和name。玄武引擎充分利用索引进行如上查询的加速,做到了极致的延迟物化,尽可能减少IO读取。


首先基于列级索引,分别获取满足每个条件的行号集合,然后根据查询的组合条件,进行行号集合的交并差获得最终的有效行集RowIdSet。玄武引擎支持非常丰富的索引类型,包括


倒排索引: 索引的key为列的值,索引的value为虚拟行号,对于常见的Filter都比较高效,基于有序数据的压缩也能降低索引的空间占用。如上的idx_city条件

BKD索引: 树形结构对范围查询相较倒排更有优势,也因此典型的用在数值和空间类型上。如上的idx_age

Bitmap索引: 常见Card值较少的,如性别、Null分布等

向量索引: 用于人脸识别等向量分析,支持HNSW_PQ搜索算法和SquaredL2距离计算公式。如上的idx_feature,也因此支持向量函数的下推

全文索引: 用于全文检索,支持IK/AliNLP/Ngram/Standard等典型分词器,且支持自定义词典。搜索上支持典型的match against/phrase/fuzzy全文检索函数

JSON索引: 用于对JSON数据类型进行检索。会对嵌套的JsonPath平坦化,并根据其值类型自动选择具体索引实现,可选自动对所有嵌套JsonPath或指定JsonPath以降低索引开销。此外,对于JSON Array,还额外支持通配符[*]索引,即对数组元数统一索引,用于在数组中高效搜索符合某些值的场景。如上的idx_tags,也因此支持JSON函数的索引下推

在获取到符合条件的RowIdSet之后,根据虚拟行号直接读取所需投影列(id,name)的数据,由虚拟行号寻址读取数据,只需要最少的IO消耗

4. 总结

本文将ADB-M与Rockset进行了对比分析,并且详细阐述了ADB-M的设计与实现。作为在阿里巴巴集团、阿里云上进行了多年自研且经过海量业务验证的云原生数据仓库,ADB-M使用存算分离架构,具备强一致性、高吞吐实时写入、全类型全索引、灵活schema、冷热数据分层存储、兼顾高并发查询和大吞吐批处理的混合负载能力等关键特性,在AI时代提供极致性能、极高性价比的实时数仓解决方案。


前往了解AnalyticDB MySQL更多内容


作者:AnalyticDB MySQL存储内核研发团队-涂继业(和君)

作者介绍
目录

相关产品

  • 云原生数据仓库AnalyticDB MySQL版