这是我 Vitess 系列的第三篇文章。这篇文章将介绍 Vitess 的架构、主要组件,并介绍如何处理查询。如果你错过了本系列的前两篇文章,你可以在这里查看:
架构概览
Vitess 是分片 MySQL 数据库的集群管理解决方案。在本节中,我们将逐步展示 Vitess 架构的样子。首先让我们只考虑两个最关键的 Vitess 组件。
他[R Ë我们看到Vitess的两个最重要的组成部分:VTGate和VTTablet。
VTGate 是一组无状态节点,它们充当用户的前端。所有用户查询都路由到任意 VTGate 主机。该 VTGate 主机检查查询以确定查询中涉及哪些分片。VTGate 然后将查询转发到适用的分片。
每个分片由 N 个平板电脑组成,其中一个是领导者。一个平板电脑由两个在同一主机上运行的组件组成——一个 MySQL 实例和一个 VTablet 实例。VTTablet 是 Vitess 组件,负责监视本地 MySQL。VTablet 可以终止查询,确保 MySQL 实例健康,对查询实施限制并向 VTGate 报告健康状况。VTablet 和 MySQL 实例总是一起部署在单个主机上。
上面的架构图描述了 VTGate 和 VTablet,但它缺少元数据存储。需要元数据存储来帮助回答以下类型的问题:
- 密钥空间是如何分片的?
- 碎片有哪些平板电脑?
- 哪个节点是分片的领导者?
这些信息存储在拓扑服务(元数据存储)中。让我们将其添加到我们的图表中。
拓扑服务需要是存储少量元数据的强一致性存储。Vitess 设计者将此组件设计为插件。它在Zookeeper、etcd和Consul之上有实现。任何支持观察的强一致性元数据存储都可以用于实现拓扑服务。VTGate 拉取信息并将其写入拓扑服务。
需要理解的 Vitess 架构的一个非常关键的部分是拓扑服务永远不会在查询的热路径中使用。它在节点启动时访问,并随着元数据的变化定期更新。但它不是按查询访问的——每个查询所需的任何分片路由信息都由 VTGate 缓存。
到目前为止,我们的架构仅限于单个故障区域。Vitess 支持跨区域部署。Vitess 有一个叫做细胞的概念。单元是一组主机,被认为具有与其他单元不同的故障边界。例如,Vitess 的部署可能使用 AWS 区域作为 Vitess 单元。让我们展示一下扩展到跨区域部署后的架构。
这是一个非常疯狂的图表——让我们分解它。
拓扑服务有两种类型:本地和全局。全局拓扑服务不与任何单元关联,它存储不经常更改的数据。本地拓扑服务是小区特定的。本地拓扑服务拥有与全局拓扑服务相同的所有信息,但另外还拥有特定于其单元的信息。例如,本地拓扑服务负责保存当前单元中平板电脑的主机地址。当全局拓扑服务中的信息有更新被推送到所有小区本地拓扑服务时。让我们再做一些关于单元本地拓扑服务和全局拓扑服务之间的关系的注意事项
- 全局拓扑服务应该将节点部署在多个单独的故障区域中。因此,它可以容忍一个完整电池的中断。
- 单元内的组件仅访问本地拓扑服务,而不访问全局拓扑服务。如果本地拓扑服务出现故障,它只会影响该特定小区。
- 全局拓扑服务可以关闭一段时间而不影响本地小区。
现在让我们将注意力转移到跨单元部署中的分片是什么样子上。单个分片将跨越多个单元格。单元的全部意义在于它们是独立的故障域——如果单个分片的所有数据都存在于单个单元中,那么单元的目的就会落空。就像单单元部署一样,所有单元中的每个分片仍然只有一个领导者。因此,如果我们有一个部署,其中一个分片由 5 个节点支持并部署在三个单元格中,一个有效的配置是单元格 A 中有 1 个节点,单元格 B 中有 2 个节点,单元格 C 中有 2 个节点。这些节点之一将成为领导者。
作为此架构图的一部分,我们将介绍另外两个组件。它们是vtctlclient和vtctld服务器。这两个组件只是形成 HTTP 客户端和 HTTP 服务器的一对,后者支持对拓扑服务的读取和更新。让我们添加这些部分。
在这里我们看到客户使用 vtctlclient 调用 vtctld 服务器。这个客户端-服务器对是用户如何影响集群中的变化和读取集群中的状态。以下是用户将使用 vtctlclient 执行的操作的几个示例
- 触发重新父化,以便不同的节点成为分片的领导者。
- 读取有关分片中平板电脑的元数据。
- 查找哪个节点是分片的领导者。
- 触发重新分片工作流。
- 将节点标记为只读。
总之Vitess有以下组件
- VTablets:数据层
- VTGate:前端路由层
- vtctld 和 vtctlclient:与集群元数据交互的 HTTP 客户端/服务器
- 本地/全局拓扑服务:集群元数据存储
阅读的生活和写作的生活
当用户发出查询时,它将到达某个 VTGate 节点。VTGate 节点将检查查询并将检查它从拓扑服务器缓存的集群元数据。基于此检查,VTGate 将确定查询跨越多个分片还是单个分片。这里有几种情况:
查询是只读的并且适用于单个分片:在这种情况下,VTGate 可以将查询转发到分片中的任何服务副本。数据库完成所有工作,VTGate 只是将结果返回给用户。
Query is Read+Write and Apply to Single Shard:这种情况与前一种情况相同,只是查询必须转发给分片的领导者。在跨小区部署中,这可能涉及进行跨小区呼叫。
查询是只读的并适用于多个分片: VTGate 将只读查询转发到查询中涉及的所有分片中的副本(这可能是集群中的所有分片或子集——但我们会更多地讨论这一点在以后的帖子中)。VTGate 从各个分片获取结果,组合结果并将它们返回给用户。
Query is Read+Write and Apply to Multiple Shards:除了所有查询都需要转发到分片领导者之外,与之前相同。
如果用户能够对他们的数据访问进行建模以避免扇出查询,这是理想的。当查询扇出到多个分片时,用户会在两个方面受到影响:
- 延迟:查询的延迟将受所有涉及的分片中最慢的限制。
- 可用性:如果单个分片的可用性为 99.9%,那么命中 3 个分片的扇出查询的可用性为 99.9% * 99.9% * 99.9% = 99.7%。
除了支持扇出查询——Vitess 还支持跨分片交易。尽管它使用非常慢的 2PC 协议支持这一点。因此,强烈建议避免使用跨分片交易。
我希望你喜欢这篇文章,现在对 Vitess 架构有更好的理解。我认为我们可以从这个架构中学到一些东西
- 将全局元数据存储与区域特定的元数据存储分离是有好处的。
- 在查询热路径上应该尽可能少地涉及到组件。在 Vitess 的情况下,查询热路径上只有两个组件。
- 将拓扑服务构建为插件使 Vitess 更易于使用。每个公司都必须有一些类似 Zookeeper 的商店——但并不是每个公司都专门使用 Zookeeper。将其作为插件实现可以让更多的公司使用 Vitess。
- 软件开发 VX zhiyan0112