14-63 剑和诗人37 – 分布式系统中的数据访问设计

14-63 剑和诗人37 - 分布式系统中的数据访问设计

在分布式系统中,跨服务和数据库提供统一、可靠的数据访问至关重要,但又极具挑战性。微服务和数据库的拓扑结构为分布、缓存、复制和同步带来了复杂性。

让我们探索有助于解决这些复杂性并简化构建强大、高性能分布式系统的常见数据访问模式。

14-63 剑和诗人37 - 分布式系统中的数据访问设计

概述

我们将通过示例介绍以下分布式数据访问模式:

  • 每个服务都有数据库
  • 共享数据库
  • 每个区域的数据库
  • CQRS 和事件源
  • Saga 模式
  • API 组成
  • 缓存
  • 物化视图
  • 复制
  • 联邦
  • 多语言持久性
  • 多数据中心复制

这些模式有助于构建数据库拓扑、有效缓存、同步更改、处理故障和扩展数据访问。

让我们更详细地了解每种模式。

每个服务都有数据库

每个服务数据库模式为每个微服务提供其自己的私有数据库。

例如,订单服务有自己的订单数据库。客户服务有自己的客户数据库。

好处:

  • 解耦——服务不依赖于共享模式或数据库
  • 所有权——明确所有权,因为每个服务都管理其数据库
  • 规模——数据库可以根据服务需求独立扩展
  • 简单性——避免数据库共享,使协调更简单

缺点:

  • 数据隔离——跨服务交易和查询执行起来更加困难
  • 一致性——如果同步不正确,服务之间的数据就会不一致
  • 开销——管理多个数据库的运营开销更高

用例:

  • 微服务采用的早期阶段
  • 不共享数据的简单 CRUD 服务
  • 服务团队希望完全控制数据

这种模式提供了一条解耦服务的快速途径,但通常会随着时间的推移而发展,以允许更好的数据共享。

共享数据库

通过共享数据库模式,服务可以共享对单个逻辑数据库的访问权限。

例如,多个服务通过不同的模式访问 Oracle 数据库中的同一个客户表。

好处:

  • 简单——避免数据库之间复杂的数据同步和访问
  • 一致性——与数据库事务的强一致性
  • 已建立— 利用经过验证的 RDBMS 特性,如事务、索引、授权

缺点:

  • 紧密耦合——服务与数据库模式紧密耦合
  • 可扩展性——由于不同的服务有不同的需求,数据库很难扩展
  • 单点故障——数据库是一个 SPOF,可能导致所有服务瘫痪

用例:

  • 逐步将整体式架构转变为服务式架构
  • 少数服务共享大部分数据
  • 需要强大的数据一致性保证

共享数据库模式牺牲了简单性和一致性,以实现紧密耦合。它在增量迁移期间可以很好地工作,但通常会演变为拆分数据库。

每个区域的数据库

每个区域数据库模式在您运营的每个地理区域中部署数据库实例。

例如,跨区域部署 PostgreSQL 副本以实现低延迟读取。

好处:

  • 性能— 每个区域内的读/写延迟较低
  • 可用性——发生中断时故障转移到另一个区域数据库
  • 数据局部性——让数据靠近用户
  • 合规性——满足数据驻留和主权要求

缺点:

  • 复杂性——需要跨区域同步数据
  • 全局读取——从其他区域读取数据时延迟较高
  • 复制滞后——更改需要时间在区域之间传播

用例:

  • 全球分布的用户
  • 数据主权法
  • 停电时需要断开操作
  • 要求极低的延迟

每个区域数据库平衡了延迟,同时增加了复杂性。它通常与联合等其他模式结合使用。

命令查询责任分离(CQRS)

CQRS 使用单独的服务或接口将读写分成不同的模型。

例如,为命令服务提供写优化的数据库,为查询服务提供读优化的物化视图。

好处:

  • 优化模型——读写模型可以根据需要进行定制
  • 可扩展性——读取和写入可以独立扩展
  • 简单性——单独的接口避免单一方法的重载
  • 性能——命令可以使用不影响读取的快速写入

缺点:

  • 复杂性——需要逻辑来同步读写模型
  • 最终一致性——由于异步传播,读取可能落后于写入

用例:

  • 具有多次读写的协作域
  • 需要独立扩展的尖锐读写模式
  • 用户可以容忍最终一致性以获得较高的读取性能

当读写模式存在很大差异时,CQRS 是最佳选择。

事件溯源

通过事件源,所有状态变化都会被存储为随时间推移的一系列事件。

例如,不要存储最新的订单状态,而是存储每个 OrderCreated、OrderShipped、OrderDelivered 事件。

好处:

  • 审计日志——完整的变更历史记录,有利于审计和调试
  • 灵活性——事件是通用的,可以为许多读取模型提供支持
  • 性能——通过顺序写入可以快速附加事件
  • 重建状态——可以通过重播事件来重建状态

缺点:

  • 复杂性——需要将事件与领域模型进行转换
  • 数据增长——存储完整历史记录会增加存储需求
  • 调试——从事件中重建状态很有挑战性

用例:

  • 审计随时间的变化
  • 根据历史事件重建预测
  • 通过重播事件进行“时间旅行”调试
  • 高写入吞吐量应用程序

事件源将变更集中为事件流。将其与 CQRS 结合可实现最大的读/写灵活性。

Saga 模式

Saga 模式使用一系列本地事务来协调跨多个服务的事务。

例如,Order Saga 跨服务发起 OrderCreated、FundsReserved、InventoryReserved 事件。

好处:

  • 原子性——提供跨服务的事务一致性
  • 协调——协调跨服务的本地事务
  • 松耦合——服务通过事件编排而不是 2PC 参与
  • 补偿——如果整个 Saga 失败,允许撤消已完成的步骤

缺点:

  • 复杂性——需要将交易流程建模为 sagas
  • 最终一致性——saga 执行期间数据最终一致
  • 没有分布式回滚——当服务发生故障时,无法全局恢复所有服务

用例:

  • 跨服务的长期业务交易
  • 松耦合服务之间的协作
  • 故障时需要采取的补偿措施

Saga 提供分布式协调,而无需紧密的服务耦合。

API 组成

API 组合将来自多个服务的数据聚合到单个 API 中。

API 层查询来自多个服务和数据库的数据并将其组合成聚合响应。

例如,提供由来自不同服务的订单、客户和产品数据组成的订单详情 API。

好处:

  • 封装——向消费者隐藏内部结构
  • 灵活性——变更实施不会影响消费者
  • 性能——从缓存等最佳来源查找数据
  • 可用性— 如果服务中断,则优雅地降级

缺点:

  • 复杂性——组合逻辑通常复杂而脆弱
  • 增加延迟——从服务中检索数据的额外网络跳数
  • 版本控制——API 版本与各个服务版本相关联

用例:

  • 向客户端呈现统一的领域模型
  • 优化从缓存、索引中查找数据
  • 跨服务的编排和聚合
  • 遗留系统集成以隐藏内部结构

组合使编排集中化。对于具有高重用性的复杂情况,请使用 ESB 样式的工具。

缓存

缓存在靠近消费者的快速访问商店中重复的热数据。

例如,跨区域的产品目录或库存数据的 Redis 缓存。

好处:

  • 性能——避免使用低延​​迟缓存数据进行远程读取
  • 可扩展性——减少数据库负载
  • 弹性——提供中断和故障的后备方案

缺点:

  • 一致性——如果不正确刷新,数据可能会变得陈旧
  • 复杂性——缓存失效、TTL 和刷新增加了逻辑
  • 开销——运行缓存所需的额外存储和服务

用例:

  • 加速数据查找
  • 实现更高的读取可扩展性
  • 通过后备缓存命中提高可用性
  • 通过扩展缓存与数据库来降低成本

缓存可提高性能和可扩展性。请谨慎管理以减少陈旧数据。

物化视图

物化视图缓存查询和聚合的结果以便快速读取。

例如,汇总来自多个服务的指标的实时仪表板视图。

好处:

  • 性能——快速检索预先计算的视图
  • 自定义索引——针对特定访问模式优化存储
  • 简单——减少消费者的复杂查询
  • Scale — 通过复制的物化视图进行缩放读取

缺点:

  • 新鲜度——需要逐步刷新具体化
  • 存储开销——物化视图重复数据
  • 维护——更改架构需要重新定义视图

用例:

  • 加速缓慢的分析查询
  • 来自多个数据源的聚合
  • 提供优化的读取模型
  • 快速访问实时仪表板和报告

物化视图用存储换取查询速度。非常适合分析和 UI。

复制

复制会在数据库内或跨区域复制数据。

例如,主从 PostgreSQL 复制或多区域 Redis。

好处:

  • 性能——跨副本分散读取
  • 可用性——如果主服务器发生故障,则故障转移到副本
  • 刻度— 水平读取刻度
  • 延迟——将副本放置在靠近消费者的位置

缺点:

  • 复杂性——复制滞后可能导致读取过时
  • 冲突——如果写入操作同时命中主服务器和副本服务器,则需要解决冲突
  • 开销——复制数据的额外存储

用例:

  • 提高读取密集型工作负载的性能
  • 具有故障转移的高可用性
  • 跨区域或可用区分布的数据
  • 从单节点过渡到集群

复制可提高读取和灾难恢复能力。请仔细监控复制滞后。

联邦

联合(或分片)在数据库之间水平划分数据。

例如,按姓氏首字母在数据库之间对用户进行分片。

好处:

  • 规模——添加数据库来扩展写入和存储
  • 隔离——将数据放置在靠近用户的位置
  • 性能— 每个数据库的工作集越小,性能就越高

缺点:

  • 复杂性——需要联邦逻辑和分散/聚集访问
  • 连接——跨分片连接具有挑战性
  • 重新平衡——重新分配分片需要迁移

用例:

  • 扩展写入和存储,超越单个数据库的限制
  • 大型区域用户群和多数据中心访问
  • 按客户 ID 分片进行隔离

联合分片数据库以满足规模和隔离需求。这增加了复杂性,但消除了单个数据库的限制。

多语言持久性

多语言持久化根据数据特点使用不同的数据模型和数据库。

例如,Cassandra 用于订单,Elasticsearch 用于产品搜索,Kafka 用于客户事件。

好处:

  • 最佳拟合— 对每种数据类型使用最佳数据库
  • 规模——目标数据库可以独立扩展
  • 简单性——每个数据类型的架构和查询更简单
  • 灵活性——轻松开发特定模型

缺点:

  • 复杂性——集成不同的数据存储
  • 一致性——保持分布式数据同步
  • 技能— 需要具有多种数据库使用经验

用例:

  • 规划具有多种访问模式的大规模
  • 将适当的数据迁移到新系统
  • 与遗留系统集成
  • 混合交易/分析处理

多语言数据最大限度地提高了灵活性,同时需要数据库之间的集成逻辑。

多数据中心复制

多数据中心(多 DC)复制扩展了跨区域数据中心的复制。

例如,具有异步复制的全球分布的 MySQL 集群。

好处:

  • 低延迟——每个数据中心内的本地读取
  • 高可用性——跨数据中心的故障转移
  • 合规性——数据驻留符合法规要求

缺点:

  • 复杂性——跨数据中心协调写入
  • 网络延迟——较长的 WAN 延迟会影响复制
  • 成本——跨区域运营和复制

用例:

  • 迁移到区域部署模型
  • 最大限度减少全球用户的延迟
  • 停电期间需要断开操作
  • 双活双数据中心

多数据中心平衡延迟、可用性和主权。监控站点间的延迟。

14-63 剑和诗人37 - 分布式系统中的数据访问设计

关键要点

观察常见的分布式数据模式,我们发现以下原则:

  • 尽可能将数据库与服务分离,以实现独立的扩展和发展。使用“每个服务一个数据库”和 CQRS 等模式。
  • 跨区域和可用区将数据分发到靠近用户的位置,以提高性能和隔离性。这包括按区域和联合的数据库。
  • 在缓存和物化视图中复制经常访问的数据,以减少事务数据库的负载。
  • 使用 API Composition 和 Saga 模式协调跨服务访问。
  • 使用复制和多语言持久性来扩展读取。
  • 通过事件和多 DC 复制等技术保持缓存、服务和数据库之间的数据同步。

没有一种模式是万能的。重点是将数据库与服务分离,以实现更好的扩展和演进。然后围绕区域用户模式构建拓扑。最后使用多语言持久性优化具有重复和不同访问模式的某些数据。

数据访问模式提供了一套工具包,用于构建能够妥善处理规模、故障和变化的分布式系统。适当混合和搭配模式,以构建可扩展、有弹性的数据架构。

RA/SD 衍生者AI训练营。发布者:chris,转载请注明出处:https://www.shxcj.com/archives/3803

Like (0)
Previous 2024-07-09 10:16 下午
Next 2024-07-10 5:10 上午

相关推荐

发表回复

Please Login to Comment
本文授权以下站点有原版访问授权 https://www.shxcj.com https://www.2img.ai https://www.2video.cn