本书的第一部分和第二部分,自底向上把所有关于分布式数据库的主要考量都讲了一遍。从数据在磁盘上的布局,一直到故障时关于分布式系统一致性的局限性。但所有的讨论都假定了应用程序中只用了一种数据库。
现实世界中的数据系统往往更为复杂。大型应用程序经常需要以多种方式访问和处理数据,没有一个数据库可以同时满足所有这些不同的需求。因此应用程序通常组合使用多种组件:数据存储,索引,缓存,分析系统,等等,并实现在这些组件中移动数据的机制。
本书的最后一部分,会研究将多个不同数据系统(可能有着不同数据模型,并针对不同的访问模式进行优化)协调一致地集成入应用架构时会遇到的问题。软件供应商经常会忽略这一方面的系统建设,并声称他们的产品能够满足您的所有需求。在现实世界中,集成不同的系统是实际应用中最重要的事情之一。
从高层次上看,存储和处理数据的系统可以分为两大类:
一个关于记录的系统,也被称为真相源(source of truth),保留了权威版本的数据。当新的数据进入时(例如,用户输入)首先会在这里记录。每个事实恰好只表示一次(表示通常是标准化的 normalized)。如果另一个系统和记录系统之间有任何差异,那么记录系统中的值是(根据定义)是正确的。
衍生系统中的数据,通常来自另一个系统的现有数据,以某种方式进行转换或处理的结果。如果丢失衍生的数据,您可以从原始来源重新创建它。典型的例子是缓存:如果存在,数据可以从缓存中提供;如果缓存不包含所需数据,总是可以降级由底层数据库提供。非规范化的值,索引和物化视图也属于这个类别。在推荐系统中,预测汇总数据通常派生自来用户日志。
从技术上讲,派生数据是冗余的(redundant),因为它重复了已有的信息。但是衍生数据对于获得良好的读性能通常是至关重要的。它通常是非规范化的。可以从同一个来源派生出多个不同的数据集,使得用户可以从不同的“视角”去洞察数据。
并不是所有的系统都在其架构中明确区分记录系统和派生系统,但是这是一种有用的区分方式,因为它明确了系统中的数据流:系统的哪一部分具有哪些输入和哪些输出,以及它们如何相互依赖。
大多数数据库,存储引擎和查询语言,本质上既不是记录系统也不是派生系统。数据库只是一个工具:如何使用它取决于你。记录系统和衍生数据系统之间的区别不在于工具,而在于应用程序中的使用方式。
通过梳理数据的派生关系,可以清楚地理解一个令人困惑的系统架构。这将贯穿本书的这一部分。
第十章通过研究面向批处理的数据流系统,例如MapReduce,看看它们是如何给我们提供构建大规模数据系统的优秀工具和原理的。
第十一章将把这些概念应用到流式数据(data streams)中,使同样的任务能以更低的延迟完成。
第十二章将对本书进行总结,探讨使用这些工具来构建可靠,可扩展和可维护的应用程序的思路。