全球部署的分布式数据库 YugabyteDB,了解一下?

简介: Yugabyte DB 是一个全球部署的分布式数据库,和国内的 TiDB 和国外的 CockroachDB 类似,也是受到 Spanner 论文启发,所以在很多地方这几个数据库存在不少相似之处。

Yugabyte DB 是一个全球部署的分布式数据库,和国内的 TiDB 和国外的 CockroachDB 类似,也是受到 Spanner 论文启发,所以在很多地方这几个数据库存在不少相似之处。


与 Cockroach 类似,Yugabyte 也主打全球分布式的事务数据库——不仅能把节点部署到全球各地,还能完整支持 ACID 事务,这是他最大的卖点。除此以外还有一些独特的特性,比如支持文档数据库接口。如果我猜的没错,Yugabyte 早期被设计成一个文档数据库,后来才调整技术路线开始主打 SQL 接口。


本文信息主要来自于 Yugabyte 的官方文档:


https://docs.yugabyte.com/


以及其 GitHub 主页:


https://github.com/yugabyte/yugabyte-db


系统架构

逻辑上,Yugabyte 采用两层架构:查询层和存储层。不过这个架构仅仅是逻辑上的,部署结构中,这两层都位于 TServer 进程中。这一点和 TiDB 不同。


Yugabyte 的查询层支持同时 SQL 和 CQL 两种 API,其中 CQL 是兼容 Cassandra 的一种方言语法,对应于文档数据库的存储模型;而 SQL API 是直接基于 PostgresQL 魔改的,能比较好地兼容 PG 语法,据官方说这样可以更方便地跟随 PG 新特性,有没有官方说的这么美好我们就不得而知了。


Yugabyte 的存储层才是重头戏。其中 TServer 负责存储 tablet,每个 tablet 对应一个 Raft Group,分布在三个不同的节点上,以此保证高可用性。Master 负责元数据管理,除了 tablet 的位置信息,还包括表结构等信息。Master 本身也依靠 Raft 实现高可用。


image.png


基于 Tablet 的分布式存储

这一部分是 HBase/Spanner 精髓部分,Cockroach/TiDB 的做法几乎也是一模一样的。如下图所示,每张表被分成很多个 tablet,tablet 是数据分布的最小单元,通过在节点间搬运 tablet 以及 tablet 的分裂与合并,就可以实现几乎无上限的 scale out。每个 tablet 有多个副本,形成一个 Raft Group,通过 Raft 协议保证数据的高可用和持久性,Group Leader 负责处理所有的写入负载,其他 Follower 作为备份。


下图是一个例子:一张表被分成 16 个 tablet,tablet 的副本和 Raft Group leader 均匀分布在各个节点上,分别保证了数据的均衡和负载的均衡。


image.png


和其他产品一样,Master 节点会负责协调 tablet 的搬运、分裂等操作,保证集群的负载均衡。这些操作是直接基于 Raft Group 实现的。这里就不再展开了。


有趣的是,Yugabyte 采用哈希和范围结合的分区方式:可以只有哈希分区、也可以只有范围分区、也可以先按哈希再按范围分区。之所以这么设计,猜测也是因为 Cassandra 的影响。相比之下,TiDB 和 Cockroach 都只支持范围分区。


哈希分区的方式是将 key 哈希映射到 2 字节的空间中(即 0x0000 到 0xFFFF),这个空间又被划分成多个范围,比如下图的例子中被划分为 16 个范围,每个范围的 key 落在一个 tablet 中。理论上说最多可能有 64K 个 tablet,这对实际使用足够了。


image.png


哈希分区的好处是插入数据(尤其是从尾部 append 数据)时不会出现热点;坏处是对于小范围的范围扫描(例如 pk BETWEEN 1 AND 10)性能会比较吃亏。


基于 RocksDB 的本地存储

每个 TServer 节点上的本地存储称为 DocDB。和 TiDB/Cockroach 一样,Yugabyte 也用 RocksDB 来做本地存储。这一层需要将关系型 tuple 以及文档编码为 key-value 保存到 RocksDB 中,下图是对文档数据的编码方式,其中有不少是为了兼容 Cassandra 设计的,我们忽略这些,主要关注以下几个部分:


key 中包含

16-bit hash:依靠这个值才能做到哈希分区

主键数据(对应图中 hash/range columns)

column ID:因为每个 tuple 有多个列,每个列在这里需要用一个 key-value 来表示

hybrid timestamp:用于 MVCC 的时间戳

value 中包含

column 的值

image.png


如果撇开文档模型,key-value 的设计很像 Cockroach:每个 cell (一行中的一列数据)对应一个 key-value。而 TiDB 是每个 tuple 打包成一个 key-value。个人比较偏好 TiDB 的做法。


分布式事务:2PC & MVCC

和 TiDB/Cockroach 一样,Yugabyte 也采用了 MVCC 结合 2PC 的事务实现。


时间戳

时间戳是分布式事务的关键选型之一。Yugabyte 和 Cockroach 一样选择的是 Hybrid Logical Clock (HLC)。


HLC 将时间戳分成物理(高位)和逻辑(低位)两部分,物理部分对应 UNIX 时间戳,逻辑部分对应 Lamport 时钟。在同一毫秒以内,物理时钟不变,而逻辑时钟就和 Lamport 时钟一样处理——每当发生信息交换(RPC)就需要更新时间戳,从而确保操作与操作之间能够形成一个偏序关系;当下一个毫秒到来时,逻辑时钟部分归零。


不难看出,HLC 的正确性其实是由 Logical Clock 来保证的:它相比 Logical Clock 只是在每个毫秒引入了一个额外的增量,显然这不会破坏 Logical Clock 的正确性。但是,物理部分的存在将原本无意义的时间戳赋予了物理意义,提高了实用性。


个人认为,HLC 是除了 TrueTime 以外最好的时间戳实现了,唯一的缺点是不能提供真正意义上的外部一致性,仅仅能保证相关事务之间的“外部一致性”。另一种方案是引入中心授时节点(TSO),也就是 TiDB 使用的方案。TSO 方案要求所有事务必须从 TSO 获取时间戳,实现相对简单,但引入了更多的网络 RPC,而且 TSO 过于关键——短时间的不可用也是极为危险的。


HLC 的实现中有一些很 tricky 的地方,比如文档中提到的 Safe timestamp assignment for a read request。对于同一事务中的多次 read,问题还要更复杂,有兴趣的读者可以看 Cockroach 团队的这篇博客 Living Without Atomic Clocks:


https://www.cockroachlabs.com/blog/living-without-atomic-clocks/)


事务提交

毫不惊奇,Yugabyte 的分布式事务同样是基于 2PC 的。他的做法接近 Cockroach。事务提交过程中,他会在 DocDB 存储里面写入一些临时的记录(provisional records),包括以下三种类型:


Primary provisional records:还未提交完成的数据,多了一个事务ID,也扮演锁的角色

Transaction metadata:事务状态所在的 tablet ID。因为事务状态表很特殊,不是按照 hash key 分片的,所以需要在这里记录一下它的位置。

Reverse Index:所有本事务中的 primary provisional records,便于恢复使用


image.png

事务的状态信息保存在另一个 tablet 上,包括三种可能的状态:Pending、Committed 或 Aborted。事务从 Pending 状态开始,终结于 Committed 或 Aborted。


事务状态就是 Commit Point 的那个“开关”,当事务状态切换到 Commited 的一瞬间,就意味着事务的成功提交。这是保证整个事务原子性的关键。


完整的提交流程如下图所示:


image.png


另外,Yugabyte 文档中提到它除了 Snapshot Isolation 还支持 Serializable 隔离级别,但是似乎没有看到他是如何规避 Write Skew 问题的。从 Release Notes 看来这应该是 2.0 GA 中新增加的功能,等更多信息放出后再研究吧!


竞品对比

以下表格摘自 Compare YugabyteDB to other databases:


https://docs.yugabyte.com/latest/comparisons/


image.png


References

https://www.yugabyte.com/

https://docs.yugabyte.com/

https://www.cockroachlabs.com/blog/living-without-atomic-clocks/


相关文章
|
3天前
|
存储 分布式计算 Hadoop
【大数据】分布式数据库HBase下载安装教程
【大数据】分布式数据库HBase下载安装教程
14 0
|
3天前
|
存储 缓存 大数据
【大数据】分布式数据库HBase
【大数据】分布式数据库HBase
25 0
|
5天前
|
运维 JavaScript Serverless
Serverless 应用引擎产品使用合集之php工程已经部署,可以正常访问数据库,静态资源样式无法正常加载,要怎么配置
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
Serverless 应用引擎产品使用合集之php工程已经部署,可以正常访问数据库,静态资源样式无法正常加载,要怎么配置
|
6天前
|
供应链 物联网 分布式数据库
区块链技术作为一种新兴的分布式数据库技术,正逐渐改变着我们的生产和生活方式。而智能合约作为区块链技术的重要应用之一
【6月更文挑战第10天】本文探讨了区块链技术与智能合约的界限及其带来的挑战。区块链,以其不可篡改性和安全性,已广泛应用于金融、供应链和物联网等领域。智能合约作为区块链的关键应用,实现了自动、安全和不可篡改的合约执行。然而,技术上的扩展性、性能问题和安全漏洞,以及法律监管的困境,构成了当前的主要挑战。尽管如此,随着技术进步和应用场景的拓宽,区块链与智能合约有望在未来发挥更大潜力。
46 0
|
8天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的数据库课程在线教学附带文章和源代码部署视频讲解等
基于ssm+vue.js+uniapp小程序的数据库课程在线教学附带文章和源代码部署视频讲解等
19 4
|
10天前
|
存储 安全 关系型数据库
分布式数据库的性能和安全麻烦
【6月更文挑战第6天】该文探讨了分布式系统中节点交互的两种方式,并对比mysql和oracle两个数据库的CAP平衡模式。
36 0
分布式数据库的性能和安全麻烦
|
11天前
|
监控 NoSQL 数据建模
使用Apache Cassandra进行分布式数据库管理的技术实践
【6月更文挑战第5天】本文探讨了使用Apache Cassandra进行分布式数据库管理的技术实践。Cassandra是一款高性能、可扩展的NoSQL数据库,适合大规模、高并发场景。文章介绍了其高可扩展性、高性能、高可用性和灵活数据模型等核心特性,并详细阐述了环境准备、安装配置、数据建模与查询以及性能优化与监控的步骤。通过本文,读者可掌握Cassandra的运用,适应不断增长的数据需求。
|
12天前
|
存储 缓存 NoSQL
浅谈分布式数据库系统
【6月更文挑战第4天】该文探讨了数据库管理系统的解决方案,建议使用Redis和MQ作为缓存和中转,减轻数据库压力。分布式系统需透明处理数据位置,解决查询执行和正确性问题。了解这些底层设计有助于应对性能挑战。
34 8
浅谈分布式数据库系统
|
17天前
|
Java 大数据 流计算
使用Docker快速部署Flink分布式集群
使用Docker快速部署Flink分布式集群
139 0
|
23天前
|
关系型数据库 MySQL 数据库
测试部署PolarDB-X 分布式与集中式
在本文中,作者详述了在CentOS 7.9上部署测试PolarDB-X分布式与集中式数据库的过程。PolarDB-X作为阿里云优化的分布式数据库,提供高稳定性和与MySQL的兼容性,是应对单体数据库扩展性和性能瓶颈的解决方案,同时也符合国产化需求。文章介绍了部署环境准备,包括关闭防火墙和SELinux,设置系统参数,安装Python3和Docker,以及配置MySQL客户端。接着,通过PXD工具部署了PolarDB-X的集中式和分布式版,遇到的问题包括阿里云镜像源异常导致的部署失败以及指定版本安装的困扰。最后,作者进行了初步的压力测试,并对文档完善、生态工具建设以及提供更多使用案例提出了建议。
47712 9
测试部署PolarDB-X 分布式与集中式