在分布式架构体系下,不同服务都有各自的数据库,但是数据之间一定是有关系的,服务A要用服务C的数据库,就必须通过服务C提供的接口来获取,这是基本机制,不然拆分服务和库就没意义了,这样就会导致服务间产生依赖关系。
如上图,如果订单服务和论坛服务同时依赖用户服务,那么就要考虑如果用户服务挂掉,会影响多大的范围,做好权衡,还有一个关键点,如果多个服务依赖一个服务,那么就要保证被依赖的服务有足够的能力应对,例如这里,如果订单服务有10W的流量,论坛服务有10W的流量,那么就要保证部署上用户服务起码要能承受20W的流量。
2、分布式事务既然数据库在不同的服务下面,服务之间又存在依赖关系,那么保证数据的事务一致性就是非常大的难题。
这里基于支付业务的转账场景做一个简单的演示,从数据源1的账户表中,向数据源2的账户表中操作转账,尽管在代码层面看添加了事务最高级别的控制,但是却没有起到控制作用,导致出账成功,但是入账失败,这就是典型的分布式事务问题。
@Service public class AccountServiceImpl implements AccountService { @Resource private JdbcTemplate jdbcTemplateOne ; @Resource private JdbcTemplate jdbcTemplateTwo ; /** * @param fromUser 出账 账户 * @param toUser 入账 账户 * @param money 涉及 金额 */ @Transactional(isolation= Isolation.SERIALIZABLE) @Override public void transfer(String fromUser, String toUser, int money) { // fromUser 出账 jdbcTemplateOne.update( "UPDATE user_account SET money = money-? WHERE username= ?", new Object[] {money, fromUser}); int i = 1/0 ; // toUser 入账 jdbcTemplateTwo.update( "UPDATE user_account SET money = money+? WHERE username= ?", new Object[] {money, toUser}); } }这里只是先演示分布式事务的问题,如何解决分布式事务问题,需要很多的篇幅描述,后面的连续几篇文章再细说。
四、源代码地址 GitHub·地址 https://github.com/cicadasmile/data-manage-parent GitEE·地址 https://gitee.com/cicadasmile/data-manage-parent推荐阅读:架构设计系列
序号 标题00 架构设计:单服务.集群.分布式,基本区别和联系
01 架构设计:分布式业务系统中,全局ID生成策略
02 架构设计:分布式系统调度,Zookeeper集群化管理
03 架构设计:接口幂等性原则,防重复提交Token管理
04 架构设计:缓存管理模式,监控和内存回收策略
05 架构设计:异步处理流程,多种实现模式详解
06 架构设计:高并发流量削峰,共享资源加锁机制