因为我是标题党。

这本书与我们常用来垫显示器的《算法导论》或《深入理解计算机系统》(如果你是大一大二的同学,可能还包括《算法竞赛入门经典》)并不属于同一类。它更接近《C++ Primer》或那本《算法》(Robert Sedgewick 著)——属于通识型读物。

换句话说,如果你尚未掌握相关基础知识,阅读这本书的学习曲线将会异常陡峭;而一旦你已经入门,它的表达方式会让你觉得十分优雅,结构也很清晰,却又可能让你觉得“说得都对,但好像也没什么新东西”。

如果你是初入数据相关系统领域的新手,我更希望你先对这本书的脉络和重点有个清晰概览,剪枝信息、化繁为简,帮助你更快建立起基础认知,从而更高效地阅读这本书,而不是在术语和细节中反复迷路。

什么是数据密集型系统

数据密集型系统可以理解为一个结构上的“双面体”:一方面,它需要实时地处理数据的存储与检索;另一方面,它还承担着异步处理和计算已有数据的任务。这两种模式共同支撑了系统对数据的全面利用。

我们之所以称其为“数据密集型”,是因为它所处理的数据具备以下三个核心特征:

  • 数据是不可再生的——一旦丢失,就无法重新获取,具有唯一性与不可逆性;
  • 数据是持续增长的——系统需要不断接收新数据,数据量随着时间推移呈线性,甚至指数级上升;
  • 数据的应用是不断演进的——数据的价值和使用方式会随着业务需求和技术手段的发展而变化。

正因为如此,设计和构建数据密集型系统时,我们必须重点关注三个目标: * 可靠性:防止数据丢失,保障系统在故障时能够正确恢复; * 可扩展性:系统能够随着数据量和访问量的增加平稳扩展; * 可维护性:系统结构清晰、易于理解,能够适应未来不断变化的需求和环境。

数据模型与数据编码

数据模型

数据模型是对现实世界的结构化抽象,是我们与数据系统沟通的“语言”。不同类型的数据模型基于不同的设计假设,适用于不同的场景。

常见的数据模型包括:

  • 关系模型

    • 典型代表:MySQL、PostgreSQL 等传统 SQL 数据库
    • 数据以“表格”的形式组织,每张表表示一种实体或关系,每行是一条记录
    • 特点:
      • 严格的结构约束(schema)
      • 支持复杂的查询语句和事务处理
      • 数据一致性强,适合结构清晰、关系复杂的场景
  • 文档模型

    • 典型代表:MongoDB、Redis(部分用作文档存储)等 NoSQL 系统
    • 数据以文档形式组织(通常是 JSON 或 BSON 格式),每个文档是一条记录
    • 特点:
      • 模式灵活,不强制 schema
      • 更适合嵌套结构和非结构化数据
      • 写入与扩展性能更好,适用于快速迭代和海量数据场景

选择何种数据模型,本质上是对业务需求和系统约束之间做出的权衡。

数据编码

在内存中,我们倾向于使用链表、哈希表、树等结构进行快速访问。但在持久化存储和网络传输中,我们需要将数据编码成紧凑且结构化的格式,以提高读写效率与兼容性。

好的数据编码格式需要权衡三个核心指标:

  • 向前兼容性:新版本的系统仍能读取旧格式的数据;
  • 向后兼容性:旧版本的系统能忽略新数据中的未知字段,正常运行;
  • 效率:编码后的数据大小与 CPU 解码开销之间取得平衡。

常见的数据编码方案:

  • 语言内置格式(如 Python 的 pickle、Java 的 Serializable
    • 与语言紧耦合,移植性差
    • 不支持数据结构演化
    • 编解码效率不高,不建议用于跨系统持久化或网络传输
  • 文本格式(如 CSV、XML、JSON)
    • 通用、易读、调试友好
    • 几乎被所有编程语言支持
    • 存在大量冗余(如键名重复),不适合高效存储或传输
    • 不适合嵌套结构或二进制数据
  • 二进制格式(如 Protobuf、Thrift、Avro)
    • 高度紧凑,支持嵌套与复杂结构
    • 支持数据演化,兼容性好
    • 编解码性能高,但不易调试(需工具查看)

在构建数据密集型系统时,模型与编码的选择往往影响深远,且难以随意更改,务必根据业务需求慎重选择。

数据检索

事务处理系统(OLTP)中的索引结构

OLTP(在线事务处理)系统主要处理高并发、实时读写请求,因此对延迟极度敏感。常见的索引结构有:

  • 哈希表:用于快速键值对检索,结构简单,性能高;
  • LSM-Tree:多层已排序数组结构,写入快,适合写多读少场景;
  • B-Tree:多叉平衡排序树,适合读写混合场景,是多数数据库的默认索引类型。

数据分析系统(OLAP)中的索引结构

OLAP(在线分析处理)系统用于处理大规模离线数据任务,关注的是整体吞吐而非单次请求的响应延迟。

事实表与列式存储

在数据仓库中,事实表记录每一条事件数据,通常有很多列来表示不同维度。虽然逻辑上按行存储,但物理上采用列式存储更为高效:

  • 查询只需读取必要的列,I/O更少;
  • 同一列数据分布相似,压缩率更高;
  • 列式布局更利于向量化计算和并行处理。

小结

从模型、编码到检索,数据系统的基础构成其实围绕着一个核心问题展开:我们如何高效、可靠地组织、保存与使用数据。

  • 数据模型决定了我们如何抽象现实世界中的事物与关系;
  • 数据编码决定了我们如何在系统之间传递和持久化这些抽象;
  • 数据检索结构则决定了我们如何以尽可能低的开销获得所需信息

下一篇,我们将探讨分布式日志、复制机制和一致性协议在数据系统中的角色与实践 —— 希望能有下一篇。


Comments

comments powered by Disqus