第 1 章 数据系统架构中的权衡
天下没有完美方案,只有种种权衡。[……] 你能做的,不过是争取在自己能拿到的取舍中挑出最好的那一份——除此别无奢望。
——Thomas Sowell,接受 Fred Barnes 采访(2005 年)
数据是当今许多应用开发的核心。随着 Web 与移动应用、SaaS(软件即服务)与云服务的普及,把众多用户的数据存放到共享的服务器端数据基础设施中已成常态。来自用户活动、业务事务、设备与传感器的数据都要被存起来,并提供给分析使用。用户与应用交互的过程中,既会读取已存的数据,也会生成更多数据。
当数据量较小、单台机器即可存储与处理时,事情往往比较简单。然而一旦数据量或查询速率不断增长,数据就必须在多台机器之间分布,随之而来便有诸多挑战。当应用的需求变得更复杂时,仅靠一种系统已不足以承载一切——你可能必须把多种存储或处理系统组合起来,让它们各以所长共同支撑。
如果数据管理是开发某个应用过程中的核心挑战之一,我们就称这种应用为数据密集型的 [1]。在计算密集型系统中,挑战在于把极大规模的计算并行化;而在数据密集型应用中,我们更关心的是如何存储与处理大数据量、如何管理数据的变化、如何在故障与并发下保证一致性,以及如何确保服务高可用。
这类应用通常由提供常用功能的标准构件搭建而成。例如,许多应用都需要做到以下几件事:
- 把数据存起来,以便它自己或另一个应用之后还能找到(数据库)
- 记住一次代价高昂操作的结果,以加快后续读取(缓存)
- 允许用户按关键词搜索数据,或以各种方式过滤数据(搜索索引)
- 在事件与数据变化发生时立即处理(流处理)
- 周期性地处理大批积累下来的数据(批处理)
构建应用时,我们通常会选取若干软件系统或服务(如数据库或 API),再用应用代码把它们粘合起来。如果你要做的事恰好与这些数据系统的设计目标相符,这一过程会相当轻松。
然而当你的应用愿景越来越大,挑战也接踵而至。可选的数据库系统数以百计,特性各异、适用场景也不同——你如何决定该用哪一种?缓存有多种实现思路,搜索索引也有几种构建方式,等等——你又如何在这些方案之间作出取舍?你需要弄清哪些工具与方法最适合手头的任务;当你要做的事情单一工具无法独力胜任时,把多种工具组合起来同样困难重重。
本书是一份指南,帮助你判断该使用哪些技术、又该如何把它们组合起来。你会发现:没有哪一种方案在根本上优于其他;每种都有自己的优劣。借助本书,你将学会问出对的问题,去评估并比较不同的数据系统,从而找到最适合你这个具体应用的那一种。
我们将从当今数据在组织中常见的几种使用方式开始这趟旅程。这里的不少思想都源自企业软件领域(即面向大型组织——如大公司与政府机关——的软件需求与工程实践),因为历史上只有大型机构才会拥有大到非借助复杂技术方案不可的数据量。如果你的数据量足够小,一张电子表格就能装下;不过近年来,规模较小的公司与初创团队也越来越频繁地需要管理大数据量、构建数据密集型系统。
数据系统的关键挑战之一,是不同的人需要用数据做截然不同的事。如果你在一家公司工作,你和团队会有自己的一套优先级,而另一支团队即便处理的是同一份数据集,目标也可能完全不同!更何况,这些目标常常没有被明确表达出来,从而引发对"正确做法"的误解与争论。
为帮助你理解这些选择,本章将对比若干互为对照的概念,探讨它们的取舍。我们会涉及以下主题:
- 运营系统与分析系统的差别("运营系统与分析系统",第 3 页)
- 云服务与自托管系统的优劣("云 vs 自托管",第 12 页)
- 何时该从单节点系统走向分布式系统("分布式系统 vs 单节点系统",第 19 页)
- 在业务需求与用户权益之间取得平衡("数据系统、法律与社会",第 24 页)
本章还会定义全书后续会用到的术语。
术语:前端与后端
本书所讨论的内容大多与后端开发有关。先解释一下这个词:对于 Web 应用而言,运行在 Web 浏览器中的客户端代码称为前端,而处理用户请求的服务器端代码则称为后端。移动 App 与前端类似——它们也提供用户界面,并通过互联网与服务器端的后端通信。前端有时也会在用户设备上本地管理数据 [2],但最主要的基础设施挑战通常出现在后端:前端只需处理一个用户的数据,而后端要为所有用户管理数据。
后端服务通常通过 HTTP(有时是 WebSocket)对外可达,通常由读写一个或多个数据库的应用代码构成,有时还会与其他数据系统对接,例如缓存或消息队列(这些可统称为数据基础设施)。应用代码通常是无状态的(即处理完一个 HTTP 请求后,便完全忘记该请求的一切),任何需要跨请求保留的信息,要么存放在客户端,要么存放在服务器端的数据基础设施里。
运营系统与分析系统
如果你在企业中从事数据系统工作,很可能会遇到几类不同的"与数据打交道"的人。第一类是后端工程师:他们构建处理读写请求的服务,这些服务往往面向外部用户,可能直接对外,也可能间接通过其他服务(参见"微服务与无服务器",第 21 页)。有时这些服务也供组织内的其他部门使用。
除了管理后端服务的团队之外,通常还有另外两类人需要访问组织的数据:业务分析师——他们针对组织的活动生成报表,帮助管理层做出更好的决策(即商业智能,BI);以及数据科学家——他们或在数据中寻找新的洞察,或借助数据分析与机器学习(ML)/AI 创造面向用户的产品功能(例如电商网站上"购买了 X 的人也购买了 Y"的推荐,或风险评分、垃圾邮件过滤、搜索结果排序等预测分析)。
虽然业务分析师与数据科学家所用的工具与工作方式各有不同,但他们也共享一些做法。第一,两者都从事分析工作,即查看用户与后端服务所产生的数据。第二,他们一般不修改这些数据(除非是修复错误),但可能会在某些处理之后创建派生数据集。
由此演化出本书将贯穿使用的两类系统的划分:
- *运营系统(Operational systems)*由产生数据的后端服务与数据基础设施组成——例如为外部用户提供服务的部分。在这里,应用代码会根据用户的操作既读取数据,也修改数据库中的数据。
- *分析系统(Analytical systems)*服务于业务分析师与数据科学家。它们存放着运营系统中数据的只读副本,并针对分析所需的处理类型做了优化。
下一节会看到,运营系统与分析系统出于种种正当理由通常被分开。随着这类系统逐步成熟,又催生出两个新的专业角色:数据工程师与分析工程师。数据工程师懂得如何把运营系统与分析系统整合起来,并对组织的数据基础设施承担更广泛的责任 [3];分析工程师则建模并转换数据,让数据对组织内的业务分析师与数据科学家更具价值 [4]。
许多工程师专精于运营或分析中的某一面。但本书涵盖两者,因为它们在组织数据生命周期中都扮演重要角色。我们会深入考察用于服务内部与外部用户的数据基础设施,让你能与"分隔线另一侧"的同事更顺畅地协作。
运营处理与分析处理的特征
业务数据处理的早期,对数据库的一次写入通常对应一次正在发生的商业交易(transaction):完成一笔销售、向供应商下订单、给员工发工资等等。当数据库逐步扩展到不涉及金钱往来的领域时,*事务(transaction)*这个术语仍然保留了下来,用于泛指构成一个逻辑单元的一组读写操作。
第 8 章会详细探讨我们所说的"事务"具体含义。本章使用这个词时较为宽松,仅指低延迟的读写。
尽管数据库已被用于各式各样的数据——社交媒体上的帖子、游戏中的一步、通讯录中的联系人,等等——但其基本访问模式仍然类似于处理商业事务。运营系统通常通过键查找少量记录(称为点查询,point query),并根据用户输入插入、更新或删除记录。由于这类应用是交互式的,这种访问模式便被称为在线事务处理(OLTP)。
然而,数据库也越来越多地被用于分析,而分析的访问模式与 OLTP 大不相同。一次分析查询通常会扫描大量记录,并计算诸如计数、求和、平均值之类的聚合统计量,而不是返回单条记录给用户。例如,一家连锁超市的业务分析师可能想回答以下分析问题:
- 我们各家门店在一月份的总营收是多少?
- 在最新一轮促销期间,香蕉比平时多卖了多少?
- 哪个品牌的婴儿食品最常与品牌 X 的尿布一起被购买?
这类查询所产出的报表对 BI 至关重要,可帮助管理层决定下一步该怎么做。为了把数据库的这类用法与事务处理区分开,它被称作在线分析处理(OLAP) [5]。OLTP 与分析之间并不总有一条清晰的分界线,但典型差异列于表 1-1 中。
表 1-1. 运营系统与分析系统特征对比
| 属性 | 运营系统(OLTP) | 分析系统(OLAP) |
|---|---|---|
| 主要读取模式 | 点查询(按键取单条记录) | 对大量记录做聚合 |
| 主要写入模式 | 创建、更新、删除单条记录 | 批量导入(ETL)或事件流 |
| 人类用户示例 | Web/移动应用的最终用户 | 内部分析师,决策支持 |
| 机器用户示例 | 检查某操作是否被授权 | 检测欺诈/滥用模式 |
| 查询类型 | 由应用预先定义、固定不变 | 由分析师任意发起、临时探索 |
| 查询数量 | 大量小查询 | 查询不多,但每条都复杂 |
| 数据所代表的 | 数据的最新状态(当前时间点) | 历经时间发生过的事件历史 |
| 数据集大小 | GB 至 TB | TB 至 PB |
OLAP 中"online(在线)"一词的含义并不清晰;它大概指查询并非仅限于预定义报表,而是由分析师以交互方式发起的探索性查询。
在运营系统中,通常不允许用户自行构造任意 SQL 查询并在数据库上运行,因为这可能让他们读到或改到本无权访问的数据;他们也可能写出执行代价极大的查询,从而拖慢其他用户访问数据库时的性能。正因如此,OLTP 系统大多运行一组预先定义、嵌入在应用代码中的固定查询,一次性的临时查询只在维护或排障时偶尔使用。相比之下,分析型数据库通常允许用户自行手写任意 SQL 查询,或借助 Tableau、Looker 或 Microsoft Power BI 等数据可视化与仪表板工具自动生成查询。
还有一种系统专为分析型工作负载(在大量记录上做聚合的查询)而设计,但被嵌入到面向用户的产品中。为此类用途设计的系统——被称为产品分析或实时分析——包括 Pinot、Druid 与 ClickHouse [6]。这类系统实时摄取数据,并针对低延迟的查询响应做了优化。相对地,传统 OLAP 系统通常以批量方式摄取数据,并针对高吞吐的查询处理做了优化。
数据仓库
最初,同一份数据库既被用于事务处理,也被用于分析查询。事实证明 SQL 在这方面相当灵活:两类查询都能跑得不错。但到了 1980 年代末与 1990 年代初,出现了一种趋势:公司不再用 OLTP 系统跑分析,而是把分析放到一台独立的数据库系统上运行。这台独立的数据库就被称为数据仓库(data warehouse)。
一家大型企业可能拥有数十个、甚至数百个 OLTP 系统:支撑面向客户网站的、控制实体门店销售点(POS)的、跟踪仓库库存的、规划车辆路线的、管理供应商的、处理员工事务的,以及完成众多其他任务的。每一个都很复杂,需要专人维护,因而它们大多最终各自独立运行。
让业务分析师与数据科学家直接查询这些 OLTP 系统通常并不可取,原因有以下几条:
- 感兴趣的数据可能散落在多个运营系统里,让"在一次查询中合并这些数据集"变得困难(这一问题被称为数据孤岛,data silos)。
- 适合 OLTP 的模式与数据布局并不太适合分析(参见"分析的星型与雪花型模式",第 77 页)。
- 分析查询往往代价高昂,跑在 OLTP 数据库上会拖累其他用户的性能。
- 出于安全或合规原因,OLTP 系统可能位于用户无权直接访问的独立网络内。
相对地,数据仓库是一份独立的数据库,分析师可以在其中尽情查询,而不影响 OLTP 操作 [7]。如同我们将在第 4 章看到的,数据仓库通常以与 OLTP 数据库截然不同的方式存放数据,针对分析中常见的查询类型做了优化。
数据仓库存放的是来自公司各 OLTP 系统的数据的只读副本。数据要么周期性地从 OLTP 数据库中转储,要么以连续的更新流抽取出来,再被转换为对分析友好的模式、清洗,然后加载进数据仓库。这种把数据迁入数据仓库的过程被称为抽取-转换-加载(ETL),如图 1-1 所示。有时*转换(transform)与加载(load)*的顺序会被互换(即先加载,再在数据仓库内做转换),由此得到 ELT。

图 1-1. 通过 ETL 将数据加载进数据仓库的简化流程
图示文字描述: 图示从上到下分为两层:上层是"运营系统",包括 Customer 使用的 Ecommerce 站点(连接 Sales DB)、Warehouse worker 使用的库存管理 App(连接 Inventory DB)、Truck driver 使用的车辆路径规划器(连接 Geo DB);下层是"分析系统",三条 Extract 箭头分别将三个 DB 的数据抽出,进入三个 Transform 框,随后通过 Load 箭头汇入中央的 Data warehouse;Business analyst 通过 Query 访问该数据仓库。
某些情况下,ETL 流程的数据源是外部 SaaS 产品——如客户关系管理(CRM)、电子邮件营销或信用卡处理系统。在这些场景下,你无法直接访问其原始数据库,只能通过软件供应商的 API 访问。把这些外部系统中的数据汇入自家数据仓库,可以让原本通过 SaaS API 无法实现的分析成为可能。SaaS API 的 ETL 通常由 Fivetran、Singer 或 Airbyte 等专业的数据连接器服务来实现。
某些数据库系统提供混合事务/分析处理(HTAP),意图在同一系统内同时支持 OLTP 与分析,避免把数据从一个系统 ETL 到另一个 [8, 9]。然而,许多 HTAP 系统在内部其实由一个 OLTP 系统加上一个独立的分析系统组成,藏在统一的接口背后——因此两者的差别仍然很重要,理解了它才能理解这些系统的工作机制。
何况,即便有 HTAP,把事务系统与分析系统分开仍然很常见,原因在于两者的目标与需求不同。具体而言,让每个运营系统都拥有自己的数据库被视为良好实践(参见"微服务与无服务器",第 21 页),由此可能产生数百个相互独立的运营数据库;与此同时,企业通常只设一个数据仓库,以便业务分析师在一次查询中整合多个运营系统的数据。
由此可见,HTAP 并不会取代数据仓库。相反,它适用于这样一类应用:同一个应用既需要扫描大量行的分析查询,又需要以低延迟读写单条记录。例如,欺诈检测就可能涉及这种工作负载 [10]。
运营系统与分析系统的分离,是一种更广泛趋势的一部分。随着工作负载越来越苛刻,系统也变得越来越专业化,针对特定负载做优化。通用型系统在小数据量下游刃有余,但规模越大,专用系统就越占上风 [11]。
从数据仓库到数据湖
数据仓库通常采用关系型数据模型,借由 SQL 查询(参见第 3 章),有时配合专门的 BI 软件。这种模型很适合业务分析师所做的查询类型,但对从事以下任务的数据科学家就不太合身:
- 把数据转化为适合训练 ML 模型的形态。这通常需要把数据库表的行与列变成由数值组成的向量或矩阵——称为特征。这一转换过程要做到能让训练出的模型性能最大化,称为特征工程;它通常需要难以用 SQL 表达的定制代码。
- 对文本数据使用自然语言处理(NLP)技术,从中提取结构化信息(例如某条产品评论中作者的情感、所提到的人或主题)。同样,数据科学家可能需要借助计算机视觉技术从照片中抽取结构化信息。
虽然有人尝试为 SQL 数据模型加入 ML 算子 [12],也有人在关系型基础上构建高效的 ML 系统 [13],但许多数据科学家更倾向于不在数据仓库这样的关系数据库里工作。他们更愿意使用 Pandas、scikit-learn 等 Python 数据分析库,R 等统计分析语言,或 Spark 等分布式分析框架 [14]。我们在"DataFrame、矩阵与数组"(第 105 页)中会进一步讨论它们。
因此,组织面临一个需求:把数据以适合数据科学家使用的形式提供出来。答案是数据湖(data lake):一个集中式的数据仓库,存放任何可能对分析有用的数据副本,这些数据通过 ETL 从运营系统获取。数据湖与数据仓库的差别在于:数据湖只是存放文件,并不强加任何特定的文件格式、数据模型或模式 [15]。数据湖中的文件可能是以 Avro 或 Parquet 等格式编码的数据库记录集合(参见第 5 章),但也可以装下文本、图像、视频、传感器读数、稀疏矩阵、特征向量、基因组序列,乃至任何其他类型的数据 [16]。除了更灵活,数据湖通常也比关系型数据存储更便宜,因为它可以使用对象存储这种通用文件存储(参见"云原生系统架构",第 14 页)。
ETL 流程已被推广为数据流水线(data pipelines);某些情况下,数据湖会成为运营系统通往数据仓库这条路上的一个中间站。数据湖中的数据保持运营系统产生的"原始(raw)"形态,未被转换为关系型数据仓库的模式。这种做法的好处在于:每个数据消费者都可以将原始数据转换成最适合自己需求的形态。这有时被称为寿司原则:原始数据更好 [17]。
数据湖之外
随着分析实践日趋成熟,组织开始越来越重视分析系统与数据流水线的管理与运维,例如《DataOps 宣言》[18] 中所体现的那样。这一趋势的部分推动力来自治理、隐私与合规问题——如《通用数据保护条例》(GDPR)和《加州消费者隐私法案》(CCPA)等法规——我们将在"数据系统、法律与社会"(第 24 页)以及第 14 章中讨论。
另一项重要因素是:用于分析的数据越来越不只是以文件与关系型表的形式呈现,而是以事件流的形式呈现(参见第 12 章)。在基于文件的数据分析中,你可以周期性地(如每日)重跑分析以响应数据变化;而流处理则允许分析系统对事件做出快得多的反应——以秒计。视应用与时效性要求而定,流处理可能很有价值,比如用于识别并阻断潜在的欺诈或滥用活动。
在某些情况下,分析系统的产出会被反过来提供给运营系统使用(这一过程有时称为反向 ETL,reverse ETL)[19]。例如,在分析系统中训练好的 ML 模型可能被部署到生产环境,为最终用户生成"购买了 X 的人也购买了 Y"这类推荐。把机器学习模型部署到运营系统的工作,可借助 TFX、Kubeflow 或 MLflow 等专门工具完成。
真实数据源与派生数据
与运营系统和分析系统的区分相关,本书还区分真实数据源(systems of record)与派生数据系统(derived data systems)。这两个术语很有用,因为它们有助于厘清数据在系统中的流向:
真实数据源 :真实数据源——也称为真相之源(source of truth)——保存着数据的权威版本或正典版本。每当有新数据进入(例如以用户输入的形式),都会先写到这里。每个事实只被表示一次(这种表示通常是规范化的;参见"规范化、反规范化与连接",第 72 页)。如果其他系统与真实数据源之间出现任何不一致,按定义以真实数据源为准。
派生数据系统 :派生数据系统中的数据,是把另一个系统的现有数据拿来做某种转换或处理后的结果。如果你丢失了派生数据,可以从原始来源把它重新生成出来。一个典型例子是缓存:数据若已在缓存中,则直接由缓存返回;若不在,则回退到底层数据库。反规范化的值、索引、物化视图、经转换的数据表示,以及在某数据集上训练出的模型,都属于这一类。
严格来讲,派生数据是冗余的,因为它复制了已有信息。但这种数据通常是获得读取性能的关键。你可以从单一来源派生出多个数据集,从而能从不同视角审视数据。
分析系统通常就是派生数据系统,因为它们消费的是别处所产生的数据。运营服务可能同时包含真实数据源与派生数据系统:真实数据源是数据最先被写入的主数据库,派生数据系统则是用以加速常见读取的索引与缓存——尤其是针对真实数据源无法高效回答的查询。
大多数数据库、存储引擎与查询语言本质上既不是真实数据源,也不是派生数据系统。数据库只是一个工具;它怎么用,由你决定。某份数据是真实数据源还是派生数据,并不取决于工具,而取决于你在应用中如何使用它。把"哪份数据是从另一份数据派生而来"这件事想清楚,就能让原本含糊不清的系统架构变得条理分明。
当一个系统中的数据是从另一系统的数据派生而来时,你需要一套流程:当原始数据在真实数据源中变更时,更新派生数据。遗憾的是,许多数据库假设你的应用始终只使用唯一一个数据库,并未让"整合多个系统以传播这类更新"变得容易。在第 11 章我们会讨论作为数据集成手段的数据流水线,它让我们能把多个数据系统组合在一起,做到任一系统单独所无法做到的事。
至此,对分析与事务处理的对比就告一段落。下一节我们将考察另一种你大概早已多次见到争论的取舍。
云 vs 自托管
每当组织要做某件事,最先要回答的问题之一就是:该自己做,还是外包?换言之——你是要自建,还是要购买?
归根结底,这是一个业务优先级问题。一条常见经验是:属于本组织核心能力或竞争优势的事应当在内部自己做,而非核心、例行或司空见惯的事则交给供应商 [20]。举一个极端的例子:大多数公司并不自己造 CPU,因为从半导体厂商买来更便宜。
对于软件而言,需要做两个重要决定:谁来构建软件,以及谁来部署它。可能性的全谱见图 1-2。一端是你自己写、自己跑的定制软件;另一端是被广泛使用的云服务或 SaaS 产品——由外部供应商实现并运营,你只通过 Web 界面或 API 访问它。

图 1-2. 关于软件及其运维方式的外包决策谱
图示文字描述: 图示从左到右是一条横向坐标轴:"内部自有软件,内部运维(如应用代码)"——"现成软件,内部运维(如在 IaaS 上自托管数据库)"——"现成软件,外包运维(如云服务/SaaS)"。轴下两端分别注:"控制更多,投入更大" 与 "控制更少,投入更小"。
中间地带是你自托管——也就是自行部署的现成软件(开源或商业版)——例如下载 MySQL,把它装在你能控制的服务器上。这台服务器可能是你自己的硬件(通常称为本地,on premises,即便它实际上待在租来的数据中心机柜里、并不真正在你自家),也可能是云中的虚拟机(VM)(即基础设施即服务,IaaS)。这条谱线上还有更多落点,比如把开源软件拿来跑一份修改过的版本。
另一个相关问题是:你要怎样部署服务,无论是在云中还是本地——例如要不要使用 Kubernetes 这样的编排框架。然而部署工具的选择不在本书讨论范围之内,因为还有其他因素对数据系统架构的影响更大。
云服务的优劣
使用云服务,相比自己运行同类软件,本质上就是把这套软件的运营外包给云提供商。围绕这种做法既有支持的论点,也有反对的论点。云提供商声称:使用他们的服务能让你节省时间与成本,且比自建基础设施更易于快速推进。
不过,云服务到底是不是真的比自托管更便宜、更省事,很大程度上取决于你的技能水平与系统所承载的工作负载。如果你已经有部署与运维所需系统的经验,且负载相当可预测(即所需机器数量不会剧烈波动),那么自购机器并自己运行软件往往更划算 [21, 22]。
另一方面,如果你需要的某个系统你还不会部署与运维,采用云服务往往比从头学着把它管理起来更轻松、更快。专门为该系统招聘并培养运维人员可能很贵。即便你已身处云上,仍然需要一支运维团队(参见"云时代的运营",第 17 页);但把基础系统管理外包出去,可以让团队腾出精力去关注更高层的事。
把一个系统的运营外包给一家专门运营它的公司,可能带来更优质的服务,因为这家提供商通过为众多客户运营该服务而积累出运维专长。另一方面,如果你自己跑这个服务,就可以针对你这一具体的工作负载进行配置与调优;云服务大概不会替你做这种定制。
当系统负载随时间剧烈波动时,云服务尤其有价值。如果你按峰值负载预先配置机器,但这些资源在大部分时间里都闲置着,系统的成本效益就会很差。这种场景下,云服务的优势在于能根据需求变化更轻松地纵向扩缩资源。
例如,分析系统的负载常常变化极大。一次大型分析查询要在短时间内完成,需要大量计算资源并行;但查询一结束,资源就闲在那里等下一次查询。预先排好的查询(如每日报表)可以用排队和调度把负载削平,但若是交互式查询,希望它们越快返回越好,工作负载就越多变。当数据集大到一次查询就要消耗大量计算资源时,使用云能省钱——因为你可以把不再需要的资源还给云提供商,而不是让它们空转。对小数据集而言,这种差别就没那么明显。
云服务最大的劣势是你对它几乎没有控制权:
- 如果它缺少你需要的某个特性,你能做的就是礼貌地询问厂商是否会增加;通常你无法自己实现。
- 如果服务挂了,你能做的只有等它恢复。
- 如果你以某种方式触发了一个 bug 或导致性能问题,要诊断会很困难。换作你自己跑的软件,你可以从操作系统获取性能指标与调试信息以了解其行为,也可以查看服务器日志;而由厂商托管的服务通常不让你访问这些内部信息。
- 如果服务停运、贵到不可接受,或者厂商把产品改成你不喜欢的样子,你就只能任其摆布;继续运行旧版本通常并不可行,于是你只得迁移到替代服务 [23]。如果替代服务暴露兼容的 API,这种风险会有所缓解;但许多云服务并没有标准 API,切换成本很高,由此带来厂商锁定问题。
- 若云服务商位于另一国,而该国与你所在国发生政治冲突,你可能因受制裁而被排除在服务之外。
- 必须信任云提供商替你保护数据安全,这可能让满足隐私与安全法规的过程变得更复杂。
尽管存在这些风险,越来越多组织选择在云服务之上构建新应用,或采用混合方式——某些方面用云服务、其他方面自己做。但云服务并不会吞并所有内部数据系统。许多老系统的诞生早于云的出现;而当现有云服务无法满足某些特殊需求时,内部系统仍然必要。例如对延迟极敏感的应用——如高频交易——需要对硬件拥有完全的控制权。
云原生系统架构
云的兴起除了带来不同的经济模型(订阅服务,而不是买硬件再为其授权软件)外,对数据系统在技术层面的实现方式也产生了深远影响。*云原生(cloud native)*一词用来描述那种为充分利用云服务而设计的架构。
原则上,几乎所有可自托管的软件也都能以云服务的形式提供,事实上许多流行的数据系统如今都有这样的托管服务。然而,那些从一开始就被设计为云原生的系统已被证明拥有若干优势:在同等硬件上性能更好、从故障中恢复更快、能迅速纵向扩缩计算资源以匹配负载,并能支撑更大规模的数据集 [24, 25, 26]。表 1-2 列举了两类系统的若干例子。
表 1-2. 自托管与云原生数据库系统示例
| 类别 | 自托管系统 | 云原生系统 |
|---|---|---|
| 运营/OLTP | MySQL、PostgreSQL、MongoDB | AWS Aurora [24]、Azure SQL DB Hyperscale [25]、Google Cloud Spanner |
| 分析/OLAP | Teradata、ClickHouse、Spark | Snowflake [26]、Google BigQuery、Azure Synapse Analytics |
云服务的分层
许多自托管数据系统对系统环境的要求很简单:它们运行在 Linux 或 Windows 这样的常规操作系统之上,以文件形式把数据存到文件系统里,使用 TCP/IP 等标准网络协议通信。少数系统会依赖特殊硬件,例如 GPU(用于 ML)或远程直接内存访问(RDMA)网络接口;但总体而言,自托管软件大多使用通用计算资源——CPU、RAM、文件系统与 IP 网络。
在云中,这类软件可以跑在 IaaS 环境里——使用一台或多台具有指定 CPU、内存、磁盘、网络带宽的 VM(即实例,instances)。与物理机相比,云实例可以更快地配齐,规格档位也更丰富,但从其他角度看仍像传统计算机:你可以在上面跑任意软件,但运维的责任在你。
相比之下,云原生服务的关键思路不仅是使用操作系统所管理的计算资源,更在于在低层云服务之上构建更高层的服务。例如:
- Amazon S3、Azure Blob Storage、Cloudflare R2 等对象存储服务用来存放大文件。它们的 API 比典型文件系统更受限(仅有基本的文件读写),但好处是隐藏了底层的物理机器;服务会自动把数据分布到多台机器上,让你不必担心某台机器的磁盘空间会耗尽。即便部分机器或其磁盘整体失效,也不会丢失数据。
- 许多其他服务又建立在对象存储与其他云服务之上。例如 Snowflake 是一种基于云的分析数据库(数据仓库),其数据存储依赖 S3 [26];还有一些服务又建立在 Snowflake 之上。
如同计算中所有抽象一样,使用哪一种并无单一正确答案。一般而言,越高层的抽象越倾向于聚焦特定用例。如果你的需求恰好与某个高层系统所设计的场景相符,使用既有高层系统通常远比从更底层组件自己拼起来省事。反过来,如果没有任何高层系统满足你的需求,自下而上自己搭建就是唯一的选择。
存储与计算的分离
在传统计算中,磁盘存储被视作持久的(我们假设一旦写入磁盘便不会丢失)。为了容忍单块硬盘故障,常用 RAID(独立磁盘冗余阵列)在挂在同一机器上的多块磁盘之间维护数据副本。RAID 可以由硬件实现,也可以由操作系统在软件中实现,对访问文件系统的应用是透明的。
而在云中,计算实例(VM)虽然也可以挂载本地磁盘,但云原生系统通常把这些本地盘当作"短命缓存"使用,很少把它们当作长期存储。原因在于:若所属实例失败,本地盘便不再可访问;若实例为适应负载变化而被替换为更大或更小的另一台(位于不同物理机上),本地盘也会消失。
作为本地磁盘的替代,云服务还提供虚拟磁盘存储——它可以从一个实例上分离、再挂载到另一个实例(如 Amazon EBS、Azure 托管磁盘、Google Cloud 持久盘)。这种虚拟盘并非真实的物理盘,而是一种由独立机群提供的云服务,用以模拟磁盘的行为(一种块设备,每个块通常 4 KiB)。这一技术让传统的基于磁盘的软件得以在云中运行,但块设备模拟引入了开销,而那些一开始就为云设计的系统则能避开这种开销 [24]。使用虚拟盘还会让应用对网络抖动非常敏感,因为对虚拟块设备的每一次 I/O 都是一次网络调用 [27]。
为了解决这个问题,云原生服务通常避开虚拟盘,而是构建在面向特定工作负载优化的专用存储服务之上。S3 这类对象存储服务被设计用于长期存放体积较大的文件,从数百 KB 到数 GB 不等。数据库中保存的单行或单值通常远比这小;因此云数据库通常用一项独立服务来管理较小的值,把较大的数据块(包含许多单值)存到对象存储中 [25, 28]。我们将在第 4 章看到这种做法的具体形式。
在传统系统架构中,同一台计算机同时承担存储(磁盘)与计算(CPU 与 RAM);而在云原生系统中,这两项职责在某种程度上被拆开——即解耦(disaggregated) [9, 26, 29, 30]:例如 S3 只负责存文件,要分析这些数据就得把分析代码运行在 S3 之外的某处。这意味着数据需经网络传输——这一点我们在"分布式系统 vs 单节点系统"(第 19 页)中会进一步讨论。
此外,云原生系统通常是*多租户(multitenant)*的:与其为每个客户准备一台独立机器,不如让一项服务在同一份共享硬件上同时处理多个客户的数据与计算 [31]。多租户能带来更高的硬件利用率、更轻松的扩缩、对云提供商更便利的管理,但同时也要求精心的工程设计,以确保某个客户的活动不会影响其他客户在该系统上的性能或安全 [32]。
云时代的运营
传统上,组织中负责服务器端数据基础设施的人被称为数据库管理员(DBA)或系统管理员(sysadmin)。近来许多组织尝试把软件开发与运营整合到同一团队,让团队既负责后端服务也负责数据基础设施;推动这一趋势的理念是DevOps。Google 的*站点可靠性工程师(SRE)*正是这一思路的具体实现 [33]。
运营的角色在于确保服务可靠地交付给用户(包括配置基础设施、部署应用),并维护一个稳定的生产环境(包括监控并诊断任何可能影响可靠性的问题)。对于自托管系统,运营传统上要在单机粒度上做大量工作,例如做容量规划(如监控可用磁盘空间、在用尽前再加盘)、配置新机器、把服务从一台机器迁到另一台、安装操作系统补丁。
许多云服务以 API 的形式呈现,把背后实现这些服务的具体机器隐藏起来。例如,云存储以按量计费取代了固定大小的磁盘——你无需提前规划容量就可以存数据,按使用量计费。此外,许多云服务即便单台机器失效,整个服务仍能保持高可用(参见"可靠性与容错",第 43 页)。
这种重心从单机到服务的转变也带来了运营角色的转变。提供可靠服务这一高层目标没有变,但流程与工具已经演化。
DevOps/SRE 理念更强调以下方面:
- 建立自动化,以可重复的流程替代手工的一次性操作
- 使用短命的 VM 与服务,而不是长期运行的服务器
- 支持频繁的应用更新
- 从故障事件中学习
- 把组织对系统的理解保留下来,即便具体人员来来去去 [34]
随着云服务兴起,运营角色出现了分化。基础设施厂商的运营团队专注于把可靠服务提供给大量客户的方方面面,而服务的客户则希望在基础设施上尽可能少花时间与精力 [35]。
云服务的客户仍然需要做运营,但侧重点不同:例如为某项任务挑选最合适的服务、把多个服务集成起来、从一项服务迁到另一项。即便按量计费消除了传统意义上的容量规划需求,了解你究竟在用哪些资源、为何而用仍然重要,免得在用不到的云资源上浪费钱。容量规划变成了财务规划,性能优化变成了成本优化 [36]。此外,云服务确实存在资源限额或配额(quotas)(如可同时运行的最大进程数),你需要在撞到天花板之前就了解并规划好它们 [37]。
采用云服务可以比自建基础设施更轻松、更迅速,但你仍需学会如何使用云服务——可能还要绕开它们的种种限制。各服务之间的集成是一项特别的挑战,因为越来越多的厂商提供面向不同用例的越来越多云服务 [38, 39]。ETL(参见"数据仓库",第 7 页)只是故事的一部分;运营性的云服务彼此之间也需要集成。目前还缺乏便于这种集成的标准,因此通常需要大量手工工作。
其他无法完全外包给云服务的运营事项还包括:维护应用及其所用类库的安全、管理自家服务之间的交互、监控自家服务的负载,以及追查性能下降或停机等问题的根因。云在改变运营的角色,但对运营的需求一如既往强烈。
分布式系统 vs 单节点系统
涉及若干通过网络通信的机器的系统称为分布式系统。分布式系统中参与的每个进程都称为一个节点。你可能出于各种原因想使用这种系统:
天生分布 :如果一个应用涉及两个或更多互动用户,各自使用自己的设备,那么这个系统不可避免地是分布式的——设备之间的通信必须经由网络发生。
云服务之间的请求 :如果数据存放在一项服务里,却由另一项服务来处理,那这份数据必须通过网络从一项服务传到另一项。云原生系统与微服务(参见"微服务与无服务器",第 21 页)因此都是分布式的。
容错/高可用 :如果你的应用即便在一台机器(或几台机器、网络、乃至整座数据中心)下线时也要继续工作,就可以用多台机器获得冗余。当一台失效时,由另一台接管。参见"可靠性与容错"(第 43 页)以及第 6 章。
可扩展性 :当你的数据量或计算需求大到一台机器装不下时,可以把负载分散到多台机器上。参见"可扩展性"(第 49 页)。
延迟 :如果你的用户遍布全球,你也许希望在世界多个区域都设置服务器,让每位用户都能由地理上离自己最近的服务器提供服务。这避免了请求的网络包要绕半个地球。参见"描述性能"(第 37 页)。
弹性 :如果你的应用时而忙时而闲,云部署可以按需纵向扩缩,让你只为正在使用的资源付费。这在单台机器上就更难做到——为承载峰值负载得按峰值配置,即便大部分时段它几乎闲着也得保留。
专用硬件 :系统中不同部分可以使用不同类型的硬件,以匹配各自的负载。例如,对象存储可能使用磁盘多但 CPU 少的机器;数据分析系统可能使用 CPU 与内存充足但无磁盘的机器;机器学习系统可能使用配 GPU 的机器(对于训练深度神经网络等 ML 任务,GPU 远比 CPU 高效)。
法律合规 :有些国家有数据驻留法,要求其辖区内居民的相关数据必须存储和处理在该国境内 [40]。这类规则的范围各异——例如有时仅适用于医疗或金融数据,有时则更宽。一项服务若用户分布在多个此类辖区,就必须把数据分散到多地服务器上。
可持续性 :如果你对作业的运行地点与时间有一定灵活性,就可以选择在有大量可再生电力的时段与地点运行,在电网紧张时避免运行。这能减少碳排放,也让你能在便宜电力可用时把它用起来 [41, 42]。
这些理由对你自己写的服务(应用代码)和由现成软件(如数据库)构成的服务都同样适用。
分布式系统的麻烦
分布式系统也有缺点。每一个跨网络的请求与 API 调用都要面对失败的可能。网络可能被中断,服务可能过载或崩溃,因此任何请求都可能在没收到响应时超时。这种情况下,我们不知道服务是否收到了请求,而简单地重试也可能并不安全。我们会在第 9 章详细讨论这些问题。
虽然数据中心网络很快,但调用另一个服务仍远慢于在同一进程内调用一个函数 [43]。处理大数据量时,与其把数据从存储传到另一台机器去处理,不如把计算搬到已经持有数据的那台机器上——这样更快 [44]。节点更多并不总意味着更快——某些情况下,一台计算机上的简单单线程程序可以显著优于一个超过 100 核的集群 [45]。
排查分布式系统通常很困难——若系统响应慢,你怎么找出问题在哪?为此而生的诊断手段被归为可观测性(observability) [46, 47],它通过收集系统运行时产生的数据,让我们能以高层指标与单事件细节两种方式去查询。OpenTelemetry、Zipkin、Jaeger 等追踪工具让你能够追踪:哪个客户端为哪次操作调用了哪台服务器、每次调用花了多长时间 [48]。
数据库提供了多种保证数据一致性的机制,我们将在第 6 章与第 8 章中介绍。然而,当每个服务都有自己独立的数据库时,跨服务维护数据一致性就成了应用自身的问题。第 8 章会讨论的分布式事务是保证一致性的一种可能方法,但在微服务架构中很少被使用——因为它与"让服务之间彼此独立"的目标背道而驰,且许多数据库并不支持它 [49]。
正因如此,把任务放在一台机器上完成,往往比搭建一个分布式系统简单得多、便宜得多 [22, 45, 50]。CPU、内存与磁盘已变得越来越大、越快、越可靠。结合 DuckDB、SQLite、KùzuDB 等单节点数据库,许多工作负载如今都能在单一节点上运行。我们将在第 4 章中进一步探讨这一主题。
微服务与无服务器
把一个系统分散到多台机器上的最常见方式,是把它划分为客户端与服务端,让客户端向服务端发请求。承载这种通信最常用的协议是 HTTP——我们会在"通过服务的数据流:REST 与 RPC"(第 180 页)中讨论。同一个进程既可以是服务端(处理传入请求),也可以是客户端(发出对其他服务的请求)。
这种构建应用的方式传统上称为面向服务的架构(SOA);近年来这一思想被精炼为微服务架构(microservices architecture) [51, 52]。在微服务架构中,每个服务都有一个明确界定的目的(例如对 S3 而言是文件存储);每个服务对外暴露可由客户端通过网络调用的 API;每个服务由一支团队负责维护。一个复杂的应用因此可被分解为多个相互交互的服务,每个由各自的团队管理。云原生系统大量使用这种"分解为服务"的做法,但本地部署的系统也可以采用面向服务的方法。
把一个复杂软件分割成多个服务有几个好处:每个服务可独立更新,从而减少团队间的协调成本;每个服务可分配它所需的硬件资源;并且把实现细节藏在 API 之后,意味着服务的所有者可以在不影响客户端的前提下自由修改实现。在数据存储方面,常见做法是每个服务都拥有自己的数据库,而不在服务之间共享数据库。共享数据库实际上会让整个数据库结构成为该服务 API 的一部分,那么这个结构就变得难以更改。共享数据库还可能让一个服务的查询拖累其他服务的性能。
另一方面,拥有许多服务本身也会带来复杂度。开发期间测试一个服务可能很麻烦,因为还得把它依赖的所有其他服务也跑起来。更重要的是,每个服务都需要部署新版本、按负载调整分配的硬件资源、收集日志、监控服务健康状况、在出问题时呼叫值班工程师等等基础设施。Kubernetes 等编排框架因为为这类基础设施提供了基础,已成为部署服务的常见方式。
此外,微服务的 API 演化也颇具挑战。调用某个 API 的客户端会期望它具有特定的字段。开发者可能希望随业务需要在 API 中增删字段,但这样做可能让客户端崩坏。更糟的是,这种崩坏常常直到开发周期后段——更新后的服务 API 被部署到预发或生产环境时——才被发现。OpenAPI 与 gRPC 等 API 描述标准能帮助管理客户端与服务端 API 之间的关系;我们将在第 5 章中进一步讨论。
微服务主要是对一种"人的问题"所提出的技术解决方案:让不同团队不必相互协调即可独立推进。这在大公司里很有价值,但在团队规模较小的小公司里,使用微服务很可能是不必要的开销,以最简单的方式实现应用反而是更好的选择 [51]。
无服务器(Serverless)——或称函数即服务(FaaS)——是另一种部署服务的方式:把基础设施的管理外包给云供应商 [32]。使用 VM 时,你必须显式选择何时启动或关停实例;而在无服务器模型下,云提供商会根据到来的请求自动分配与释放硬件资源 [53]。正如云存储以按量计费取代了容量规划(提前决定要买多少磁盘),无服务器把按量计费带到了代码执行层面:你只为应用代码实际运行的时间付费,而不必提前预置资源。
为了提供这种好处,许多无服务器基础设施供应商对函数的执行时间设置了上限,并对运行时环境作了限制;此外,当一个函数首次被调用时,服务可能因冷启动而变慢。"无服务器"这个名字也可能引起误解:每次无服务器函数的执行仍然在某台服务器上运行,只不过下一次执行可能在另一台。此外,BigQuery 与各种 Kafka 服务等基础设施服务也采用了"无服务器"这一术语,用以表明它们的服务会自动扩缩,并按用量计费,而非按机器实例计费。
云计算 vs 超级计算
云计算并不是构建大规模计算系统的唯一方式;另一种途径是高性能计算(HPC),也称超级计算。虽然两者有交集,但 HPC 的优先级与所采用的技术常常不同于云计算和企业数据中心系统。下面是几项主要差别:
- 超级计算机通常用于计算密集的科学计算任务,如气象预报、气候建模、分子动力学(模拟原子与分子的运动)、复杂优化问题,以及求解偏微分方程。云计算则更倾向于在线服务、业务数据系统及类似系统——它们需要以高可用性服务用户请求。
- 超级计算机通常运行大型批作业,作业会不时把计算状态写入磁盘做检查点(checkpoint)。当一个节点失效时,常见做法是把整个集群停下来、修复故障节点、再从最近一次检查点重启计算 [54, 55]。在云服务中,让整个集群停下来通常并不可取,因为服务必须以尽可能少的中断持续为用户提供。
- 超级计算机的节点通常通过共享内存与 RDMA 通信,二者支持高带宽、低延迟,但假设系统使用者之间存在高度信任 [56]。在云计算中,网络与机器常被互不信任的组织共享,需要更强的安全机制——例如资源隔离(如虚拟机)、加密与认证。
- 云数据中心网络通常基于 IP 与以太网,按 Clos 拓扑布设以提供高对分带宽(bisection bandwidth)——这是衡量网络整体性能的常用指标 [54, 57]。超级计算机往往使用专门的网络拓扑,如多维网格与环面(torus)[58],能在通信模式已知的 HPC 工作负载上获得更好的性能。
- 云计算允许节点跨多个地理区域分布,而超级计算机一般假定其全部节点在物理上聚集在一起。
大型分析系统有时与超级计算共享某些特征,因此若你工作在该领域,了解这些技术也会有帮助。但本书主要关注那些必须持续可用的服务,"可靠性与容错"(第 43 页)会进一步讨论。
数据系统、法律与社会
正如本章所见,数据系统的架构不仅受技术目标与需求的影响,也受其所服务组织中"人的需要"的影响。数据系统工程师越来越意识到:仅仅满足自家公司的需求是不够的;我们对整个社会同样负有责任。
一类特别值得关注的问题,是那些存放与人本身及其行为相关数据的系统。自 2018 年以来,GDPR 让许多欧洲国家的居民对其个人数据拥有了更大的控制权与法律权利;类似的隐私法规已在世界其他国家与地区被采纳(例如 CCPA)。围绕 AI 的法规——如欧盟《人工智能法案》(EU AI Act)——则对个人数据可被如何使用施加了进一步的限制。
此外,即便在并未直接受监管的领域,人们也越来越意识到计算机系统对人与社会的影响。社交媒体改变了人们消费新闻的方式,进而影响其政治观点,乃至选举结果。自动化系统越来越频繁地做出对个人产生深远后果的决策——比如谁该获得贷款或保险、谁该被邀请来面试、谁该被视为犯罪嫌疑人 [59]。
在这类系统上工作的每个人,都共担一份责任:思考自身决策带来的伦理影响,并确保它们遵守相关法律。并不是每个人都得成为法律与伦理专家,但对法律与伦理原则有基本的认识,就和掌握分布式系统的某些基础知识一样重要。
法律考量正在影响数据系统设计最底层的决定 [60]。例如,GDPR 赋予个人在请求时删除其个人数据的权利(有时称为被遗忘权)。然而正如本书将看到的,许多数据系统的设计依赖于不可变结构,例如仅追加日志(append-only logs)。我们如何能从一个本应不可变的文件中删除某些数据?又如何处理那些已被纳入派生数据集(参见"真实数据源与派生数据",第 10 页)——例如 ML 模型训练数据——的数据的删除?回答这些问题催生了新的工程挑战。
目前,对于哪些具体技术或系统架构应当被视为"GDPR 合规",我们还没有清晰的指引。该法规刻意没有规定具体技术,因为技术可能随时演进而迅速变化。法律文本设定的是高层原则,需要经过解释。因此,如何遵守隐私法规并无简单答案,但本书将尝试以这一视角审视一些技术。
一般而言,我们之所以存储数据,是因为我们认为其价值大于存储成本。但值得记住的是:存储成本不止于你付给 S3 或其他服务的账单。成本-收益的核算还应把以下风险纳入考虑:数据被对手泄露或篡改时所带来的责任与声誉损失;以及若数据的存储与处理被发现违法所带来的法律成本与罚款 [50]。
政府或警方也可能强制要求公司交出数据。当数据可能揭露被视作犯罪的行为(例如某些中东与非洲国家中的同性恋行为,或美国某些州中的堕胎行为)时,存储这类数据会给用户带来真实的安全风险。例如前往一家堕胎诊所的行程,很容易通过位置数据被揭露——甚至可能仅靠用户 IP 地址随时间的日志(其中蕴含大致位置)就能推出来。
把全部风险纳入考量后,合理的结论可能是:有些数据干脆不值得存储,因此应予删除。这一原则——有时以德语术语 Datensparsamkeit(数据节俭)著称——与"大数据"哲学(先把大量数据存起来,万一以后有用呢)背道而驰 [61]。但数据节俭与 GDPR 的精神相符:GDPR 规定个人数据只能为特定、明确目的而收集;不得日后另作他用;不得保留超过收集目的所必需的时长 [62]。
商业领域同样开始重视隐私与安全问题。信用卡公司要求支付处理商遵循严格的支付卡行业(PCI)标准。处理机构会接受独立审计的频繁评估,以验证持续合规。软件供应商也面临更严格的审视;许多买家如今要求其供应商遵循 Service Organization Control(SOC)Type 2 标准。与 PCI 合规一样,供应商也需接受第三方审计以核实合规性。
总体而言,重要的是在你的业务需求与你正在收集和处理其数据的人的需求之间取得平衡。这一话题还有更多内容;第 14 章会更深入地讨论伦理与法律合规,包括偏见与歧视问题。
小结
本章的主题是理解权衡——也就是认识到许多问题并没有唯一正确的答案,而是有几种可能性、各自都有优劣。我们考察了影响数据系统架构的若干最重要的选择,并引入了贯穿全书的术语。
我们首先区分了运营(事务处理,OLTP)与分析(OLAP)系统,并考察了它们的差异:不仅在于管理具有不同访问模式的不同类型数据,也在于服务的对象不同。沿途我们遇到了"数据仓库"与"数据湖"的概念——它们经由 ETL 接收来自运营系统的数据。在第 4 章我们会看到,运营系统与分析系统由于需要服务的查询类型不同,所采用的内部数据布局也大相径庭。
随后我们把云服务这一相对新近的现象,与长期主导数据系统架构的传统自托管软件范式作了比较。哪种方法在成本上更优,很大程度上取决于你的具体处境,但毋庸置疑的是,云原生的做法正给数据系统架构带来巨大变化——例如它们如何把存储与计算分离开来。
云系统天生是分布式的,我们也简略考察了相对于单机而言的若干分布式系统取舍。某些情形下你无法避开分布式,但只要还能让系统留在单机上,就最好不要急于走上分布式之路。第 9 章将更详细地讨论分布式系统所面临的挑战。
最后,我们看到数据系统的架构不仅由部署该系统的业务需求决定,也受保护被处理者权利的隐私法规影响——这是许多工程师容易忽略的一面。如何把法律要求转化为技术实现尚未被形式化,但在本书后续部分中,把这一问题持续放在心里十分重要。
参考文献
[1] Richard T. Kouzes, Gordon A. Anderson, Stephen T. Elbert, Ian Gorton, Deborah K. Gracio. "The Changing Paradigm of Data-Intensive Computing." IEEE Computer, volume 42, issue 1, pages 26–34, January 2009.
[2] Martin Kleppmann, Adam Wiggins, Peter van Hardenberg, Mark McGranaghan. "Local-First Software: You Own Your Data, in Spite of the Cloud." At 2019 ACM SIGPLAN International Symposium on New Ideas, New Paradigms, and Reflections on Programming and Software (Onward!), October 2019.
[3] Joe Reis and Matt Housley. Fundamentals of Data Engineering. O'Reilly Media, 2022. ISBN: 9781098108304
[4] Rui Pedro Machado and Helder Russa. Analytics Engineering with SQL and dbt. O'Reilly Media, 2023. ISBN: 9781098142384
[5] Edgar F. Codd, S. B. Codd, C. T. Salley. "Providing OLAP to User-Analysts: An IT Mandate." E. F. Codd Associates, 1993. 归档于 perma.cc/RKX8-2GEE
[6] Chinmay Soman, Neha Pawar. "Comparing Three Real-Time OLAP Databases: Apache Pinot, Apache Druid, and ClickHouse." startree.ai, April 2023. 归档于 perma.cc/8BZP-VWPA
[7] Surajit Chaudhuri, Umeshwar Dayal. "An Overview of Data Warehousing and OLAP Technology." ACM SIGMOD Record, volume 26, issue 1, pages 65–74, March 1997.
[8] Fatma Özcan, Yuanyuan Tian, Pinar Tözün. "Hybrid Transactional/Analytical Processing: A Survey." At ACM International Conference on Management of Data (SIGMOD), May 2017.
[9] Adam Prout, Szu-Po Wang, Joseph Victor 等。"Cloud-Native Transactions and Analytics in SingleStore." At International Conference on Management of Data (SIGMOD), June 2022.
[10] Chao Zhang, Guoliang Li, Jintao Zhang, Xinning Zhang, Jianhua Feng. "HTAP Databases: A Survey." IEEE Transactions on Knowledge and Data Engineering, volume 36, issue 11, pages 6410–6429, April 2024.
[11] Michael Stonebraker, Uğur Çetintemel. "'One Size Fits All': An Idea Whose Time Has Come and Gone." At 21st International Conference on Data Engineering (ICDE), April 2005.
[12] Jeffrey Cohen, Brian Dolan, Mark Dunlap, Joseph M. Hellerstein, Caleb Welton. "MAD Skills: New Analysis Practices for Big Data." Proceedings of the VLDB Endowment, volume 2, issue 2, pages 1481–1492, August 2009.
[13] Dan Olteanu. "The Relational Data Borg Is Learning." Proceedings of the VLDB Endowment, volume 13, issue 12, pages 3502–3515, August 2020.
[14] Matt Bornstein, Martin Casado, Jennifer Li. "Emerging Architectures for Modern Data Infrastructure: 2020." future.a16z.com, October 2020. 归档于 perma.cc/LF8W-KDCC
[15] Rihan Hai, Christos Koutras, Christoph Quix, Matthias Jarke. "Data Lakes: A Survey of Functions and Systems." IEEE Transactions on Knowledge and Data Engineering (TKDE), volume 35, issue 12, pages 12571–12590, December 2023.
[16] Martin Fowler. "Data Lake." martinfowler.com, February 2015. 归档于 perma.cc/4WKN-CZUK
[17] Bobby Johnson, Joseph Adler. "The Sushi Principle: Raw Data Is Better." At Strata+Hadoop World, February 2015.
[18] DataKitchen, Inc. "The DataOps Manifesto." dataopsmanifesto.org, 2017. 归档于 perma.cc/3F5N-FUQ4
[19] Tejas Manohar. "What Is Reverse ETL: A Definition & Why It's Taking Off." hightouch.io, November 2021. 归档于 perma.cc/A7TN-GLYJ
[20] Camille Fournier. "Why Is It So Hard to Decide to Buy?" skamille.medium.com, July 2021. 归档于 perma.cc/6VSG-HQ5X
[21] David Heinemeier Hansson. "Why We're Leaving the Cloud." world.hey.com, October 2022. 归档于 perma.cc/82E6-UJ65
[22] Nima Badizadegan. "Use One Big Server." specbranch.com, August 2022. 归档于 perma.cc/M8NB-95UK
[23] Steve Yegge. "Dear Google Cloud: Your Deprecation Policy Is Killing You." steve-yegge.medium.com, August 2020. 归档于 perma.cc/KQP9-SPGU
[24] Alexandre Verbitski 等。"Amazon Aurora: Design Considerations for High Throughput Cloud-Native Relational Databases." At ACM International Conference on Management of Data (SIGMOD), May 2017.
[25] Panagiotis Antonopoulos 等。"Socrates: The New SQL Server in the Cloud." At ACM International Conference on Management of Data (SIGMOD), June 2019.
[26] Midhul Vuppalapati, Justin Miron, Rachit Agarwal, Dan Truong, Ashish Motivala, Thierry Cruanes. "Building an Elastic Query Engine on Disaggregated Storage." At 17th USENIX Symposium on Networked Systems Design and Implementation (NSDI), February 2020.
[27] Nick Van Wiggeren. "The Real Failure Rate of EBS." planetscale.com, March 2025. 归档于 perma.cc/43CR-SAH5
[28] Colin Breck. "Predicting the Future of Distributed Systems." blog.colinbreck.com, August 2024. 归档于 perma.cc/K5FC-4XX2
[29] Gwen Shapira. "Compute-Storage Separation Explained." thenile.dev, January 2023. 归档于 perma.cc/QCV3-XJNZ
[30] Ravi Murthy, Gurmeet Goindi. "AlloyDB for PostgreSQL Under the Hood: Intelligent, Database-Aware Storage." cloud.google.com, May 2022. 归档于 archive.org
[31] Jack Vanlightly. "The Architecture of Serverless Data Systems." jack-vanlightly.com, November 2023. 归档于 perma.cc/UDV4-TNJ5
[32] Eric Jonas, Johann Schleier-Smith 等。"Cloud Programming Simplified: A Berkeley View on Serverless Computing." arXiv:1902.03383, February 2019.
[33] Betsy Beyer, Jennifer Petoff, Chris Jones, Niall Richard Murphy. Site Reliability Engineering: How Google Runs Production Systems. O'Reilly Media, 2016. ISBN: 9781491929214
[34] Thomas Limoncelli. "The Time I Stole $10,000 from Bell Labs." ACM Queue, volume 18, issue 5, November 2020.
[35] Charity Majors. "The Future of Ops Jobs." acloudguru.com, August 2020. 归档于 perma.cc/GRU2-CZG3
[36] Boris Cherkasky. "(Over)Pay as You Go for Your Datastore." medium.com, September 2021. 归档于 perma.cc/Q8TV-2AM2
[37] Shlomi Kushchi. "Serverless Doesn't Mean DevOpsLess or NoOps." thenewstack.io, February 2023. 归档于 perma.cc/3NJR-AYYU
[38] Erik Bernhardsson. "Storm in the Stratosphere: How the Cloud Will Be Reshuffled." erikbern.com, November 2021. 归档于 perma.cc/SYB2-99P3
[39] Benn Stancil. "The Data OS." benn.substack.com, September 2021. 归档于 perma.cc/WQ43-FHS6
[40] Maria Korolov. "Data Residency Laws Pushing Companies Toward Residency as a Service." csoonline.com, January 2022. 归档于 perma.cc/CHE4-XZZ2
[41] Severin Borenstein. "Can Data Centers Flex Their Power Demand?" energyathaas.wordpress.com, April 2025. 归档于 perma.cc/MUD3-A6FF
[42] Bilge Acun 等。"Carbon Dependencies in Datacenter Design and Management." ACM SIGENERGY Energy Informatics Review, volume 3, issue 3, pages 21–26, October 2023.
[43] Kousik Nath. "These Are the Numbers Every Computer Engineer Should Know." freecodecamp.org, September 2019. 归档于 perma.cc/RW73-36RL
[44] Joseph M. Hellerstein 等。"Serverless Computing: One Step Forward, Two Steps Back." arXiv:1812.03651, December 2018.
[45] Frank McSherry, Michael Isard, Derek G. Murray. "Scalability! But at What COST?" At 15th USENIX Workshop on Hot Topics in Operating Systems (HotOS), May 2015.
[46] Cindy Sridharan. Distributed Systems Observability: A Guide to Building Robust Systems. Report, O'Reilly Media, 2018. 归档于 perma.cc/M6JL-XKCM
[47] Charity Majors. "Observability—A 3-Year Retrospective." thenewstack.io, August 2019. 归档于 perma.cc/CG62-TJWL
[48] Benjamin H. Sigelman 等。"Dapper, a Large-Scale Distributed Systems Tracing Infrastructure." Google 技术报告 dapper-2010-1, April 2010. 归档于 perma.cc/K7KU-2TMH
[49] Rodrigo Laigner 等。"Data Management in Microservices: State of the Practice, Challenges, and Research Directions." Proceedings of the VLDB Endowment, volume 14, issue 13, pages 3348–3361, September 2021.
[50] Jordan Tigani. "Big Data Is Dead." motherduck.com, February 2023. 归档于 perma.cc/HT4Q-K77U
[51] Sam Newman. Building Microservices, 2nd edition. O'Reilly Media, 2021. ISBN: 9781492034025
[52] Chris Richardson. "Microservices: Decomposing Applications for Deployability and Scalability." infoq.com, May 2014. 归档于 perma.cc/CKN4-YEQ2
[53] Mohammad Shahrad 等。"Serverless in the Wild: Characterizing and Optimizing the Serverless Workload at a Large Cloud Provider." At USENIX Annual Technical Conference (ATC), July 2020.
[54] Luiz André Barroso, Urs Hölzle, Parthasarathy Ranganathan. The Datacenter as a Computer: Designing Warehouse-Scale Machines, 3rd edition. Springer Nature, 2019. ISBN: 9783031017612
[55] David Fiala 等。"Detection and Correction of Silent Data Corruption for Large-Scale High-Performance Computing." At International Conference for High Performance Computing, Networking, Storage and Analysis (SC), November 2012.
[56] Anna Kornfeld Simpson, Adriana Szekeres, Jacob Nelson, Irene Zhang. "Securing RDMA for High-Performance Datacenter Storage Systems." At 12th USENIX Workshop on Hot Topics in Cloud Computing (HotCloud), July 2020.
[57] Arjun Singh 等。"Jupiter Rising: A Decade of Clos Topologies and Centralized Control in Google's Datacenter Network." At Annual Conference of the ACM Special Interest Group on Data Communication (SIGCOMM), August 2015.
[58] Glenn K. Lockwood. "Hadoop's Uncomfortable Fit in HPC." glennklockwood.blogspot.co.uk, May 2014. 归档于 perma.cc/S8XX-Y67B
[59] Cathy O'Neil. Weapons of Math Destruction: How Big Data Increases Inequality and Threatens Democracy. Crown Publishing, 2016. ISBN: 9780553418811
[60] Supreeth Shastri 等。"Understanding and Benchmarking the Impact of GDPR on Database Systems." Proceedings of the VLDB Endowment, volume 13, issue 7, pages 1064–1077, March 2020.
[61] Martin Fowler. "Datensparsamkeit." martinfowler.com, December 2013. 归档于 perma.cc/R9QX-CME6
[62] "Regulation (EU) 2016/679 of the European Parliament and of the Council of 27 April 2016 (General Data Protection Regulation)." Official Journal of the European Union L 119/1, May 2016.