「读书笔记」《大规模分布式存储系统:原理解析与架构实战》:七

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介: 「读书笔记」《大规模分布式存储系统:原理解析与架构实战》:七

7 分布式数据库

关系型数据库设计之初没有预见到 IT 行业发展如此之快,总是假设系统运行在单机 这一封闭系统上。

7.1 数据库中间层

最常见做法:应用层按照规则将数据拆分为多个 分片 ,分布到多个数据库节点,并 引入一个中间层 来对应用屏蔽后端的数据库拆分细节。

7.1.1 架构

以 MySQL Sharding 为例:

  • 中间层 dbproxy 集群:解析客户端 SQL 请求并转发到后端的数据库。具体上:解析 MySQL 协议,执行 SQL 路由,SQL 过滤,读写分离,结果归并,排序以及分组等。由多个无状态的 dbproxy 进程组成,不存在单点的情况。另外,可以在客户端与中间层之间引入 LVS 对客户端请求进行负载均衡。需要注意的是,客户端请求需要额外增加一层通信开销,因此,常见的做法是直接在客户端配置中间层服务器列表,由客户端处理请求负载均衡以及中间层服务器故障等情况。
  • 数据库组:每个 dbgroup 由 N 台数据库机器组成,其中一台为 Master,另外的为 Slave。Master 负责所有的写事务及强一致读事务,并将操作以 binlog 的形式复制到备机,备机可以支持有一定延迟的读事务。
  • 元数据服务器:负责维护 dbgroup 拆分规则并用于 dbgroup 选主。dbproxy 通过元数据服务器获取拆分规则从而确定 SQL 语句的执行计划。另外,如果 dbgroup Master 出现故障,需要通过元数据服务器选主。元数据服务器本身也需要多个副本实现 HA,一般常见的方式是采用 Zookeeper 实现。
  • 常驻进程 agents:用于实现监控,单点切换,安装,卸载程序等。

MySQL 客户端库:应用程序通过 MySQL 原生的客户端与系统交互,支持 JDBC。

假设数据库按照用户哈希分区,同一个用户的数据分布在一个数据库组上。如果 SQL 请求只涉及同一个用户(这对于大多数应用都是成立的),那么,中间层将请求转发给相应的数据库组,等待返回结果并将结果返回给客户端;如果 SQL 请求涉及多个用户,那么中间层需要转发给多个数据库组,等待返回结果并将结果执行合并、分组、排序等操作后返回客户端。由于中间层的协议与 MySQL 兼容,客户端完全感受不到与访问单台 MySQL 机器之间的差别。

7.1.2 扩容

MySQL Sharding 集群一般按照用户 id 进行 哈希分区,存在两个问题:

  1. 集群容量不足:双倍扩容的方案,从 2 -> 4 -> 8 …
  2. 单个用户的数据量太大:在应用层定期统计大用户,并且将这些用户的数据按照数据量拆分到多个 dbgroup。当然,定期维护这些信息对应用层是一个很大的代价。

常见扩容方式:(假设 2 个 dbgroup,第一个 dbgroup Master 为 A0,备机为 A1,第二个 dbgroup Master 为 B0, 备机为 B1. 按照用户 id 哈希模 2,结果为 0 的用户分布在第一个 dbgroup,结果为 1 的用户分布在第二个 dbgroup)

  1. 等待 A0 和 B0 的数据同步到其备服务器,即 A1 和 B1
  2. 停止写服务,等待主备完全同步后解除 A0 与 A1、B0 与 B1 的主备关系
  3. 修改中间层的映射规则,将哈希值模 4 等于 2 的用户数据映射到 A1, 哈希值模 4 等于 3 的用户数据映射到 B1
  4. 开启写服务,用户 id 哈希值模 4 等于 0/1/2/3 的数据将分别写入到 A0/A1/B0/B1。这就相当于有一半的数据分别从 A0、B0 迁移到 A1、B1.
  5. 分别给 A0、A1、B0、B1 增加一台备机

最终,集群由 2 个 dbgroup 变为 4 个 dbgroup。可以看到,扩容过程需要停一小会儿服务,另外,扩容执行过程中如果再次发生服务器故障,将使扩容变得非常复杂,很难做到完全自动化。

7.1.3 讨论

引入数据库中间层将后端分库分表对应用透明化在大型互联网公司内部很常见。这种做法实现简单,对应用友好,但是也有一些问题:

  • 数据库复制:可能只支持异步复制,主库压力大可能产生很大的延迟,因此,主备切换可能会丢失一部分更新事务,这时需要人工介入
  • 扩容问题:扩容涉及数据重新划分,整个过程复杂易出错
  • 动态数据迁移问题:难自动化。

7.2 Microsoft SQL Azure

7.3 Google Spanner

Google 的 全球级分布式数据库(Globally-Distributed Database)。扩展性达到了全球级,可以扩展到数百个数据中心,数百万台服务器,上亿行记录。还能通过 同步复制和多版本控制 来满足外部一致性,支持跨中心事务。

7.3.1 数据模型

对于典型相册应用,存储用户和相册,建表语句如下:

CREATE TABLE Users {
  user_id int64 not null,
  email string
} PRIMARY KEY(user_id), DIRECTORY;
CREATE TABLE Albums {
  user_id int64,
  album_id int32,
  name string
} PRIMARY KEY(user_id, album_id),
    INTERLEAVE IN PARENT Users;
SQL

Spanner 表是层次化的,最底层的表是目录表(Directory table),其他表创建时,可以用 INTERLEAVE IN PARENT 来表示层次关系。

实际存储时,Spanner 会将同一个目录的数据存放到一起,只要目录不太大,同一个目录的每个副本都会分配到同一台机器。因此,针对同一个目录的读写事务大部分情况下都不会涉及跨机器操作。

7.3.2 架构

Spanner 构建在 Google 下一代分布式文件系统 Colossus 之上。Colossus 是 GFS 的延续,相比 GFS,Colossus 主要改进点在于 实时性,且支持海量小文件

Spanner 概念:

  1. Universe:一个 Spanner 部署实例称为一个 Universe。 目前全世界有 3 个,一个开发,一个测试,一个线上。Universe 支持多数据中心部署,且多个业务可以共享同一个 Universe
  2. Zones: 每个 zone 属于一个数据中心,而一个数据中心可能有多个 zones。一般来说, Zone 内部的网络通信代价较低,而 Zone 之间通信代价很高。(zone 概念类似于 region)

Spanner 包含如下组件:

  • Universe Master: 监控这个 Universe 里 Zone 级别状态信息。
  • Placement Driver:提供跨 Zone 数据迁移功能。
  • Location Proxy:提供获取数据的位置信息服务。客户端需要通过它才能知道数据由哪台 Spanserver 服务。
  • Spanserver:提供存储服务,功能上相当于 Bigtable 系统中的 Tablet Server

每个 Spanserver 会服务多个子表,而每个子表又包含多个目录。客户端往 Spanner 发送读写请求时,首先查找目录所在的 Spanserver,接着从 Spanserver 读写数据。

7.3.3 复制与一致性

每个数据中心运行一套 Colossus,每个机器有 100 - 1000 个子表,每个子表会在多个数据中心部署多个副本。为了同步系统的操作日志,每个子表上会运行一个 Paxos 状态机。Paxos 协议会选出一个副本作为主副本,主副本默认寿命为 10s。 正常情况下,这个主副本会在快要到期的时候将自己再次选择为主副本;如果主副本宕机,其他副本会在 10s 后通过 Paxos 协议选举为新的主副本。

通过 Paxos 协议,实现了跨数据中心的多个副本之间的一致性。另外,每个主副本所在的 Spanserver 还会实现一个锁表用于并发控制,读写事务操作某个子表上的目录时需要通过锁表避免多个事务之间互相干扰。

除了锁表,每个主副本还有一个事务管理器。如果事务在一个 Paxos 组里面,可以绕过事务管理器。但是一旦事务跨多个 Paxos 组,需要事务管理器来协调。

锁表实现单个 Paxos 组内的单机事务,事务管理器实现跨多个 Paxos 组的分布式事务。为了实现分布式事务,需要实现两阶段提交协议。有一个 Paxos 组的主副本会成为两阶段提交协议中的协调者,其他 Paxos 组的主副本为参与者。

7.3.4 TrueTime

要给每个事务分配全局唯一的事务 id。Spanner 通过 全球时钟同步机制 Truetime 实现。

Truetime 返回时间戳 t 和误差 e。真实系统 e 平均下来只有 4 ms。

Truetime API 实现的基础是 GPS 和原子钟。

每个数据中心需要部署一些主时钟服务器(Master),其他机器上部署一个从时钟进程(Slave)来从主时钟服务器同步时钟信息。有的主时钟服务器用 GPS,用的用原子钟。

7.3.5 并发控制

支持以下事务:

  • 读写事务
  • 只读事务
  • 快照读,客户端提供时间戳
  • 快照读,客户端提供时间范围

考虑 TrueTime,为了保证事务顺序,事务 T1 会在 t1 + e 之后才提交,事务 T2 会在 t2 + e 之后才提交。意味着每个写事务的延迟至少为 2e。

7.3.6 数据迁移

7.3.7 讨论

相关文章
|
5月前
|
数据采集 机器学习/深度学习 运维
量化合约系统开发架构入门
量化合约系统核心在于数据、策略、风控与执行四大模块的协同,构建从数据到决策再到执行的闭环工作流。强调可追溯、可复现与可观测性,避免常见误区如重回测轻验证、忽视数据质量或滞后风控。初学者应以MVP为起点,结合回测框架与实时风控实践,逐步迭代。详见相关入门与实战资料。
|
5月前
|
前端开发 JavaScript BI
如何开发车辆管理系统中的车务管理板块(附架构图+流程图+代码参考)
本文介绍了中小企业如何通过车务管理模块提升车辆管理效率。许多企业在管理车辆时仍依赖人工流程,导致违章处理延误、年检过期、维修费用虚高等问题频发。将这些流程数字化,可显著降低合规风险、提升维修追溯性、优化调度与资产利用率。文章详细介绍了车务管理模块的功能清单、数据模型、系统架构、API与前端设计、开发技巧与落地建议,以及实现效果与验收标准。同时提供了数据库建表SQL、后端Node.js/TypeScript代码示例与前端React表单设计参考,帮助企业快速搭建并上线系统,实现合规与成本控制的双重优化。
|
5月前
|
机器学习/深度学习 人工智能 缓存
面向边缘通用智能的多大语言模型系统:架构、信任与编排——论文阅读
本文提出面向边缘通用智能的多大语言模型(Multi-LLM)系统,通过协同架构、信任机制与动态编排,突破传统边缘AI的局限。融合合作、竞争与集成三种范式,结合模型压缩、分布式推理与上下文优化技术,实现高效、可靠、低延迟的边缘智能,推动复杂场景下的泛化与自主决策能力。
444 3
面向边缘通用智能的多大语言模型系统:架构、信任与编排——论文阅读
|
5月前
|
Cloud Native Serverless API
微服务架构实战指南:从单体应用到云原生的蜕变之路
🌟蒋星熠Jaxonic,代码为舟的星际旅人。深耕微服务架构,擅以DDD拆分服务、构建高可用通信与治理体系。分享从单体到云原生的实战经验,探索技术演进的无限可能。
微服务架构实战指南:从单体应用到云原生的蜕变之路
|
5月前
|
人工智能 自然语言处理 安全
AI助教系统:基于大模型与智能体架构的新一代教育技术引擎
AI助教系统融合大语言模型、教育知识图谱、多模态交互与智能体架构,实现精准学情诊断、个性化辅导与主动教学。支持图文语音输入,本地化部署保障隐私,重构“教、学、评、辅”全链路,推动因材施教落地,助力教育数字化转型。(238字)
886 23
|
5月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
Spring Boot 3.x 微服务架构实战指南
|
6月前
|
消息中间件 数据采集 NoSQL
秒级行情推送系统实战:从触发、采集到入库的端到端架构
本文设计了一套秒级实时行情推送系统,涵盖触发、采集、缓冲、入库与推送五层架构,结合动态代理IP、Kafka/Redis缓冲及WebSocket推送,实现金融数据低延迟、高并发处理,适用于股票、数字货币等实时行情场景。
772 3
秒级行情推送系统实战:从触发、采集到入库的端到端架构
|
6月前
|
设计模式 人工智能 API
AI智能体开发实战:17种核心架构模式详解与Python代码实现
本文系统解析17种智能体架构设计模式,涵盖多智能体协作、思维树、反思优化与工具调用等核心范式,结合LangChain与LangGraph实现代码工作流,并通过真实案例验证效果,助力构建高效AI系统。
737 7
|
5月前
|
存储 人工智能 搜索推荐
拔俗AI助教系统:基于大模型与智能体架构的新一代教育技术引擎
AI助教融合大语言模型、教育知识图谱、多模态感知与智能体技术,重构“教、学、评、辅”全链路。通过微调LLM、精准诊断错因、多模态交互与自主任务规划,实现个性化教学。轻量化部署与隐私保护设计保障落地安全,未来将向情感感知与教育深度协同演进。(238字)
520 0

推荐镜像

更多
  • DNS