写点什么

如何将 Schemaless 演化成分布式 SQL 数据库

  • 2021-04-22
  • 本文字数:3479 字

    阅读完需:约 11 分钟

如何将 Schemaless 演化成分布式 SQL 数据库

2016 年,我们发表了关于 Schemaless—Uber Engineering 的可扩展数据存储的博文()。在这两篇博文中,我们介绍了 Schemaless 的设计,并解释了开发它的原因。今天这篇文章我们将要讲的是 Schemaless 向通用事务性数据库 Docstore 的演化历程。


Docstore 是一个通用的多模型数据库,它在分区级别上提供了严格的序列化一致性模型,并且可以横向扩展以满足高容量工作负载。诸如 Transaction(事务)、Materialized View(物化视图)、Associations(关联)和 Change Data Capture(变更数据捕获)等功能,结合建模的灵活性和丰富的查询支持,显著提高了开发人员的工作效率,并缩短了 Uber 新应用的交付时间。


Docstore 目前已经投入生产,并服务于业务关键用例。

动机

Schemaless最初被设计为一个仅有附加的数据存储。最小的实体被称为单元格,它是不可变的。去除可变性降低了系统的复杂性,并使其不易出错。然而,随着时间的推移,我们意识到,由于限制性的 API 和建模能力,使得用户很难将其作为一个通用的数据库来使用。


Schemaless 的缺点导致了 Cassandra 的推出,它确实提供了很多灵活性和易用性。但是,Cassandra 还有其他缺点。Uber 的数据足迹很大,因此可扩展性和效率必须齐头并进。在 Uber 的规模下,我们发现,Cassandra 在操作方面不够成熟,同时它也不能提供理想的效率水平。而 Cassandra 提供的一致性,最终也阻碍了开发人员的工作效率,因为他们必须围绕着缺乏强一致性的问题进行设计,这就使得应用架构变得更加复杂。


有了开发和运行 Schemaless 和 Cassandra 的第一手经验,我们得出的结论认为,将 Schemaless 演化为一个通用的事务性数据库是最佳选择。Schemaless 历来是一个高度可靠的系统,但现在我们需要关注可用性,同时实现相似或更好的可靠性。

设计上的考虑

我们并不想构建 NoSQL 系统,相反,我们想实现两全其美:文档模型的模式灵活性和传统关系模型中的模式约束。


为了在数据上约束模式,我们在 Docstore 中设计了表。使用数据的应用程序通常采用某种结构。这意味着,它们要么利用读时模式(schema-on-read),即应用程序在读取数据时对数据进行解释;要么利用写时模式 (schema-on-write) ,确保模式是显式的,而数据库则确保数据模式的一致性。缺省情况下,我们支持后一种方法“写时模式”。


Docstore 除了上面的模式约束之外,还提供了模式灵活性,而且模式是可以演化的。Docstore 允许共存不同模式的记录,并且模式更新无需重建全表。稀疏性和对复杂嵌套数据类型的支持是 Docstore 的一流特性。

功能集

Docstore 内置了以下功能。它整合了 Uber 软件生态系统,只需点击一下按钮即可进行配置。



图 1:Docstore 功能

架构

Docstore 的架构是层次化的,Docstore 的部署称为实例。每个实例分为查询引擎层、存储引擎层和控制平面。



图 2:Docstrore 层次架构


查询层是无状态的,它负责将请求路由到存储层。


负责存储数据的存储引擎被组织成一组分区,数据分布在这些分区上。控制平面负责为 Docstore 分区分配分片,并根据故障事件自适应地调整分片的位置。


Docstore 具有表的概念。表看上去类似于关系型数据库表,其结构由行、列和值组成。对于 Docstore 中表的建模方式没有任何限制,Docstore 可以使用用户定义的类型将嵌套的记录存储为行。举例来说,如果数据具有与文档相似的结构,并且整个层次结构只加载一次,那么这就很有用。Docstore 还支持“关联”,允许表示一对多和多对多的关系。我们称之为“灵活的文档模型”,因为它支持对关系型和层次型的数据模型进行建模。在本系列博文的第二部分中,我们将介绍 Docstore 的数据建模。


每个表可以有一个或多个物化视图。物化视图是一种视图,它通过使用不同的列,允许以不同于主表的方式对数据进行分区。增加由非主键列进行分区的物化视图,可以有效地通过该列来查询数据,并允许不同的查询访问模式。


每个表都必须有一个主键,而主键可以由一个或多个列组成。主键标识了表中的行,并强制执行唯一约束。从内部看,主键和分区键列都存储为字节数组,并通过对键列值进行保序编码来获取值。Docstore 按照主键值的排序顺序存储行。这种方法与复合分区键相结合,可以实现复杂的查询模式,包括使用给定的分区键抓取所有行,或者使用主键的剩余部分来缩小特定查询的相关行。



图 3:Docstore 表布局


当然,对于我们来说,下一步就是在设计过程中实现分片逻辑。表被分片并分布在多个分片上:对应用程序来说是透明的。每个分片代表表中几百 GB 的一组行,它被完整地分配到一个分区。一个分区可以包含一个或多个分片。


主要设计考虑是让应用程序通过选择键来控制数据局部性(data locality)。这就是我们在主键之外引入分区键的原因。应用程序可以选择在模式中明确定义分区键,否则,Docstore 就会使用主键来对数据进行分片。


通常情况下,每个 Docstore 实例中都有多个分区。为解决单点故障问题,分区是由 3~5 个节点组成的一组,每个节点是一个物理隔离单元,部署在一个独立的区域中。每个分区都会被复制到多个地理位置,以提供数据中心故障的恢复能力。



图 4:Docstore 数据分区

复制状态机

为了保证一致性,每个分区都会运行 Raft 共识协议。有一个领导者和多个跟随者。



图 5:Docstore 复制状态机


所有的写入均由领导者发起。执行共识协议以保持分区中各节点复制日志的一致性。这样就确保了分区中的所有节点都以相同的顺序包含相同的写入,从而保证了可序列化。只有在达成共识的情况下,在每个节点上运行的状态机才会继续提交写入。这样就提供了一个非常好的属性,即如果对一个键的写入提交成功,则通过同一键所有后续的读取将返回该特定操作或随后某个写入操作的相同数据。

一致性模型

Docstore 在分区级别上提供了严格的可序列化一致性模型。这样用户就可以很好地了解到事务是按顺序执行的。事务的顺序是这样的:一个事务“A”在事务“B”之前启动和提交,并且始终发生在事务“B”之前。这样可以确保读操作总是从最近的写操作返回结果。用 CAP 定理的术语来说,Docstore 更倾向于一致性而不是可用性,因此它是一个 CP 系统。

事务

Docstore 使用 MySQL 作为底层数据库引擎。在复制状态机中,复制单位是一个 MySQL 事务。所有的操作都在 MySQL 事务的上下文中执行,以保证 ACID 语义。这些事务随后使用 Raft 共识协议在节点间进行复制。



图 6:事务中的操作序列


我们依靠 MySQL 进行并发控制。要知道,MySQL 依靠行锁来实现写操作(插入、更新、删除)的并发控制,这一点很重要。这样,MySQL 就有效地序列化了对同一行的并发更新,并且当控制流到达客户端发出提交时,所有的锁都已经处理完毕。


通过图 7 的流程图,我们可以看出事务是在时间上交错的。在时间轴上,用不同位置的方框表示交错,也就是不同方框对应着不同时间的“事件”。



图 7:交错插入


基于 Raft 复制状态机的实现,MySQL 的事务可以以高可用的方式公开给客户端,即所有的复制体相互协调应用事务,这样,复制体之间就可以实现自动故障转移,同时即使发生故障转移,事务的 ACID 属性也会保持不变。需要注意的是,由于我们依赖于将 MySQL 的事务公开给客户端,因此集成了 MySQL 事务的所有优点和约束。



图 8:Docstore 事务流

总结

在这篇文章中,我们已经阐述了 Docstore 的起源及其背后的动机。此外,我们还深入分析了该架构,并解释了如何在 Docstore 中处理事务。在本系列博文的下一个部分,我们将重点讨论数据建模和模式管理。我们将介绍 Docstore 如何支持分层和关系模型,以及哪些类型的应用应该选择这些数据模型。我们将深入研究 Docstore 中的物化视图,这是本系列博文的第三部分,也是最后一部分。其中包括动机、物化视图刷新框架以及我们计划如何利用物化视图,尽管在查询中没有明确提及。


作者介绍:


Ovais Tariq,Uber 核心存储团队的高级经理,领导运营存储平台组,专注于提供一个世界级的平台,为 Uber 所有关键业务功能和业务线提供动力。该平台为数千万 QPS 提供服务,可用性达到 99.99% 以上,并存储了数十个 PB 的运营数据。


Deba Chatterjee,Uber 基础设施团队担任高级产品经理。在加入 Uber 之前,Deba 曾在数据库创业公司和甲骨文公司担任各种产品管理职务。在进入产品管理之前,Deba 负责管理大型数据仓库的性能。Deba 拥有宾夕法尼亚大学的技术管理硕士学位。


Himank Chaudhary,Uber Docstore 的技术负责人。主要关注领域是构建分布式数据库,随着 Uber 的超速发展而扩展。在加入 Uber 之前,他曾在雅虎的邮件后端团队建立元数据存储。Himank 拥有纽约州立大学计算机科学硕士学位,专业为分布式系统。


原文链接:


https://eng.uber.com/schemaless-sql-database/

2021-04-22 10:545896
用户头像
刘燕 InfoQ高级技术编辑

发布了 1112 篇内容, 共 581.4 次阅读, 收获喜欢 1981 次。

关注

评论

发布
暂无评论
发现更多内容

webgl开发框架及特点

北京木奇移动技术有限公司

数字孪生 软件外包公司 webgl开发

畅连啦!华为开发者空间云开发环境惊喜上线

华为云开发者联盟

暑期出境游还是鸿蒙5好用,轻松搞定流量、导航和翻译

最新动态

中小企业会议成本高?可以试试这款私有化视频会议软件

BeeWorks

即时通讯 IM 私有化部署

私有化部署且支持局域网使用的IM即时通讯软件

BeeWorks

即时通讯 IM 私有化部署

回收站的照片被删除了怎么找回?回收站被清空了还能恢复文件吗?

阿拉灯神丁

EasyRecovery 文件恢复 照片恢复 数据恢复软件 备份 & 恢复

[鸿蒙征文] HarmonyOS NEXT 语音播报 Demo:零门槛上手,小白也能秒启动

三掌柜

鸿蒙 HarmonyOS HarmonyOS NEXT 实践分享

CST直角反射器 --- A求解器, 距离分辨率,ICZT与逆傅里叶IFT

思茂信息

仿真软件 电磁仿真 CST Studio Suite

华为何刚:深耕基础软件开源 使能千行万业创新

最新动态

对话|Data Agent:企业首位AI数据专家如何颠覆传统分析?

火山引擎开发者社区

AI

AI大模型的调用性能优化

北京木奇移动技术有限公司

AI大模型 软件外包公司 AI英语学习

一文带你简单了解云安全管理平台-行云管家

行云管家

云计算 云服务 云管理

Web3 软件系统的开发框架

北京木奇移动技术有限公司

区块链开发 软件外包公司 web3开发

从概念到场景化落地,灯塔低代码平台重构企业数字化生态

中烟创新

AI大模型接口调用流程优化

北京木奇移动技术有限公司

AI大模型 AI教育 软件外包公司

Playwright自动化测试 | 第二阶段:核心技能与调试 ​​交互操作大全

测试人

轻松上手|用 TRAE + Context7 MCP Server 创建代码助手智能体

火山引擎开发者社区

Trae

Meta的AI之路,为何节节败退?

脑极体

AI

数字健康行业需要部署堡垒机的几种情形简单分析

行云管家

网络安全 数据安全 数字健康

QT客户端开发框架及特点

北京木奇移动技术有限公司

软件外包公司 QT开发 QT客户端开发

信用引擎驱动  新租赁带动消费新浪潮——中国新租赁行业洞察2025

易观分析

CPU 负载高,到底应不应该告警?

巴辉特

最佳实践 监控告警 运维监控

Perplexity CEO专访:AI浏览器大战、挑战谷歌以及广告模式的终结

AI数据云Relyt

openai ChatGPT LLM AIAgent AI浏览器

百度智能云国产万卡集群率先通过信通院测评,获“五星级”评级

科技热闻

AI助力烟草专卖人才管理升级:构建智能化人员画像与队伍考评系统

中烟创新

训练效率提升100%!阿里云后训练全栈解决方案发布实录

阿里云大数据AI技术

人工智能 云计算 大数据 强化学习 大模型

打造可落地的“指标 + AI”应用架构,支撑智能问数与分析能力

袋鼠云数栈

指标 指标管理 智能分析 智能数据分析 智能问数

数据分析与AI丨如何选择合适的知识图谱软件,CTO/CIO 必问10个关键点

Altair RapidMiner

人工智能 AI 数据分析 汽车 数字孪生

TRAE 新增自定义模型服务商、进程资源管理器,国际版支持银联支付!

火山引擎开发者社区

Trae

从谨慎检查到一键接受,TRAE 如何成为我的主力 IDE?

火山引擎开发者社区

Trae

他来了!她来了!CodeBuddy IDE 首发!首批限时内测开启,速来尝鲜!

六月的雨在InfoQ

CodeBuddyIDE AIIDE

如何将 Schemaless 演化成分布式 SQL 数据库_AI&大模型_Uber Engineering_InfoQ精选文章