拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DDIA 第一部分《数据系统基础》导读:前五章构建数据密集型应用的核心知识体系

DDIA 第一部分《数据系统基础》导读:前五章构建数据密集型应用的核心知识体系
  • 文档
  • 教程

【免费下载链接】ddia

《Designing Data-Intensive Application》DDIA 第一版 / 第二版 中文翻译

项目地址:https://gitcode.com/gh_mirrors/dd/ddia
点击查看免费下载

本篇导读基于《Designing Data-Intensive Applications》(DDIA)中文翻译仓库中的 第一部分总览页 展开,系统梳理第一部分的五章内容——数据系统架构权衡、非功能性需求、数据模型与查询语言、存储与检索、编码与演化——并结合仓库中对应章节的源码级细节,帮助你建立从单机到分布式、从存储引擎到数据流模式的完整知识骨架。读完本文,你将掌握每一章的核心概念、关键术语与可直接定位的阅读路径,为后续阅读第二、第三部分打下基础。

第一部分在全书中的位置与阅读顺序

《Designing Data-Intensive Applications》共分三大部分:第一部分"数据系统基础"(Part I)、第二部分"分布式数据"(Part II)、第三部分"派生数据"(Part III)。正如 part-i.md 开篇所强调的:

本书前五章介绍了数据系统底层的基础概念,无论是在单台机器上执行的单点数据系统,还是分布在多台机器上的分布式数据系统都适用。

也就是说,第一部分的五章讨论的是所有数据系统共享的底层问题:如何权衡架构、如何定义需求、如何选择数据模型、数据如何存储与检索、数据如何编码与演化。这些内容不依赖"分布式"这一前提,因此是后续第二、第三部分的技术前提。

从仓库的 Hugo 内容结构也能印证这一点:content/tw/part-i.md的 front matter 中book_kind: part、book_number: I、weight: 100,而五章分别以weight: 101–105紧随其后(见 content/tw 目录),即按 1→2→3→4→5 的固定顺序组织,说明第一部分内部存在明确的前后依赖关系——例如 第三章 介绍的数据模型会被 第四章 的存储引擎设计复用,第五章 的编码演化问题又建立在前两章的术语之上。

第一章:数据系统架构中的权衡

第一章 回答一个根本问题:既然数据系统没有"唯一正确"的架构,我们应该如何在相互冲突的目标之间做取舍?章节开篇引用了 Thomas Sowell 的话:"没有解决方案,只有权衡取舍。"

本章首先区分两类应用:数据密集型(data-intensive)应用关心的是如何存储和处理海量数据、如何管理数据变更、如何在故障与并发面前保证一致性、如何维持高可用;而计算密集型(compute-intensive)系统的难点在于把某项庞大计算并行化。绝大多数现代 Web、移动、SaaS 与云应用都属于前者。

数据系统的标准构件

章节列出了几乎所有数据密集型应用都会用到的标准构件:

  • 数据库(database):存储数据,供自己或其他应用日后查找
  • 缓存(cache):记住开销昂贵的操作结果,加快读取
  • 搜索索引(search index):允许用户按关键字搜索或过滤数据
  • 流处理(stream processing):在事件和数据变更发生后立即处理
  • 批处理(batch processing):定期处理累积的大批量数据

应用通常用若干软件系统(数据库、API 等)拼装而成;难点在于判断哪种工具最适合当前任务,以及当单件工具无法独立完成时如何组合它们。

三组核心权衡

章节正文围绕三组相对概念展开(对应 分析型与事务型系统、云服务与自托管、分布式与单节点系统 三个小节):

  1. 事务型系统(OLTP)与 分析型系统(OLAP):事务型系统由创建数据的后端服务组成,按某个键做低延迟的点查询(point query)并插入、更新、删除记录;分析型系统则存储事务型数据的只读副本,扫描海量记录计算聚合统计量。章节进一步讨论了数据仓库(data warehouse)、从数据仓库到数据湖(data lake)、权威记录系统与衍生数据(derived data)等概念,并引入了数据工程师与分析工程师两个专业角色。
  2. 云服务与自托管:对比二者的利弊(云服务的利弊),讨论云原生系统架构(云服务分层、存储与计算分离)以及云时代的运维模式。
  3. 分布式与单节点系统:说明何时应当从单节点转向分布式(分布式系统的问题),并延伸到微服务与无服务器(serverless)架构(微服务与无服务器)。

此外,本章还讨论了 数据系统、法律与社会 这一面向合规与用户权利的议题,并提供全书通用的术语基础——例如"前端与后端""数据基础设施""无状态服务"等概念。章节末尾的 总结 浓缩了上述权衡的核心结论。

第二章:定义非功能性需求

第二章 讨论功能需求之外的另一半:性能、可靠性、可伸缩性、可维护性等非功能性需求(nonfunctional requirements)。它们未必被明确写下来,但"一个慢得让人无法忍受、或是很不可靠的应用,几乎等于不存在"。

案例研究:社交网络首页时间线

为了让抽象概念落地,章节用一个类似 X(原 Twitter)的社交网络作为贯穿案例,并给出了真实的 SQL 查询示例——获取某位用户首页时间线的核心查询:

SELECT posts.*, users.* FROM posts JOIN follows ON posts.sender_id = follows.followee_id JOIN users ON posts.sender_id = users.id WHERE follows.follower_id = current_user ORDER BY posts.timestamp DESC LIMIT 1000

由此引出两个关键工程概念(见 案例研究:社交网络首页时间线 与 时间线的物化与更新):

  • 扇出(fan-out):一次发帖引发多个下游请求,请求数量被放大的倍数。
  • 物化(materialization):预先计算并持续更新查询结果;时间线缓存就是一种物化视图(materialized view)。物化以写入时更多工作换取读取时更快的速度,章节还讨论了关注极多账号、或拥有海量粉丝的名人账号等极端场景下的取舍。

描述性能

描述性能 小节区分了延迟(latency)与响应时间(response time),并介绍了用平均值、中位数与分位数(尤其尾部延迟 p95/p99)来刻画用户体验的方法(平均值、中位数与分位数),以及如何将其落实为 SLO / SLA 指标(响应时间指标的应用)。

可靠性、可伸缩性与可维护性

  • 可靠性(reliability):系统在出问题时仍能继续正确工作。章节覆盖容错(fault tolerance)、硬件与软件故障(含通过冗余容忍硬件故障)、以及人为因素——人为错误往往比硬件故障更常见(人类与可靠性)。
  • 可伸缩性(scalability):系统负载增长时能否高效增加计算能力。描述负载 给出了描述负载的指标(如 Twitter 案例中的每秒发帖数、时间线读取率);共享内存、共享磁盘与无共享架构 对比了三种横向扩展的硬件组织方式。
  • 可维护性(maintainability):从三个维度展开——可运维性(让运维更轻松)、简单性(管理复杂度)、可演化性(让变化更容易)。

第三章:数据模型与查询语言

第三章 讨论数据模型——"它们不仅影响软件的编写方式,还影响我们的解题思路"。章节用一个四层模型说明数据抽象的层次:应用层的数据结构与 API → 通用数据模型(JSON/XML 文档、关系表、图的顶点与边)→ 存储引擎的字节表示 → 硬件层。每层通过明确的模型隐藏下层复杂性。

关系模型与文档模型

本章对比的核心是关系模型(relational model,1970 年由 Edgar Codd 提出)与文件模型(document model,由 NoSQL 运动推广,常以 JSON 表示):

  • 对象关系不匹配(阻抗不匹配):对象式编程语言与关系表模型之间需要笨拙的转换层。章节专门用一节讨论 ORM(如 ActiveRecord、Hibernate)的局限与优势(对象关系映射 ORM),包括著名的N+1 查询问题。
  • 一对多关系:文档模型天然适合一对多关系(用于一对多关系的文档数据模型)。
  • 规范化、反规范化与连接:讨论正规格的权衡,以及社交网络案例中的反规范化(正规格化的权衡、社交网络案例研究中的反规范化)。
  • 多对一与多对多关系(多对一与多对多关系):文档模型在这一场景下需要仿照关系模型做连接。
  • 星型与雪花型:分析模式(星型与雪花型:分析模式):分析型数据建模的经典模式。
  • 何时使用哪种模型:从模式灵活性(读时模式 vs 写时模式)、读写的数据局部性、文档的查询语言、文档与关系数据库的融合四个角度给出决策框架(文档模型中的模式灵活性、读写的数据局部性、文档的查询语言、文档和关系数据库的融合)。

图数据模型、事件溯源与其他模型

  • 图数据模型:从属性图(property graph,属性图)讲起,依次对比 Cypher 查询语言、SQL 中的图查询、三元组存储与 SPARQL(含 RDF 数据模型)、Datalog(递归关系查询)以及 GraphQL(Cypher 查询语言、SQL 中的图查询、三元组存储与 SPARQL、GraphQL)。
  • 事件溯源与 CQRS(事件溯源与 CQRS):以不可变事件日志为核心的数据模型。
  • 数据框、矩阵与数组(数据框、矩阵与数组):面向数据科学/机器学习场景的模型。

章节还以术语框形式介绍了声明式查询语言(SQL、Cypher、SPARQL、Datalog 等)与命令式算法的区别:声明式查询由查询优化器决定执行计划,数据库可以无修改地并行执行并提升性能。

第四章:存储与检索

第四章 从数据库的视角回答"数据如何存储、如何重新找到"。章节开篇用两个 Bash 函数展示了"世界上最简单的数据库",完整演示了追加写日志的核心思想:

db_set () { echo "$1,$2" >> database } db_get () { grep "^$1," database | sed -e "s/^$1,//" | tail -n 1 }

调用db_set key value将键值对追加到文件末尾,db_get key返回该键最后一次出现的值。这个例子说明:仅追加(append-only)日志是所有复杂存储引擎的基础,真正的数据库还要解决并发写入、磁盘空间回收、崩溃恢复(处理写了一半的记录)等问题。

OLTP 存储引擎的两大流派

  • 日志结构(log-structured)存储:以不可变文件顺序写入数据,通过压实(compaction)回收空间。章节依次讲解SSTable 文件格式、SSTable 的构建与合并、布隆过滤器(加速键是否存在判断)与压实策略(SSTable 文件格式、构建和合并 SSTable、布隆过滤器、压实策略)。
  • B 树(B-tree):就地更新数据页的经典结构,需要*预写日志(WAL)*保证可靠性(使 B 树可靠),并有多种变体。

随后章节给出 B 树与 LSM 树的系统性对比(比较 B 树与 LSM 树):读取性能、顺序与随机写入、写放大(write amplification)、磁盘空间使用四个维度。此外还覆盖多列索引与二级索引、全内存存储(in-memory)等主题。

分析型数据存储与高级索引

  • 分析型数据存储(分析型数据存储):云数据仓库、列式存储(列压缩、排序顺序、写入列式存储),以及现代查询引擎的编译与向量化执行(查询执行:编译与向量化)、物化视图与多维数据集。
  • 多维度索引与全文索引(多维度索引与全文索引):全文检索与向量嵌入(embedding,向量嵌入)等支撑复杂查询的索引技术。

第五章:编码与演化

第五章 的主题是"唯变所适":应用必然随时间变化,数据格式与模式也随之演化。章节的核心框架是一对兼容性定义:

  • 向后兼容(backward compatibility):较新的代码可以读取由较旧代码写入的数据——通常不难实现。
  • 向前兼容(forward compatibility):较旧的代码可以读取由较新代码写入的数据——更难,因为旧代码必须忽略新代码新增的字段。

章节还用一个具体场景(旧版代码读出新字段记录、更新后写回,若模型对象不显式保留未知字段就会丢失数据)说明向前兼容的难点,这也是选择编码格式时最重要的判据。

编码数据的格式

  • 特定语言的格式(如 JavaSerializable、Pythonpickle、RubyMarshal):方便但存在语言锁定、任意类实例化的安全风险、版本管理缺失、效率低下等问题,通常不适合长期存储。
  • JSON、XML 及其二进制变体:跨语言标准格式,章节讨论了JSON Schema与二进制编码方案。
  • Protocol Buffers:通过字段标签(field tag)支持模式演化(字段标签与模式演化)。
  • Avro:基于写入者模式与读取者模式的兼容机制(写入者模式与读取者模式),以及模式演化规则、动态生成的模式等特性。
  • 模式的优点(模式的优点):显式模式带来的文档价值与校验能力。

数据流的模式

编码不仅用于存储,也用于进程间通信。章节将数据流归纳为三种模式:

  • 流经数据库的数据流:不同时间写入的不同值、归档存储(不同时间写入的不同值、归档存储)。
  • 流经服务的数据流:REST 与 RPC:Web 服务、RPC 的固有问题(重试、超时、幂等)、负载均衡器、服务发现与服务网格,以及 RPC 场景下的数据编码与演化(Web 服务、RPC 的问题、负载均衡器、服务发现和服务网格、RPC 的数据编码与演化)。
  • 事件驱动的架构:持久化执行与工作流(durable execution)、消息代理(message broker)与分布式 actor 框架(持久化执行、消息代理、分布式 actor 框架)。

仓库中的阅读路线与延伸资源

本仓库同时维护了简体中文、繁体中文与第一版译文,便于对照阅读:

  • 简体中文第一部分的五章见 content/zh/ch1.md 至 content/zh/ch5.md;本篇所依据的繁体中文版见 content/tw/ch1.md 至 content/tw/ch5.md;
  • 第一版译文位于 content/v1 目录,可供版本对比;
  • 每章的图集中存放于 static/fig(如 ddia_0201.png、ddia_0501.png 等按章节编号),章首还配有位于 static/map 的章节思维导图(如本章引用的 ch01.png 对应第二章);
  • 全书目录与阅读说明见 README.md,其"目录"一节列出了三大部分共十四章的完整结构。

读完全部五章之后,即可进入 第二部分(分布式数据,对应第六章至第十章),届时第一部分的单机知识会与复制、分片、事务、一致性与共识等分布式主题衔接起来。从仓库的 front matter 结构看,第二部分以book_number: II、weight紧随第一部分编排(见 content/tw/part-ii.md),两部分构成全书递进的知识链条。

结语

第一部分"数据系统基础"是整本 DDIA 的基石:第一章确立"权衡"的世界观,第二章给出衡量系统的指标语言,第三章教会你选择数据模型,第四章揭示存储引擎的内部机理,第五章则解决系统长期演化中的兼容性问题。五章环环相扣、层层递进,无论你最终面向单机系统还是分布式系统,这部分知识都同样适用。建议按照 ch1 → ch5 的顺序通读,并结合本仓库的章节链接与思维导图资源边读边对照,为第二部分的分布式主题做好准备。

  • 文档
  • 教程

【免费下载链接】ddia

《Designing Data-Intensive Application》DDIA 第一版 / 第二版 中文翻译

项目地址:https://gitcode.com/gh_mirrors/dd/ddia
点击查看免费下载
上一篇:Java代码生成最佳实践:基于gh_mirrors/auto/auto的设计模式应用
下一篇:Applaudo 档案全解析:remote-jobs 目录中远程友好型科技公司的档案结构与构建链路

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表