数据系统架构中的权衡

没有解决方案,只有权衡取舍,你只能尽力作出最佳权衡。

在共享的服务器端数据基础设施中存储众多用户的数据,已司空见惯,用户活动、业务交易、设备和传感器产生的数据等 保存下来以供分析, 用户与应用交互 既会读取已存储的数据也会产生更多数据。

少量数据单台机器可以存储和处理,随着数据量或查询速率增长,数据就需要分布到多台机器上,然后再变复杂数据放一个系统里也不够用,往往需要组合多个能力各异的存储或处理系统。

如果数据管理是开发应用时面临的主要挑战之一,我们就称这种应用为 数据密集型 应用。

许多应用都需要:

分析型与事务型系统

数据系统通常有几类打交道的人,后端工程师(后端程序)、业务分析师(生成报表 商业智能BI)、数据科学家(从数据中寻找新的洞见 机器学习)。

事务处理与分析的特征

事务型系统通常按某个键查找少量记录(称为 点查询),再根据用户输入插入、更新或删除记录。由于这些应用具有交互性,这种访问模式称为 联机事务处理(OLTP)。OLTP系统主要执行写在代码里的固定查询,只在维护或排查故障时偶尔运行一次性自定义查询。

分析的访问模式与OLTP 大相径庭,分析查询通常会扫描海量记录、计算计数、总和或平均值等聚合统计量,而不是把一条记录返回给用户。人们称之为 联机分析处理(OLAP)。分析数据库,通常允许用户自由手写任意SQL查询 通过 Tableau、Lokker、Microsoft Power BI 等数据可视化或仪表盘工具自动生成查询。

有一类系统专门分析负载(聚合大量记录的查询)而设计,嵌入在面向用户的产品中,这类用途称为 产品分析或实时分析,有 Pinot、Druid、ClickHouse。

数据仓库

企业一般不在OLTP系统进行分析,在一个独立的数据库系统上运行分析查询,这个独立数据库称为 数据仓库。

不宜让业务分析师和数据科学家直接查询这些OLTP系统:

数据从OLTP数据库中抽取,定期转储或连续的更新流,转换为便于分析的模式并加以清理,最后载入数据仓库。

提取 -> 转换 -> 加载(ETL)

图1-1 将数据通过ETL导入数据仓库的简化示意图

事务型系统与分析型系统的分离,系统日益专门化,针对特定负载进行优化。

从数据仓库到数据湖

数据仓库通常用 关系数据模型,用SQL查询。适合业务分析师所需的,不适合数据科学家的需求。它们喜欢将 数据转换为适合机器学习训练、应用于自然语言处理、提取特征等,喜欢用 panda、scikit-learn等数据分析库, R语言,Spark等分布式分析框架。

数据湖:一个集中的数据存储库,保存一切可能对分析有用的数据副本,这些数据通过ETL流程从事务性系统取得。

数据湖与数据仓库的区别在于,它只保存文件,并不强制规定文件格式或数据模型。

超越数据湖

有时,分析系统的输出还会提供给事务型系统,这个过程有时称为 反向 ETL 。例如,在分析系统中训练好的机器学习模型可以部署到生产环境,向最终用户生成“购买了 X 的人也购买了 Y”之类的推荐。

权威记录系统与衍生数据

权威记录系统:也称 权威数据源,保存某类数据的权威或 规范 版本。新数据到来时,例如用户输入,首先写入这里。如果其他系统与权威记录系统的数据不一致,那么按照定义,应以权威记录系统中的值为准。

衍生数据系统:衍生系统中的数据,是以另一个系统中的现有数据为基础,经过某种转换或处理而得到的结果。衍生数据即使丢失,也可以从原始数据源重新创建。 缓存就是一个经典例子。

从技术上讲,衍生数据是冗余的,因为它复制了现有信息。

云服务与自托管

一个极端是完全定制的软件,由你自行编写并在内部运行;另一个极端是广泛使用的云服务或软件即服务(SaaS)产品,由外部供应商开发和运维,你只能通过 Web 界面或 API 使用。

图1-2 软件类型及其运维方式的连续谱

云服务的利弊

云服务究竟是否比自托管,这与软件规模,硬件搭建、电力价格、网络设施价格都有很大关系。

系统负载随时间大幅波动,云服务价值很高。目前几乎没什么小公司自己搭建机房,先把业务干大干强,真能到一定规模称为现象级应用或平台,建机房都是水到渠成的事。

云原生系统架构

云计算采用订阅服务,而不是购买硬件和软件许可证,再自己运行软件。云原生 一词用来描述专为利用云服务优势而设计的架构。

自托管数据库系统与云原生数据库系统示例

类别 自托管系统 云原生系统
事务型 OLTP MySQL、PostgreSQL、MongoDB AWS Aurora、Azure SQL DB、Hyperscale、Google Cloud Spanner
分析型 OLAP Teradata、ClickHouse、Spark Snowflake、Google BigQuery、Azure Synapse Analytics

云服务的分层

自托管软件使用的都是十分通用的计算资源,CPU、内存、文件系统和IP网络。

在云中,这类软件可以运行在基础设施即服务 Iaas 环境里,一台多多台虚拟机,每台实例分配一定数量 CPU、内存、磁盘和网络贷款。

云原生服务关键思想:不仅使用操作系统管理的计算资源,还要在底层云服务的基础上构建更高层的服务,如

Amazon S3、Azure Blob Storage、Cloudflare R2 等对象存储服务用于保存大型文件。

存储与计算的分离

传统计算,磁盘存储视为持久存储,为了容忍单块硬盘故障,通常使用 RAID 独立磁盘冗余阵列。

云中的计算实例(虚拟机)也可以连接本地磁盘,一旦实例发生故障,本地磁盘无法访问。

云服务还提供虚拟磁盘存储,可以从一个实例写在,再挂载到另一个实例上,如 Amazon EBS、Azure 托管磁盘、Google Cloud 持久磁盘。虚拟磁盘并不是真正的物理磁盘,而是由另一组机器提供的云服务,用来模拟磁盘的行为——也就是 块设备,其中每个块通常为 4 KB。

传统系统架构,同一台计算机同时负责存储(磁盘)和 计算(CPU与内存),在云原生系统中,计算和存储一定程度解耦。

云原生系统往往采用 多租户 模式,并不为每个客户单独分配一台机器,而是由同一项服务在共享硬件上处理多个客户的数据和计算。

云时代的运维

以前是 数据库管理员 DBA、系统管理员 sysadmin,现在把软件开发与运维角色融 入同一个团队,共同负责后端服务和数据基础设施。DevOps理念推动了这一趋势。

站点可靠性工程师 SRE 是 Google 对这一理念的实践。

DevOps、SRE 理念更强调:

分布式与单节点系统

分布式系统:由多台机器通过网络通信而构成的系统,称为 分布式系统。

节点:参与分布式系统的每个进程称为一个 节点。

分布式系统的问题

每一个经过网络的请求和API调用,都必须面对失败的可能。网络可能中断、服务可能过载、 任何请求都可能超时收不到响应,贸然重试未必安全。

分布式系统往往很难排查故障,用于诊断分布式系统问题的技术统称为 可观测性。有一些如 OpenTelemetry、Zipkin、Jaeger 等追踪工具。

数据库提供了多种保证数据一致性的机制。现在单机器也能满足需求,比搭建分布式系统简单又便宜,如 DuckDB、SQLite 单节点数据库非常不错,还有改造的分布式版本。

微服务与无服务器

微服务架构,每项服务都有明确用途,服务通过API向客户端开放能力,由客户端经网络调用,每项服务由一个团队负责维护,复杂应用拆分为多项相互交互的服务。Kubernetes 等 编排 框架为这类基础设施提供了基础能力,因此成了部署服务的常用方式。

OpenAPI 和 gRPC 等API描述标准有助于管理客户端API与服务器API之间的关系。

无服务器 serverless,又称 函数即服务 FaaS。每次执行无服务器函数仍然需要用到一台服务器,只是下一次执行可能换到另一台。如 vercel 平台就比较出名。

BigQuery 和各种 Kafka 产品也采用了“无服务器”这个说法,用来表示服务能够自动伸缩,并按使用量而不是机器实例收费。

云计算与超级计算

云计算并非构建大规模计算系统的唯一方式,另一条路线是 高性能计算 HPC,也称 超级计算。

就是每个国家建立的那种超算中心,一般都是为了 计算密集型的科学计算任务。