使用微服务架构时如何保持数据库同步?
How to keep DB in sync when using microservices architecture?
我即将了解微服务架构的工作原理。到目前为止,我不明白每个微服务都需要自己的数据库,这是有道理的。
假设我们有一个客户微服务,它负责创建客户并返回客户列表。该服务当然会有自己的客户数据库。
假设我们在此服务上的负载非常高,因此我们选择横向扩展 20 倍。
我们有 20 个微服务,每个都有自己的数据库,所有服务都在负载均衡器后面。
现在客户端要创建客户,负载均衡器将客户端请求发送到服务 9/20,客户创建完成。
在下一个请求中,同一客户希望确保已创建客户并希望查看客户列表,在请求 LB 将他发送到服务 11/20 时。
现在我如何确保服务 9/20 将新创建的客户同步到服务 11/20 的数据库?
在 MSSQL 中有在允许初始提交之前保持数据库同步的功能,首先将数据保存在所有其他数据库中,但是这种方法会在较长的 运行 中产生问题,因为服务越多,提交的时间就越长?
each microservice need its own database
每个微服务一个单独的数据库不是先决条件(也不是要求,真的)。
您可以根据需要在同一数据库上运行任意数量的微服务,但例如使用不同的架构。
微服务的有界上下文应该是边界。
Lets say we have very high load on this service, so we choose to scale out 20x.
扩展到相同微服务的 (X) 个实例并不意味着每个相同服务的每个实例都必须有一个单独的数据库。
大多数数据库在设计时都考虑了并发连接、用户和事务。单个数据库实例(具有一定的乐观并发性)可以优雅地处理数百个(如果不是数千个)并发连接。
如果您明确选择为同一服务的每个实例使用一个单独的数据库,那么您将不得不同步这些数据库。而且,数据一致性很可能会因此受到影响。
这里有一些建议:
无论有多少实例在使用它,每个微服务(而不是每个实例)都使用一个数据库。当您确定单个数据库无法处理负载时,才考虑每个实例一个数据库。
在数据库之上使用共享缓存层(可能是redis缓存)
使用数据库集群来处理高 load/availability 数据库。
这可以使用 CQRS 设计模式来实现,该模式通过遵循异步范例将实体的创建和查看分开。
创建时,我们将实体持久性推送到 Kafka/RabbitMQ 并将其异步推送到数据库。可以在数据库上创建实体化视图,这使得检索速度更快。
虽然可以为多个服务使用同一个数据库,但应避免这样做,因为它会在服务之间创建比预期更高的耦合度。例如。数据库停机会影响所有共享服务,但如果每个服务都有自己的服务,则只会影响一个服务。
为避免 "distributed monolith" 服务彼此同步调用(例如使用 REST),您可以使用基于流的方法。每当其数据更改时,每个服务都会发布一个更改事件,其他服务可以订阅这些流。因此他们可以对与他们相关的数据变化做出反应,例如通过在他们自己的数据库中存储数据的本地版本(以适合他们需要的表示形式,例如,只是他们感兴趣的列)。这样他们就可以提供他们的功能,即使其他服务在一段时间内不可用。自然地,这种架构采用了最终一致性的语义,但通常这在分布式系统中是不可避免的。
设置此类数据流的一种方法是更改数据捕获 CDC,它将跟踪数据库日志文件(例如 MySQL 中的 binlog)并为每个 INSERT、UPDATE 和 DELETE 发布相应的事件。一个开源 CDC 工具是 Debezium,它带有用于 MySQL、Postgres、MongoDB 以及(目前正在进行中的)Oracle 和 SQL Server 的连接器.它可以与 Apache Kafka 一起用作流 backbone 或作为 Java 应用程序中的库,允许您仅使用少量代码将数据更改流式传输到其他流层,例如 Pulsar 或 Kinesis。为更改事件使用持久性主题的一个好处,例如对于 Kafka,是新服务可以出现并重新读取整个更改流(取决于主题的保留策略),或者只是获取每条记录的当前状态以做本地数据库的初始种子。
(免责声明:我是 Debezium 的负责人)
使用多个数据库只会改变分布式协调的一个软件架构问题,恕我直言,后者是一个更困难的问题。
人们建议使用事件系统,这意味着现在每个服务都必须有自己的分布式数据协调小解决方案,ACID 出局 window。看看数据库格局,您会发现这不是一个容易或完全解决的问题。然后去分布式协调事务...
有很多次您宁愿停机也不愿让 N 个数据库处于完全未知的不一致状态。此外,对正常运行时间的看法具有误导性,是的,您的服务正常运行,但如果它们对相同数据或丢失数据(丢失事件)的看法不一致,它们是否真的在运行?还是它们会产生不一致和错误的结果?
要么你有两个完全不依赖于拥有相同数据的服务,要么你需要一个共享的一致数据层。但是使用事件系统在 N 个数据库之间复制并希望得到最好的选择。
分布式、持久化、一致性和可用性的问题应该在存储层处理,而不是应用层的每个服务临时处理。建立这样一个系统需要许多人的谨慎和专业知识,即使那样也有不同的风格和权衡(CAP 定理)。
最后:大多数人希望微服务能够比通过单体更快地开发和改进他们的应用程序。在每个微服务中处理分布式协调和存储的一致性会适得其反。
我即将了解微服务架构的工作原理。到目前为止,我不明白每个微服务都需要自己的数据库,这是有道理的。
假设我们有一个客户微服务,它负责创建客户并返回客户列表。该服务当然会有自己的客户数据库。
假设我们在此服务上的负载非常高,因此我们选择横向扩展 20 倍。
我们有 20 个微服务,每个都有自己的数据库,所有服务都在负载均衡器后面。
现在客户端要创建客户,负载均衡器将客户端请求发送到服务 9/20,客户创建完成。
在下一个请求中,同一客户希望确保已创建客户并希望查看客户列表,在请求 LB 将他发送到服务 11/20 时。
现在我如何确保服务 9/20 将新创建的客户同步到服务 11/20 的数据库?
在 MSSQL 中有在允许初始提交之前保持数据库同步的功能,首先将数据保存在所有其他数据库中,但是这种方法会在较长的 运行 中产生问题,因为服务越多,提交的时间就越长?
each microservice need its own database
每个微服务一个单独的数据库不是先决条件(也不是要求,真的)。
您可以根据需要在同一数据库上运行任意数量的微服务,但例如使用不同的架构。
微服务的有界上下文应该是边界。
Lets say we have very high load on this service, so we choose to scale out 20x.
扩展到相同微服务的 (X) 个实例并不意味着每个相同服务的每个实例都必须有一个单独的数据库。
大多数数据库在设计时都考虑了并发连接、用户和事务。单个数据库实例(具有一定的乐观并发性)可以优雅地处理数百个(如果不是数千个)并发连接。
如果您明确选择为同一服务的每个实例使用一个单独的数据库,那么您将不得不同步这些数据库。而且,数据一致性很可能会因此受到影响。
这里有一些建议:
无论有多少实例在使用它,每个微服务(而不是每个实例)都使用一个数据库。当您确定单个数据库无法处理负载时,才考虑每个实例一个数据库。
在数据库之上使用共享缓存层(可能是redis缓存)
使用数据库集群来处理高 load/availability 数据库。
这可以使用 CQRS 设计模式来实现,该模式通过遵循异步范例将实体的创建和查看分开。
创建时,我们将实体持久性推送到 Kafka/RabbitMQ 并将其异步推送到数据库。可以在数据库上创建实体化视图,这使得检索速度更快。
虽然可以为多个服务使用同一个数据库,但应避免这样做,因为它会在服务之间创建比预期更高的耦合度。例如。数据库停机会影响所有共享服务,但如果每个服务都有自己的服务,则只会影响一个服务。
为避免 "distributed monolith" 服务彼此同步调用(例如使用 REST),您可以使用基于流的方法。每当其数据更改时,每个服务都会发布一个更改事件,其他服务可以订阅这些流。因此他们可以对与他们相关的数据变化做出反应,例如通过在他们自己的数据库中存储数据的本地版本(以适合他们需要的表示形式,例如,只是他们感兴趣的列)。这样他们就可以提供他们的功能,即使其他服务在一段时间内不可用。自然地,这种架构采用了最终一致性的语义,但通常这在分布式系统中是不可避免的。
设置此类数据流的一种方法是更改数据捕获 CDC,它将跟踪数据库日志文件(例如 MySQL 中的 binlog)并为每个 INSERT、UPDATE 和 DELETE 发布相应的事件。一个开源 CDC 工具是 Debezium,它带有用于 MySQL、Postgres、MongoDB 以及(目前正在进行中的)Oracle 和 SQL Server 的连接器.它可以与 Apache Kafka 一起用作流 backbone 或作为 Java 应用程序中的库,允许您仅使用少量代码将数据更改流式传输到其他流层,例如 Pulsar 或 Kinesis。为更改事件使用持久性主题的一个好处,例如对于 Kafka,是新服务可以出现并重新读取整个更改流(取决于主题的保留策略),或者只是获取每条记录的当前状态以做本地数据库的初始种子。
(免责声明:我是 Debezium 的负责人)
使用多个数据库只会改变分布式协调的一个软件架构问题,恕我直言,后者是一个更困难的问题。
人们建议使用事件系统,这意味着现在每个服务都必须有自己的分布式数据协调小解决方案,ACID 出局 window。看看数据库格局,您会发现这不是一个容易或完全解决的问题。然后去分布式协调事务...
有很多次您宁愿停机也不愿让 N 个数据库处于完全未知的不一致状态。此外,对正常运行时间的看法具有误导性,是的,您的服务正常运行,但如果它们对相同数据或丢失数据(丢失事件)的看法不一致,它们是否真的在运行?还是它们会产生不一致和错误的结果?
要么你有两个完全不依赖于拥有相同数据的服务,要么你需要一个共享的一致数据层。但是使用事件系统在 N 个数据库之间复制并希望得到最好的选择。
分布式、持久化、一致性和可用性的问题应该在存储层处理,而不是应用层的每个服务临时处理。建立这样一个系统需要许多人的谨慎和专业知识,即使那样也有不同的风格和权衡(CAP 定理)。
最后:大多数人希望微服务能够比通过单体更快地开发和改进他们的应用程序。在每个微服务中处理分布式协调和存储的一致性会适得其反。