System Design 系统设计 (数据库)


原文引用 – System Design


Chapter II 数据库



Databases and DBMS 数据库和数据库管理系统

什么是数据库?

数据库是结构化信息或数据的有组织集合,通常以电子方式存储在计算机系统中。

数据库通常由数据库管理系统 (DBMS) 控制。

数据DBMS 以及与之关联的应用程序一起称为数据库系统,通常简称为数据库

什么是数据库管理系统? DBMS

数据库通常需要一个称为数据库管理系统 (DBMS) 的综合数据库软件程序。

DBMS 充当数据库与其最终用户或程序之间的接口,允许用户检索、更新和管理信息的组织和优化方式。

DBMS 还有助于监督和控制数据库,支持各种管理操作,例如性能监控、调整以及备份和恢复。

数据库中一些常见组件

  • Schema

定义数据结构的形状,并指定什么样的数据可以去哪里。

Schema可以在整个数据库中严格执行,也可以在数据库的一部分上松散地执行,或者它们可能根本不存在。

  • Table

每个表都包含各种列,就像在电子表格中一样。

一个表可以只有两列,也可以有一百或更多列,这取决于表中放置的信息类型。

  • Column

一列包含一组特定类型的数据值,一个值代表数据库的每一行。

一列可能包含文本值、数字、枚举、时间戳等。

  • Row

表中的数据记录在行中。

表中可能有数千或数百万行具有任何特定信息。

大规模运行数据库时面临的一些常见挑战

  • 吸收数据量的显着增加:

    来自传感器、联网机器和许多其他来源的数据呈爆炸式增长。
    
  • 确保数据安全:

     如今,数据泄露无处不在,确保数据安全且用户易于访问比以往任何时候都更加重要。
    
  • 跟上需求:

    公司需要实时访问他们的数据以支持及时的决策制定并利用新的机会。
    
  • 管理和维护数据库和基础设施:

    随着数据库变得越来越复杂和数据量的增长,公司面临着雇用额外人才来管理其数据库的费用。
    
  • 消除对可扩展性的限制:

    企业要想生存就需要发展,其数据管理也必须随之发展。 但是很难预测公司需要多少容量,尤其是本地数据库。

  • 确保数据驻留、数据主权或延迟要求:

    一些组织的用例更适合在本地运行。 在这些情况下,为运行数据库而预先配置和预先优化的工程系统是理想的。

数据库 类型

  • SQL

  • NoSQL

    Document

    Key-value

    Graph

    Timeseries

    Wide column

    Multi-model

SQL databases

SQL(或关系型)数据库是数据项的集合,它们之间具有预定义的关系。

这些项目被组织为一组包含列和行的表格。 表用于保存有关要在数据库中表示的对象的信息。 表中的每一列都包含某种数据,字段存储属性的实际值。 表中的行表示一个对象或实体的相关值的集合。

表中的每一行都可以用一个称为主键的唯一标识符来标记,并且多个表之间的行可以使用外键进行关联。 这些数据可以通过多种不同的方式访问,而无需重新组织数据库表本身。

SQL 数据库通常遵循 ACID 一致性模型。

Materialized views 实体化视图

实体化视图是从查询规范派生并存储以备后用的预先计算的数据集。 因为数据是预先计算的,所以查询物化视图比对视图的基表执行查询更快。 当查询频繁运行或足够复杂时,这种性能差异可能会很明显。

它还支持数据子集化并提高在大型数据集上运行的复杂查询的性能,从而减少网络负载。 物化视图还有其他用途,但它们主要用于性能和复制。

N+1查询问题

N+1 查询问题发生在数据访问层执行 N 个额外的 SQL 语句以获取在执行主 SQL 查询时可能已检索到的相同数据时。 N的值越大,执行的查询越多,对性能的影响越大。

这在 GraphQL 和 ORM(对象关系映射)工具中很常见,可以通过优化 SQL 查询或使用数据加载器来解决, 该数据加载器对连续请求进行批处理并在后台发出单个数据请求。

优缺点

优点

简单准确
辅助功能
数据一致性
灵活性

缺点

维护费用昂贵
困难的模式演变
性能命中(连接、非规范化等)
水平可扩展性差,难以扩展

例子

PostgreSQL

MySQL

MariaDB

Amazon Aurora

NoSQL databases

NoSQL 是一个广泛的类别,包括不使用 SQL 作为其主要数据访问语言的任何数据库。 这些类型的数据库有时也称为非关系数据库。

与关系数据库不同,NoSQL 数据库中的数据不必符合预定义的模式。 NoSQL 数据库遵循 BASE 一致性模型。

不同类型的 NoSQL 数据库:

  • Document

文档数据库(也称为面向文档的数据库或文档存储)是一种在文档中存储信息的数据库。

它们是通用数据库,服务于交易和分析应用程序的各种用例。

优点

直观灵活

简单的水平缩放

无模式

缺点

无模式

非关系型

例子

MongoDB

Amazon DocumentDB

CouchDB
  • Key-value

作为最简单的 NoSQL 数据库类型之一,键值数据库将数据保存为一组键值对,每个键值对由两个数据项组成。

它们有时也被称为键值存储

优点

简单而高效
高度可扩展以应对大量流量
会话管理
优化查找

缺点

基本增删改查
无法过滤值
缺乏索引和扫描功能
未针对复杂查询进行优化

例子

Redis

Memcached

Amazon DynamoDB

Aerospike
  • Graph

图数据库是一种 NoSQL 数据库,它使用图结构进行具有节点、边和属性的语义查询来表示和存储数据,而不是表或文档。

该图将存储中的数据项与节点和边的集合相关联,边表示节点之间的关系。

这些关系允许商店中的数据直接链接在一起,并且在许多情况下,可以通过一次操作进行检索。

优点

查询速度
敏捷灵活
显式数据表示

缺点

复杂的
没有标准化的查询语言

用例

欺诈识别

推荐引擎

社交网络

网络映射

例子

Neo4j

ArangoDB

Amazon Neptune

JanusGraph
  • Time series

时间序列数据库是针对时间戳或时间序列数据优化的数据库。

优点

快速插入和检索
高效的数据存储

用例

物联网数据

指标分析

应用监控

了解金融趋势

例子

InfluxDB

Apache Druid
  • Wide column

宽列数据库,也称为宽列存储,与模式无关。

数据存储在列族中,而不是行和列中。

优点

高度可扩展,可以处理 PB 级数据
实时大数据应用的理想选择

缺点

昂贵的
增加写入时间

用例

商业分析

基于属性的数据存储

例子

BigTable

Apache Cassandra

ScyllaDB
  • Multi-model

多模型数据库将不同的数据库模型(即关系、图形、键值、文档等)组合到一个集成的后端中。

这意味着它们可以适应各种数据类型、索引、查询,并将数据存储在多个模型中

优点

灵活性
适用于复杂项目
数据一致

缺点

复杂的
不太成熟

例子

ArangoDB

Azure Cosmos DB

Couchbase


SQL vs NoSQL databases SQL 与 NoSQL 数据库

在数据库世界中,有两种主要类型的解决方案,SQL(关系型)和 NoSQL(非关系型)数据库。

它们的构建方式、存储的信息类型以及存储信息的方式都不同。

关系数据库是结构化的并且具有预定义的模式,而非关系数据库是非结构化的、分布式的并且具有动态模式。

SQL 和 NoSQL 之间的一些高级差异

  • Storage 存储

SQL 将数据存储在表中,其中每一行代表一个实体,每一列代表关于该实体的一个数据点。

NoSQL数据库有键值、图、文档等不同的数据存储模型。

  • Schema

在 SQL 中,每条记录都符合一个固定的模式,这意味着必须在输入数据之前决定和选择列,并且每行必须有每一列的数据。 模式可以稍后更改,但它涉及使用迁移修改数据库。

而在 NoSQL 中,模式是动态的。 可以即时添加列,每一行(或等效行)不必包含每一列的数据。

  • Querying

SQL 数据库使用 SQL(结构化查询语言)来定义和操作数据,功能非常强大。

在 NoSQL 数据库中,查询集中在文档集合上。 不同的数据库有不同的查询语法。

  • Scalability 扩展性

在大多数常见情况下,SQL 数据库是垂直可扩展的,这可能会变得非常昂贵。 跨多个服务器扩展关系数据库是可能的,但这是一个具有挑战性且耗时的过程。

另一方面,NoSQL 数据库是横向可扩展的,这意味着我们可以轻松地向我们的 NoSQL 数据库基础架构添加更多服务器来处理大流量。

任何廉价的商品硬件或云实例都可以托管 NoSQL 数据库,因此比垂直扩展更具成本效益。 许多 NoSQL 技术还自动跨服务器分发数据。

  • Reliability 可靠性

绝大多数关系数据库都符合 ACID。 因此,就数据可靠性和执行事务的安全保证而言,SQL 数据库仍然是更好的选择。

大多数 NoSQL 解决方案为了性能和可扩展性而牺牲了 ACID 合规性。

选择 SQL NoSQL的原因

对于 SQL

具有严格模式的结构化数据

关系数据

需要复杂的连接

交易

按索引查找非常快

对于 NoSQL

动态或灵活的模式

非关系数据

不需要复杂的连接

数据密集型工作负载

非常高的 IOPS 吞吐量


数据库同步,复制

复制是一个涉及共享信息以确保冗余资源(例如多个数据库)之间的一致性,以提高可靠性、容错性或可访问性的过程。

主从复制 Master-Slave Replication

master 提供读写服务,将写入复制到一个或多个仅提供读取服务的 slave。 从站还可以以树状方式复制其他从站。

如果 master 离线,系统可以继续以只读模式运行,直到一个 slave 被提升为 master 或提供一个新的 master。

优点

整个数据库的备份对master相对没有影响。

应用程序可以在不影响主服务器的情况下从从服务器读取数据。

从站可以脱机并同步回主站,而无需停机。

缺点

复制增加了更多的硬件和额外的复杂性。

主机故障时的停机时间和可能的数据丢失。

所有写入也必须在主从架构中对主服务器进行。

读从机越多,我们要复制的越多,这会增加复制滞后。

主-主复制 Master-Master Replication

两个 master 都提供读/写服务并相互协调。

如果任一主节点出现故障,系统可以继续进行读写操作。

优点

应用程序可以从两个主机读取。

在两个主节点之间分配写入负载。

简单、自动且快速的故障转移。

缺点

不像主从配置部署那么简单。

松散一致或由于同步而增加了写入延迟。

随着更多写入节点的添加和延迟的增加,冲突解决开始发挥作用。

同步与异步复制 Synchronous vs Asynchronous replication

同步和异步复制之间的主要区别在于数据写入副本的方式。

同步复制中,数据同时写入主存储和副本。 因此,主副本和副本应始终保持同步。

相反,异步复制在数据已写入主存储后将数据复制到副本。 尽管复制过程可能会近乎实时地进行,但按计划进行复制更为常见,并且更具成本效益。


索引 Indexes

当涉及到数据库时,索引是众所周知的,它们用于提高数据存储上的数据检索操作的速度。

索引在增加存储开销和较慢的写入(因为我们不仅要写入数据而且还必须更新索引)以换取更快的读取之间进行权衡。

索引用于快速定位数据,而无需检查数据库表中的每一行。

可以使用数据库表的一列或多列创建索引,为快速随机查找和高效访问有序记录提供基础。

索引是一种数据结构,可以将其视为目录,将我们指向实际数据所在的位置。

因此,当我们在表的列上创建索引时,我们将该列和指向整行的指针存储在索引中。

索引还用于创建相同数据的不同视图。 对于大型数据集,这是指定不同过滤器或排序方案的绝佳方式, 而无需求助于创建多个额外的数据副本。

数据库索引的一个特性是它们可以是密集的或疏的。 这些指数质量中的每一个都有其自身的权衡。

Dense Index

密集索引中,为表的每一行创建一个索引记录。

记录可以直接定位,因为索引的每个记录都包含搜索关键字值和指向实际记录的指针。

在写入时,密集索引比稀疏索引需要更多维护。 由于每一行都必须有一个条目,因此数据库必须在插入、更新和删除时维护索引。 每行都有一个条目也意味着密集索引将需要更多内存。 密集索引的好处是可以通过二进制搜索快速找到值。 密集索引也不对数据强加任何排序要求。

Sparse Index

在稀疏索引中,仅为部分记录创建记录。

稀疏索引在写入时比密集索引需要更少的维护,因为它们只包含值的一个子集。 这种较轻的维护负担意味着插入、更新和删除会更快。 拥有更少的条目也意味着索引将使用更少的内存。 查找数据速度较慢,因为跨页面扫描通常遵循二进制搜索。 在处理有序数据时,稀疏索引也是可选的。


Normalization and Denormalization 规范化和反规范化

规范化和反规范化中的一些常用术语

  • Keys 键

Primary key 主键:可用于唯一标识表中每一行的列或列组。

Composite key 复合键:由多个列组成的主键。

Super key 超级键:可以唯一标识表中存在的所有行的所有键的集合。

Candidate key 候选键:在表中唯一标识行的属性。

Foreign key 外键:它是对另一个表的主键的引用。

Alternate key 备用键:不是主键的键称为备用键。

Surrogate key 代理键:当没有其他列能够保存主键的属性时,系统生成的值可以唯一标识表中的每个条目。

  • Dependencies 依赖关系

Partial dependency 部分依赖:发生在主键决定其他一些属性时。

Functional dependency 功能依赖:它是存在于两个属性之间的关系,通常是表中的主键和非键属性之间。

Transitive functional dependency 传递函数依赖:当一些非关键属性决定其他一些属性时发生。

  • Anomalies 异常现象

当由于不正确的计划或将所有内容存储在平面数据库中而导致数据库存在缺陷时,就会发生数据库异常。 这通常通过规范化过程来解决。

Insertion anomaly 插入异常:当我们无法在没有其他属性存在的情况下将某些属性插入数据库时发生。

Update anomaly 更新异常:发生在数据冗余和部分更新的情况下。 换句话说,数据库的正确更新需要其他操作,例如添加、删除或两者。

Deletion anomaly 删除异常:发生在删除某些数据需要删除其他数据的情况下。

Normalization 规范化

规范化是在数据库中组织数据的过程。

这包括根据旨在保护数据和通过消除冗余和不一致的依赖性使数据库更加灵活的规则来创建表和在这些表之间建立关系

  • 为什么需要规范化

规范化的目标是消除冗余数据保证数据的一致性

完全规范化的数据库允许扩展其结构以容纳新类型的数据,而无需过多更改现有结构。 因此,与数据库交互的应用程序受到的影响最小。

  • Normal forms 范式

范式是一系列确保数据库规范化的准则

- `1NF` 第一范式


    不允许重复组。
  
    用主键标识每组相关数据。
  
    一组相关数据应该有一个单独的表。
  
    不允许在同一列中混合数据类型



- `2NF` 第二范式


    满足第一范式 (1NF)

    不应该有任何部分依赖




- `3NF` 第三范式


    满足第二范式 (2NF)。

    传递函数依赖是不允许的



- `BCNF` Boyce-Codd 范式

`Boyce-Codd 范式`(或 BCNF)是第三范式 (3NF) 的稍强版本,用于解决最初定义的 3NF 未处理的某些类型的异常。
有时也称为 `3.5 范式` (3.5NF)。

    满足第三范式(3NF)

    对于每个函数依赖 X → Y,X 应该是超级键


- ...

在关系数据库中,如果关系满足第三范式,则通常将其描述为“规范化”

大多数 3NF 关系没有插入、更新和删除异常。

与许多正式的规则和规范一样,现实世界的场景并不总是允许完美合规。

如果您决定违反规范化的前三个规则之一,请确保您的应用程序预见到可能发生的任何问题, 例如冗余数据和不一致的依赖关系。

  • 优缺点

优点

减少数据冗余。
更好的数据设计。
提高数据一致性。
强制参照完整性。

缺点

数据设计很复杂。
性能较慢。
维护开销。
需要更多的连接。

Denormalization 反规范化

非规范化是一种数据库优化技术,我们将冗余数据添加到一个或多个表中。

这可以帮助我们避免在关系数据库中进行代价高昂的连接

它试图以牺牲一些写入性能为代价来提高读取性能。 数据的冗余副本写入多个表以避免昂贵的连接。

一旦数据通过联合和分片等技术分布,跨网络管理连接会进一步增加复杂性。 非规范化可能会避免对此类复杂连接的需求。

注意:反规范化并不意味着反转规范化(reversing normalization)

  • 优缺点

优点

检索数据更快。
编写查询更容易。
减少表的数量。
便于管理。

缺点

昂贵的插入和更新。
增加数据库设计的复杂性。
增加数据冗余。
数据不一致的可能性更大。


ACID and BASE consistency models ACIDBASE 一致性模型

ACID

ACID 代表原子性、一致性、隔离性和持久性。 ACID 属性用于在事务处理期间维护数据完整性。

为了保持事务前后的一致性,关系数据库遵循 ACID 属性

  • 原子 Atomic

事务中的所有操作都成功或每个操作都被回滚。

  • 持续的 Consistent

事务完成后,数据库在结构上是健全的。

  • 隔离的 Isolated

事务不相互竞争。 对数据的有争议的访问由数据库进行调节,以便事务看起来是按顺序运行的。

  • 耐用的 Durable

一旦事务已经完成,写入和更新已经写入磁盘,即使发生系统故障,它也会保留在系统中。

BASE

随着数据量和高可用性要求的增加,数据库设计方法也发生了巨大变化。 为了提高扩展能力并同时保持高可用性,我们将逻辑从数据库移至单独的服务器。 这样,数据库变得更加独立,专注于存储数据的实际过程。

NoSQL 数据库世界中,ACID 事务不太常见, 因为一些数据库放宽了对即时一致性、数据新鲜度和准确性的要求,以获得其他好处,如规模和弹性。

BASE 属性比 ACID 保证宽松得多,但是两个一致性模型之间没有直接的一对一映射

  • 基本可用性 Basic Availability

数据库似乎大部分时间都在工作。

  • 软状态 Soft-state

存储不必写一致,不同的副本也不必始终相互一致。

  • 最终一致性 Eventual consistency

数据可能不会立即一致,但最终会变得一致。 系统中的读取仍然是可能的,即使它们可能由于不一致而无法给出正确的响应。

ACID BASE 的权衡

对于我们的应用程序需要 ACID 还是 BASE 一致性模型,没有正确的答案。 这两种模型的设计都是为了满足不同的要求。 在选择数据库时,我们需要牢记模型的属性和应用程序的要求

考虑到 BASE 的松散一致性,如果开发人员为他们的应用程序选择 BASE 存储, 则他们需要对一致性数据有更多的了解和严格。 必须熟悉所选数据库的 BASE 行为并在这些约束下工作。

另一方面,与 ACID 事务的简单性相比,围绕 BASE 限制进行规划有时可能是一个主要缺点。 完全 ACID 数据库非常适合数据可靠性和一致性至关重要的用例


分布式系统 CAP Theorem (Consistency, Availability,Partition tolerance)

CAP 定理指出,分布式系统只能提供一致性可用性分区容错性 (CAP) 这三个所需特性中的两个

CAP定理所指的三个分布式系统特性

  • 一致性 Consistency

一致性意味着所有客户端同时看到相同的数据,无论它们连接到哪个节点。 为此,无论何时将数据写入一个节点,都必须在写入被视为“成功”之前立即转发或复制到系统中的所有节点。

  • 可用性 Availability

可用性意味着任何发出数据请求的客户端都会得到响应,即使一个或多个节点已关闭。

  • 分区容差 Partition tolerance

分区容错意味着系统在消息丢失或部分故障的情况下继续工作。 分区容错的系统可以承受任何数量的网络故障,但不会导致整个网络出现故障。 跨节点和网络的组合充分复制数据,以在间歇性中断期间保持系统正常运行。

  • 一致性-可用性 Consistency-Availability 权衡

物理世界中,无法保证网络的稳定性,所以分布式数据库必须选择Partition Tolerance(P)

这意味着需要在一致性 (C) 可用性 (A) 之间进行权衡。

CA 数据库

CA 数据库提供跨所有节点的一致性和可用性。 如果系统中任意两个节点之间存在分区,则无法执行此操作,因此无法提供容错。

示例:PostgreSQL、MariaDB。

CP数据库

CP 数据库以可用性为代价提供一致性和分区容错性。 当任意两个节点之间发生分区时,系统必须关闭不一致的节点,直到分区解决。

示例:MongoDB、Apache HBase。

AP数据库

AP 数据库以一致性为代价提供可用性和分区容错性。 发生分区时,所有节点都保持可用,但分区错误端的节点可能会返回比其他节点更旧的数据版本。 分区解决后,AP 数据库通常会重新同步节点以修复系统中的所有不一致。

示例:Apache Cassandra、CouchDB。


分布式系统 PACELC Theorem

PACELC 定理CAP 定理的扩展。

CAP 定理指出,在分布式系统中的网络分区 (P) 的情况下,必须在可用性 (A) 和一致性 (C) 之间做出选择。

PACELC 通过引入延迟 (L) 作为分布式系统的附加属性来扩展 CAP 定理。 该定理指出,否则(E),即使系统在没有分区的情况下正常运行,也必须在延迟(L)一致性(C)之间做出选择

PACELC 定理的开发是为了解决 CAP 定理的一个关键限制,因为它没有对性能或延迟做出规定。

例如,
  根据 CAP 定理,如果查询在 30 天后返回响应,则可以认为数据库可用。 
  显然,对于任何现实世界的应用程序来说,这样的延迟都是不可接受的


Transaction 事务

事务是被视为“单个工作单元”的一系列数据库操作。

事务中的操作要么全部成功,要么全部失败。

这样,事务的概念在系统的一部分出现故障时支持数据完整性

并非所有数据库都选择支持 ACID 事务,通常是因为它们优先考虑其他难以或理论上无法一起实施的优化。

通常,关系型数据库支持ACID事务,非关系型数据库不支持(也有例外)。

事务的状态 States

数据库中的事务可以处于以下状态

  • Active

在这种状态下,交易正在执行。 这是每笔交易的初始状态。

  • Partially Committed

当一个事务执行它的最终操作时,它被称为处于部分提交状态。

  • Committed

如果一个事务成功执行了它的所有操作,则称它已提交。 它的所有效果现在都永久地建立在数据库系统上。

  • Failed

如果数据库恢复系统所做的任何检查失败,则称该事务处于失败状态。 失败的交易不能再继续进行。

  • Aborted

如果任何检查失败并且事务已达到失败状态,则恢复管理器将回滚其对数据库的所有写操作,以使数据库恢复到事务执行之前的原始状态。 处于这种状态的交易被中止。

数据库恢复模块可以在事务中止后选择以下两种操作之一:
  
  重启交易
  杀死交易
  • Terminated

如果没有任何回滚或事务来自已提交状态,则系统是一致的并为新事务做好准备,旧事务将终止。


Distributed Transactions 分布式事务

分布式事务是跨两个或多个数据库执行的一组数据操作。

它通常在通过网络连接的独立节点之间进行协调,但也可能跨越单个服务器上的多个数据库。

为什么需要分布式事务?

与单个数据库上的 ACID 事务不同,分布式事务涉及更改多个数据库上的数据。 因此,分布式事务处理更加复杂,因为数据库必须作为一个独立的单元来协调事务中更改的提交或回滚。

换句话说,所有节点都必须提交,或者所有节点都必须中止并且整个事务回滚。

一些流行的分布式事务解决方案

  • The two-phase commit (2PC) 两阶段提交

两阶段提交 (2PC) 协议是一种分布式算法,它协调参与分布式事务的所有进程是提交还是中止(回滚)事务。

即使在许多临时系统故障的情况下,该协议也能实现其目标,因此被广泛使用。 但是,它无法适应所有可能的故障配置,并且在极少数情况下,需要手动干预来补救结果。

该协议需要一个协调节点,它基本上协调和监督不同节点之间的交易。 协调器试图分两个阶段在一组进程之间建立共识,因此得名。

> 两阶段提交包括以下阶段


- `准备阶段` Prepare phase


准备阶段涉及协调器节点从每个参与者节点收集共识。
除非每个节点都响应它们已准备好,否则事务将被中止。


- `提交阶段` Commit phase


如果所有参与者都向协调器响应他们已准备好,那么协调器将要求所有节点提交事务。
如果发生故障,事务将被回滚



> 两阶段提交协议可能会出现以下问题:


    如果其中一个节点崩溃怎么办?

    如果协调器本身崩溃了怎么办?

    它是一个阻塞协议
  • Three-phase commit (3PC) 三阶段提交

三阶段提交 (3PC) 是两阶段提交的扩展,其中提交阶段分为两个阶段。 这有助于解决两阶段提交协议中出现的阻塞问题

> 三阶段提交包括以下阶段


- `Prepare phase` 准备阶段

此阶段与两阶段提交相同。

- `Pre-commit phase` 预提交阶段

协调器发出预提交消息,所有参与节点都必须确认它。
如果参与者未能及时收到此消息,则交易将中止。

- `Commit phase` 提交阶段

这一步也类似于两阶段提交协议


> 为什么预提交阶段有帮助

如果在这个阶段找到了参与者节点,则意味着每个参与者都完成了第一阶段。
准备阶段的完成是有保证的。 每个阶段现在都可以超时并避免无限期等待
  • Sagas

saga 是一系列本地事务

每个本地事务更新数据库并发布消息或事件以触发 saga 中的下一个本地事务。

如果本地事务因为违反业务规则而失败,则 saga 会执行一系列补偿事务,以撤消先前本地事务所做的更改。

协调的实现方式有两种:

每个本地事务都会发布触发其他服务中本地事务的域事件。

编排器告诉参与者要执行哪些本地事务。

问题

Saga 模式特别难调试。
  
参与者之间存在循环依赖的风险。
  
缺乏参与者数据隔离带来了持久性挑战。
  
测试很困难,因为所有服务都必须运行以模拟事务。


Sharding 分片

Data Partitioning 数据分区

数据分区是一种将数据库分解成许多较小部分的技术。

它是在多台机器上拆分数据库或表以提高数据库的可管理性、性能和可用性的过程。

  • 方法 Methods

有许多不同的方法可以用来决定如何将应用程序数据库分解为多个较小的数据库。

以下是各种大型应用程序使用的最流行的方法:

- `水平分区`(或`分片`)

在该策略中,我们根据分区键定义的取值范围`水平拆分表数据`。 它也称为`数据库分片 database sharding`。


- `垂直分区`

在垂直分区中,我们根据列对数据进行垂直分区。

我们将表划分为元素较少的相对较小的表,每个部分都存在于一个单独的分区中。

什么是分片?

分片是一种与水平分区相关的数据库架构模式,它是将一个表的行分成多个不同表的做法,称为分区或分片。

每个分区都有相同的模式和列,但也有共享数据的一个子集。 同样,每个分区中保存的数据都是唯一的,并且独立于其他分区中保存的数据。

数据分片的理由是,在某个点之后,通过添加更多机器来水平扩展比通过添加强大的服务器来垂直扩展更便宜、更可行。 分片可以在应用程序或数据库级别实现

划分标准

有大量的标准可用于数据分区。 一些最常用的标准是:

  • Hash-Based 基于散列

该策略基于哈希算法将行划分为不同的分区,而不是基于连续索引对数据库行进行分组。

这种方法的缺点是动态添加/删除数据库服务器变得昂贵。
  • List-Based 基于列表

在基于列表的分区中,每个分区都是根据列上的值列表而不是一组连续的值范围来定义和选择的。

  • Range Based 基于范围

范围分区根据分区键值的范围将数据映射到各个分区。 换句话说,我们以这样一种方式对表进行分区,即每个分区都包含由分区键定义的给定范围内的行。

范围应该是连续的但不重叠,其中每个范围指定一个分区的非包含下限和上限。 任何等于或高于范围上限的分区键值都将添加到下一个分区。

  • Composite 合成的

顾名思义,复合分区基于两种或多种分区技术对数据进行分区。 这里我们首先使用一种技术对数据进行分区,然后使用相同或其他方法将每个分区进一步细分为子分区

分片优缺点

优点

可用性:为分区数据库提供逻辑独立性,确保我们应用程序的高可用性。 在这里可以独立管理各个分区。

可扩展性:证明可以通过跨多个分区分布数据来提高可扩展性。

安全性:通过将敏感和非敏感数据存储在不同的分区中来帮助提高系统的安全性。 这可以为敏感数据提供更好的可管理性和安全性。

查询性能:提高系统的性能。 现在系统不必查询整个数据库,而只需查询一个较小的分区。

数据可管理性:将表和索引划分为更小且更易于管理的单元。

缺点

复杂性:分片通常会增加系统的复杂性。

跨分片连接:一旦数据库被分区并分布在多台机器上,执行跨多个数据库分片的连接通常是不可行的。 由于必须从多个服务器检索数据,因此此类连接的性能效率不高。

重新平衡:如果数据分布不均匀或单个分片上有很多负载,在这种情况下,我们必须重新平衡我们的分片,以便请求尽可能平均地分布在分片之间。

什么时候使用分片

利用现有硬件而不是高端机器。

在不同的地理区域维护数据。

通过添加更多分片来快速扩展。

更好的性能,因为每台机器的负载都更少。

当需要更多并发连接时。


Consistent Hashing 一致性哈希

为什么要有 一致性哈希?

在传统的基于散列的分发方法中,我们使用散列函数来散列我们的分区键(即请求 ID 或 IP)。

然后,如果我们对节点(服务器或数据库)的总数使用模数。 这将为我们提供我们想要路由请求的节点。

key:请求ID或IP。

H:哈希函数结果。

N:节点总数。

节点:请求将被路由到的节点。

这样做的问题是,如果我们添加或删除一个节点,它会导致 N 发生变化, 这意味着我们的映射策略将会中断,因为相同的请求现在将映射到不同的服务器。 因此,大多数请求将需要重新分配,这是非常低效的。

我们希望在不同的节点之间统一分配请求,这样我们应该能够以最小的努力添加或删除节点。 因此,我们需要一种不直接依赖于节点(或服务器)数量的分配方案,以便在添加或删除节点时, 需要重新定位的键的数量最少。

一致性哈希通过确保每次我们向上或向下扩展时,不必重新安排所有密钥或接触所有服务器, 从而解决了这个水平可扩展性问题。

一致性哈希 如何工作的

Consistent Hashing 是一种分布式哈希方案,它独立于分布式哈希表中的节点数量运行, 通过为它们分配一个抽象圆或哈希环上的位置。

这允许服务器和对象在不影响整个系统的情况下进行扩展。

» Details consistent-hashing


Database Federation 数据库联合

数据库联合(或功能分区)按功能拆分数据库。 使几个不同的物理数据库作为一个逻辑数据库出现在最终用户面前。

联合模式中的所有组件都通过一个或多个联合模式联系在一起,这些模式表达了整个联合模式数据的共性。 这些联合模式用于指定可由联合组件共享的信息,并为它们之间的通信提供公共基础。

联合数据库的一些关键特征:

透明度:联合数据库掩盖了用户差异和底层数据源的实现。 因此,用户不需要知道数据存储在哪里。

异质性:数据源可以在许多方面有所不同。 联合数据库系统可以处理不同的硬件、网络协议、数据模型等。

可扩展性:可能需要新的资源来满足不断变化的业务需求。 一个好的联合数据库系统需要使添加新源变得容易。

自治:联合数据库不会更改现有数据源,接口应保持不变。

数据集成:联合数据库可以集成来自不同协议、数据库管理系统等的数据。

优点

灵活的数据共享。

数据库组件之间的自治。

统一访问异构数据。

应用程序与遗留数据库没有紧密耦合。

缺点:

添加更多硬件和额外的复杂性。

连接来自两个数据库的数据很复杂。

对自主数据源的依赖。

查询性能和可扩展性。


Buy me a 肥仔水!