云原生实时湖仓系统的一数多擎实践之路-OushuDB
导读 OushuDB 是一款云原生数据库,目标是打造一个云原生实时、一数多擎的实时湖仓系统。本文将分享云原生实时湖仓的发展历程,以及 OushuDB 的实践之路。
主要内容包括:
-
云原生实时湖仓发展历程
-
OushuDB 体系架构
-
开发应用实践之路
分享嘉宾|陶征霖 北京偶数科技有限公司 首席架构师
编辑整理|余凡
内容校对|李瑶
出品社区|DataFun
01云原生实时湖仓发展历程
1.发展里程碑
① 数据库阶段
首先是数据库阶段,这一阶段主要以 OLTP(在线事务处理)为主,Oracle 和 DB2 等交易型系统是这一阶段的重要产物。这些系统采用了集中式架构来存储数据,此时数据的体量还相对较小,每个用户都可以拥有自己独立的业务系统,并且这些数据可以集中存储在一个数据库中。在这个阶段,整体数据的存取需求量不大,因此数据库用户使用起来也没有什么问题。
② 分布式数据库阶段
在1990年,Bill Inmon 先生在其所著的《建立数据仓库》一书中提出了"数据仓库"这一概念。
到了2000年左右,出现了数据爆炸的情况。随着数据体量的逐渐增加,客户开始意识到将所有数据整合在一起进行批量运算的重要性。在许多交易型系统中,数据通常被分散在各处,无法直接进行整合和统一处理。因此分布式数据库开始出现,分布式数据库通过将数据分散到多个节点上,实现了数据的分布式存储和处理,提高了数据处理的效率和可靠性。同时,OLAP(联机分析处理)引擎也开始出现,它主要用于分析型数据的处理。在 OLAP 引擎中,数据被存储在一个多维数据模型中,可以进行多维分析和查询。
一些具有代表性的 MPP(大规模并行处理)数据库产品,如 GreenPlum,采用了share-nothing 架构。在这种架构中,每个节点都拥有自己的一份独立数据,并在本地进行计算和处理,节点之间相互独立,互不共享任何数据或元数据。这种架构可以实现高效的分布式数据处理,但需要足够的存储和计算资源来支持大规模数据的处理和分析。MPP 数据库产品通过在数据层面进行隔离,实现了数据的分布式存储和处理。在 MPP 架构中,数据可能需要经过一些重分布和合并操作,以实现数据的重新组织和处理。这些操作可以统一由 MPP 数据库产品自带的计算引擎来完成,也可以通过其他工具或程序来实现。通用型 X86 机器可以作为 MPP 数据库产品的硬件平台,支持分布式数据处理和分析。
③ 大数据平台阶段
随着时间的推移,到了大约2010年左右的大数据平台阶段。Hadoop 已经发展了一段时间,并成为了一个能够承接各种数据类型的数据湖底座。无论是结构化数据、半结构化数据还是非结构化数据,都可以导入到 Hadoop 平台上。Hadoop 最核心的底座是HDFS,它主要负责数据的存储。在 HDFS 上面,会有许多不同的计算引擎,例如最早出现的 MapReduce 和 HBase 等等,这些都是受到了 Google 三驾马车的启发。
然而,随着应用场景的不断扩大和技术的发展,MapReduce 的一些不足之处逐渐显现出来,例如内存管理和性能等问题。为了解决这些问题,一些新的计算框架开始出现,例如 Apache Spark,它提供了更高效的分布式计算和数据处理能力。Spark 可以与Hadoop 的 HDFS 和 YARN 等组件进行集成,并成为了大数据领域中一个重要的计算框架。
随着业务的发展和需求的增加,人们对于实时分析的需求也逐渐增多。因此,出现了许多流计算引擎,例如Spark Streaming和Apache Flink等。这些引擎可以处理实时数据流并进行实时分析和应用。然而,Hadoop家族的产品确实比较杂乱,单一组件使用起来局限性较大,使用和部署起来比较复杂,运维成本也较高。
④ 湖仓分体阶段
分布式数据库 MPP 在性能方面表现不错,但在扩展性和高并发场景下的能力不足。对于 Hadoop 而言,存在性能较差,以及内存管理和家族成员过多等复杂问题。为了更好地满足数据全域整合和共享访问的需求,同时提供更高效的计算和存储能力,客户已经有建立湖仓一体的诉求。
湖仓一体架构出现的一个原因是因为大多数公司并未从 Hadoop 平台中获得期待已久的商业智能洞察力:尽管 Hadoop 能够以低成本的方式存储大量非结构化和半结构化数据,但由于其查询性能以及与其他企业级系统集成的限制性等问题,导致其无法成为企业级分析应用的主要数据源;此外由于其无法支持全实时数据处理场景也导致其无法成为企业级实时分析应用的主要数据源;再加上 Hadoop 家族成员众多、使用复杂、运维成本高昂等问题使其在企业中的落地应用变得异常困难。
因此客户希望能有一种方案来解决这些问题:既能实现湖仓一体化的数据整合和共享访问能力、又能在性能和扩展性上满足企业级应用需求、同时还能简化部署、降低运维成本------这就是云原生湖仓一体架构出现的背景原因之一。
在2015年左右的时候虽然技术发展还没有取得重大突破,但是大多数情况下人们采用了一种湖仓分体的架构来解决数据存储和处理的问题。在这种架构中 Hadoop 被用作存储数据的湖,而采用 MPP 引擎来构建仓。然而从湖到仓的数据转换过程中需要进行ETL(提取、转换和加载)操作,这会导致数据的天然割裂,很容易引入数据不一致的问题,带来了巨大的运维成本。
⑤ 云原生实时湖仓一体架构的发展
2020年左右一个很重要的转折点,就是云原生湖仓一体架构开始大发展的时期。
云原生湖仓一体架构是将云原生技术和湖仓一体架构相结合的一种新型数据存储和处理架构。它具有以下特点:
- 云原生技术:云原生湖仓一体架构采用云原生技术,可以利用云计算资源,实现数据的高效处理和存储,同时也具有更好的可伸缩性和可靠性。
- 统一的数据存储和处理:云原生湖仓一体架构将数据湖和数据仓库的功能整合到一个平台上,可以支持实时数据和离线数据的处理,以及多种数据类型。
- 数据隐私和安全:云原生湖仓一体架构可以更好地保护数据隐私和安全,采用数据加密和安全认证等措施,保证数据的安全性和可靠性。
- 更好的业务支持:云原生湖仓一体架构可以更好地支持业务需求,支持实时分析和决策,提高业务效率和准确性。
02OushuDB 体系架构
1. 云原生+一数多擎总体架构
OushuDB具有以下一些特性:
① 全实时数据集成接入
② 统一元数据管理
③ 原生支持多种存储平台
存储平台不仅包括云厂商提供的对象存储,如 OSS 和 COS 等,还涉及 Hadoop Distributed File System(HDFS)等存储以及偶数自研的分布式表存储Magma。OushuDB 的湖仓一体架构下的存储具有多模态特性,可以应对不同场景的需求。例如,对象存储技术更适合存储冷数据,而 HDFS 则更适合存储温数据。OushuDB 自主研发的分布式表存储 Magma 可用于存储热数据或实时数据。
④ 多计算引擎共享一份数据,避免数据孤岛
⑤ 弹性资源管理按需使用
⑥ 高性能、全实时处理分析
2. 产品体系架构
接下来讲一下作为实时湖仓核心底座的数据库是怎样构建的。从图中可以看出,数据库采用了分层的体系架构,每一层设计的核心思想都是可以水平地无限扩展。
① 客户端层
可以通过 JDBC 和 ODBC 等标准方式来连接数据库。
② 主节点层
主节点负责接受客户端请求,查询编译优化,任务分发,结果汇总的逻辑实现。元数据和事务状态从主节点剥离出来,完全无状态化的设计让主节点多活高可用,也让水平扩展和动态加减主节点变得更容易。
③ 虚拟计算集群层
计算节点无状态化,通过将变更的元数据、事务状态和数据从计算节点中解耦出去,计算节点可以变得更容易扩展和容错,同时提高了整体性能和可用性。计算集群逻辑上可以拆分成多个虚拟子集群,每个子集群包含一组计算节点,并共享相同的数据和元数据。这种架构可以支持海量计算节点,并实现多租户资源隔离,例如 CPU 和内存的物理资源完全隔离。
④ 虚拟存储集群层
存储集群包括元数据存储和数据存储,多模态存储类型包含对象存储,HDFS 和分布式表存储 Magma,每一组存储节点可以通过虚拟存储子集群技术(VSC)接入 OushuDB,这种架构可以支持海量存储节点,并实现多租户IO资源隔离。
03开发应用实践之路
1.存算分离
① 计算和存储解耦,计算节点无状态化,共享分布式存储
存算分离是打造云原生数据库的一个基本点。存算分离是指将计算和存储资源进行分离,例如在云上,通过将数据存储在对象存储上,而将计算和数据处理能力放在更贴近业务需求的位置上。这样,可以更好地适应云端环境,提高数据处理和存储的效率,并降低成本。存算分离可以更好地支持弹性扩展和自动化运维等云原生特性,并且可以提高系统的可维护性和可扩展性。因此,存算分离是打造云原生数据库的一个重要技术手段。在云原生数据库的设计和应用过程中,更需要考虑多租户、弹性伸缩、分布式、自动化运维等多个方面来进一步提升数据库的性能和可靠性。
云原生数据库可以利用云平台的弹性架构,动态地调整资源,提高计算和存储的效率。例如,可以在需要时启动更多的计算节点,以加快数据处理的速度,而在不需要时则可以关闭这些节点,以节省成本。
另外,云原生数据库还可以更好地支持多租户,为不同用户或应用提供独立的资源和管理平面,从而提高系统的可用性和可靠性。这些优势的实现需要数据库体系架构层面的改造和优化,例如采用分布式架构、多副本机制、弹性伸缩机制等。同时,云原生数据库还需要考虑安全性、数据一致性、高可用性等方面的要求,因此需要进行更多的深度思考和实践。
实现存算分离需要考虑以下几个方面:首先,计算节点需要无状态化,这意味着计算节点的运行不依赖于任何特定的存储状态,这样可以更好地支持计算节点的动态扩展和缩减;其次,需要选择一个可靠的共享分布式存储系统,比如对象存储、HDFS或者其他的分布式表存储等。这种存储系统可以提供高可用性、持久性和共享访问等功能,以支持多个计算节点同时访问和操作数据。
② 计算资源的调度,更靠近数据所在的地方,优先考虑缓存数据
存算分离以后,由于计算和数据存储被分离,计算节点需要访问远端的分布式存储来获取数据,这会增加访问的时延和带宽消耗。因此,需要考虑计算资源的调度问题,以使计算更加靠近数据所在的位置。需要使用类似于 Serverless 的技术,按需申请计算资源,降低项目启动成本,为各个业务做数据创新提供灵活性和便利性。
还需要设计高效的数据缓存策略来提高缓存利用率和降低成本。缓存策略应该考虑缓存的大小、缓存的数据种类和访问频率等因素,以实现缓存的有效利用和性能优化。
可以考虑开发分布式的缓存服务器,这样每个计算节点都可以拥有自己的独立的缓存服务,在调度时可以优先考虑到缓存能力。
弹性调度和根据数据量大小及资源使用情况动态决定调度节点的逻辑,这是非常重要的。在云原生数据库中,需要考虑更多的维度来进行资源的调度,例如数据大小、计算复杂度、并发度等等。
③ 计算层与存储层映射关系的管理
存算分离需要考虑计算层和存储层之间的映射关系管理。在传统的数据库中,计算层和存储层是紧密耦合的,但是在存算分离的架构中,这种关系被解耦了。存储层的数据文件和计算节点不应该存在强绑定关系,而只是一层逻辑上的映射关系。这样在计算层和存储层加减节点的场景下依然有效。同时存储层加节点带来的数据搬迁需要尽可能通过一致性哈希降低后台数据搬迁量。
④ 节点异常的处理
当出现节点异常时,需要采取一些措施来保证数据的完整性和系统的可用性。在传统 MPP 架构中,节点异常处理相对比较复杂。而在存算分离架构中,因为实现了计算节点的无状态化,计算节点的故障相对容易处理。当然存储节点故障还是需要采取相应的一些措施。针对分布式存储系统,可以采用副本机制来提高系统的可靠性和可用性。例如,Hadoop 分布式文件系统(HDFS)采用三副本机制进行容错处理。对于对象存储而言,由于其特性不太需要考虑这种问题。对于其他分布式表存储,可以通过Raft等一致性协议来保证。
⑤ 读写一致性问题
此外,还包括一些读写一致性的问题需要处理,包括强事务的 ACID 属性。对于 HDFS 和对象存储,事务是通过元数据集群保证。对于其他分布式表存储可以通过两阶段事务提交来实现分布式事务。
2.多活主节点支持高并发
① 主节点无状态化
混合负载高并发下,除了计算节点可能成为瓶颈外,主节点同样也可能成为一个瓶颈。传统的 MPP 架构数据库通常采用单主节点主备模式,这种方式并不能很好地满足现代应用场景的需求。我们的架构中,多活主节点的设计意味着每个主节点都是可读可写的,不是一种读写分离的设计实现。这样不仅解决了 TCP 连接数和 CPU 的瓶颈问题,还可以有效避免单点故障,提高了系统的高可用性和可扩展性。
② 主节点可以在线增减,实现客户端连接的负载均衡
此外,主节点可以完全在线自由增减,外围有一套负载均衡(LB)服务,比如在云上可以提供负载均衡服务。如果在物理机或虚拟机上部署主节点,可以使用 nginx 作为负载均衡器进行客户端连接的负载均衡。
③ 主节点完全高可用
因为每个主节点都是独立的,没有相互依赖关系,所以当任意一个节点挂掉时,负载均衡器可以实现路由的高可用性,将请求路由到其他可用的主节点上,保证系统的可用性和稳定性。
3.元数据集群高可用
① 元数据集群采用 P2P 去中心化完全对等网络架构
对于元数据集群的构建 OushuDB 采用了分布式表存储 Magma 来承接,该架构为完全去中心化的 P2P 架构。在 OushuDB 的设计体系中,Magma 的架构能够高效地支持大规模数据的存储和高并发访问,并且更好地适应分布式环境下的数据存取需求。
② 通过一致性协议算法保证数据和服务的高可用
OushuDB 通过 Raft 协议保证数据和服务的高可用性。
③ 元数据采用多副本机制,均匀分布在各个节点上
在数据的存储方面,OushuDB 采用了多副本机制。通过 Raft 协议,OushuDB 确保每个分片的 leader 在各个节点上均匀分布,从而实现了热点的打散。对于读写操作,OushuDB 目前主要通过 leader 来提供读写服务。
④ 元数据读写的负载均衡
由于实现了 leader 在各个节点上的均匀分布,因此可以实现读写负载均衡。
4.多集群架构支持混合负载
① 多虚拟计算集群支持对用户访问的 CPU 和内存资源的物理隔离
接下来,我们来探讨一下 OushuDB 的计算侧设计思想。
OushuDB 的目标是通过多集群架构支持多集群混合负载高并发。为此,OushuDB 将超大规模计算节点从逻辑上拆分为多个虚拟计算子集群。对于每个虚拟计算子集群,可以包含多个子集群实例,相当于一组计算节点。OushuDB 通过这种方法实现了多租户资源物理隔离。
② 多虚拟计算集群将超大规模计算节点根据负载情况划分为多个虚拟计算子集群
在 OushuDB 中,用户与虚拟计算子集群的绑定关系是通过元数据层进行记录和管理。当用户通过负载均衡(如 LB)路由到任何一个主节点(master)时,主节点可以根据元数据中记录的信息,将其作业分配到对应的虚拟计算子集群中。
③ 每个多虚拟计算子集群可以有多个实例,每个实例包含一组计算节点
每个租户都可以独享自己的一套虚拟子集群,实现资源的物理隔离,确保其在生产实践中的独立性和安全性。在 OushuDB 中,每个虚拟计算子集群实例内部可以定义不同的资源队列,以支持不同用户的不同资源需求。
④ 支持虚拟计算子集群层面的节点动态扩容
同时,为了更好地适应负载变化和作业增长,OushuDB 还支持计算节点的动态扩缩容。通过动态扩缩容功能,可以根据需要扩展或缩小虚拟子集群的大小,以满足不同租户的资源需求,并提高整体系统的高可用性和可扩展性。这些功能都在 OushuDB 的设计思路中得到了充分考虑和实现。
5.多虚拟存储集群实现磁盘 IO 隔离和存储扩展
① 用户根据磁盘 IO 负载情况或磁盘空间情况,按需将表建在不同的虚拟存储子集群中
通过虚拟存储子集群的技术,可以将多个存储子集群挂载到数据库中,并利用数据库中的关联计算功能对不同存储中的数据进行计算和分析。这样不仅可以提高计算效率,还可以灵活地利用不同的存储资源,实现更加高效和灵活的数据处理。
通过这种方法,用户可以控制磁盘IO的负载,并控制磁盘的空间使用情况。例如,如果一个 HDFS 集群已经满了,可以通过扩展子集群并挂载进来来增加存储空间。
② 虚拟存储子集群和计算没有绑定关系,对用户完全透明
这种方法的核心思想是将表对象与存储之间的映射关系存储在元数据中,从而对用户完全透明。用户只需关注表,而不需要关心存储的具体实现。
③ 支持虚拟存储子集群维度的扩缩容
此外,这种方法还支持根据子集群维度进行扩展和缩容。
6. 原生支持Hudi表格式
① 原生支持 Hudi 表格式的增删改查
引入 Hudi 的表格式,其主要目的是实现 "一数多擎"的思想,即在多个数据引擎之间共享和转换数据,从而实现更高效的数据处理和分析。Hudi 表格式提供了一种通用的数据存储格式,可以支持多种数据引擎,包括 Spark、Flink 等。通过使用 Hudi 表格式,可以更好地管理和利用不同引擎的优势和特点,提高数据处理效率和质量。
② 和 Spark/Flink 实现数据共享
在湖仓一体的企业架构中,数据可能存储在 HDFS 上。此时,客户可能会有多个引擎共享一份数据的需要。例如,流式数据和实时数据可能通过Flink等流处理引擎进入,而批处理和一些算法计算可能使用Spark等批处理引擎。在传统做法中,MPP 数据库和 Spark、Flink 等引擎之间的文件共享需要进行数据导入和导出操作。而现在,OushuDB 天然支持 Hudi 表格式,可以与大数据引擎打通,实现一数多擎,共享一份数据。这种实现不是外表的实现,而是原生的内表实现。
③ 支持动态分区表技术
Hudi 表格式支持动态分区,相比传统的静态分区技术,动态分区可以节约元数据存储体量,运行时动态剪枝的技术让查询性能更加优化。
7.共享 Hive 元数据
① 通过可插拔元数据框架共享Hive元数据
前面提到了引入 Hudi 表格式,现在来谈谈如何与 Hive 共享元数据。很多客户都有存量 Hive 集群,里面的数据量可能很大。此时,无论是想要进行数据迁移,还是想在Hive集群上添加一套计算引擎,都需要有一个比较好的解决方案。
② 作为纯计算引擎,无需创建外表实现对 Hive 数据的访问或关联计算
传统的一些数据库可能通过 connector 方案来实现,但是这种方法使用起来性能很差。OushuDB 计算引擎可以通过共享 HMS(Hive Metastore)元数据,直接访问 Hive 在 Hdfs 上数据文件的方式加速访问性能,并且可以实现库内的关联计算。
③ 自动感知 Hive 表 schema 的变化
如果使用的是外表方案,通常需要删除表并重新建立以感知变化。OushuDB 采用了共享 Hive 元数据的思路。将数据库的元数据剥离,完全依赖于 Hive 的 HMS,通过这种方法,我们可以原生地感知 Hive 表的 Schema 变化。
④ 打通 Ranger 权限对接实现对Hive表列级权限控制
此外,我们还可以与权限进行对接打通。例如,如果 Hive 使用 Ranger 做权限控制,可以与Ranger进行对接,实现列级权限控制
⑤ 兼容 Hive 分区表
Hive 原生的分区表可以无缝对接到我们的数据库中。OushuDB 还可以针对 Hive 表进行 DB 侧的统计信息收集和分析操作,并且可以利用 OushuDB 的分布式特性和优化措施来提高查询性能和并发处理能力。
今天的分享就到这里,谢谢大家。