背景
假设你正在采用微服务架构构建一个在线商城。大多数服务需要将数据持久化到数据库。例如,订单服务
存储订单信息,客户服务
存储客户信息
问题
微服务应用的数据库架构是什么?
限制
- 服务必须松散耦合,因此它们可以独立的开发,部署和扩展
- 某些业务事务必须强制跨多个服务执行。比如,
Place Order
用例必须验证一个新订单没有超出客户的信用额度。其他业务服务,必须更新多个服务拥有的数据。 - 一些业务事务需要查询多个服务拥有的数据。比如,
View Available Credit
用例必须查询客户服务找出creditLimit
,查询订单服务计算未结算订单的总金额。 - 一些查询必须关联多个服务拥有的数据。比如,查询指定区域的顾客和他们最近的订单,需要顾客和订单的关联。
- 数据库有时必须复制和分区,以便扩展。参见Scale Cube。
- 不同服务拥有不同的数据存储需求。一些服务,关系型数据库是最好的选择。其他服务可能需要NoSQL数据库,比如MongoDB,因为它适合存储复杂的非结构化数据,或者Neo4J,它设计来有效存储和查询图形数据。
解决方案
使用一个(单一的)数据库共享给多个服务。每个服务自由的使用ACID事务访问被其他服务拥有的数据。
示例
OrderService
和CustomerService
自由的访问对方的表。比如,OrderService
可以采用如下的ACID事务确保一个新订单不会超出顾客的信用额度。
BEGIN TRANSACTION
…
SELECT ORDER_TOTAL
FROM ORDERS WHERE CUSTOMER_ID = ?
…
SELECT CREDIT_LIMIT
FROM CUSTOMERS WHERE CUSTOMER_ID = ?
…
INSERT INTO ORDERS …
…
COMMIT TRANSACTION
就算同时有多个事务尝试为相同的顾客创建订单,数据库也将保证信用额度不会超出,
结果
这个模式的优势:
- 开发人员使用熟悉和简单直接的ACID事务来实施数据一致性
- 单一数据库操作更简单
这个模式的弊端:
-
开发时耦合 - 比如,工作在
OrderService
的开发人员将需要与其他访问了相同表的开发人员协调schema变更。这个耦合和额外的协调将降低开发速度。 -
运行时耦合 - 由于所有服务访问相同的表,它们能潜在的影响彼此。比如,如果长时间运行的
CustomerService
事务获取了ORDER
表的锁,OrderService
将被阻塞。 -
单一数据库可能不能满足所有服务对数据存储和访问的需求。
相关模式
- 每服务每数据库 是个替代方案
网友评论