场景
设想正在使用微服务架构模式开发一个在线商店应用。大多数服务需要持久化数据到某种类型的数据库中。例如,订单服务存储订单相关信息以及用户信息存储用户相关信息。
问题
微服务应用中的数据库架构是什么样的?
约束条件
服务必须是松耦合的,这样才能够独立地开发、部署和扩展这些微服务。
必须保持某些跨多个服务的业务事务的不变性。例如,下订单用例必须验证新订单不会超出用户信用额度限制。某些业务事务必须更新由多个服务拥有的数据。
某些业务事务需要查询由不同服务拥有的数据。例如,查看可用信用额度用例必须查询用户服务来查找信用额度限制以及订单服务来计算未完成订单总数量。
某些查询必须关联由多个服务拥有的数据。例如,查找属于特定区域的用户以及他们最近一段时间的订单,需要关联用户和订单。
有时候为了扩展,数据库必须可以被复制和共享。
不同服务有不同的数据存储要求。对于某些服务,关系型数据库是最好的选择。其它服务可能需要NoSQL数据库比如MongoDB(擅长存储复杂、非结构化数据)或Neo4J(能高效地存储以及查询图形数据)。
解决方案
使用被多个服务共享的单个数据库。每个服务自由地使用本地ACID事务访问由其它服务拥有的数据。
实例
订单服务和用户服务自由地访问彼此的表。例如,订单服务能够使用下面的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事务来实施数据一致性。
单个数据库比较容易操作。
该模式的弊端:
开发时间上的耦合 —— 某个开发人员致力于,例如,订单服务,会需要与其它服务访问相同表的开发人员协调schema相关更改。
运行时耦合 —— 因为所有的服务访问相同的数据库,他们可能会互相干扰。例如,如果长时间运行的用户服务事务保有在ORDER表上的某个锁,那么订单服务将会被阻塞。
单个数据库可能不会满足所有服务的数据存储和访问的需求。