微服务拆分治理最佳实践

背景
部门中维护了一个老系统,功能都耦合在一个单体应用中(300+接口),表也放在同一个库中(200+表),导致系统存在很多风险和缺陷 。经常出现问题:如数据库的单点、性能问题,应用的扩展受限,复杂性高等问题 。
从下图可见 。各业务相互耦合无明确边界,调用关系错综复杂 。

微服务拆分治理最佳实践

文章插图
 
随着业务快速发展,各种问题越来越明显,急需对系统进行微服务改造优化 。经过思考,整体改造将分为三个阶段进行:
 
  • 数据库拆分:数据库按照业务垂直拆分 。
  • 应用拆分:应用按照业务垂直拆分 。
  • 数据访问权限收口:数据权限按照各自业务领域,归属到各自的应用,应用与数据库一对一,禁止交叉访问 。
 
微服务拆分治理最佳实践

文章插图
 
数据库拆分
单体数据库的痛点:未进行业务隔离,一个慢sql易导致系统整体出现问题;读写压力大,性能下降;
数据库改造
微服务拆分治理最佳实践

文章插图
 
根据业务划分,我们计划将数据库拆分为9个业务库 。数据同步方式采用主从复制的方式,我们提前整理好表和新数据库的对应关系交给运维同学,运维同学通过binlog过滤将对应的表和数据同步到对应的新数据库中,每个新数据库中只包含自己业务的表 。
代码改造方案
如果一个接口中操作了多张表,之前这些表属于同一个库,数据库拆分后可能会分属于不同的库 。所以需要针对代码进行相应的改造 。
目前存在问题的位置:
 
  • 数据源选择:系统之前是支持多数据源切换的,在service上添加注解来选择数据源 。数据库拆分后出现的情况是同一个service中操作的多个mApper从属于不同的库 。
  • 事务:事务注解目前是存在于service上的,并且事务会缓存数据库链接,一个事务内不支持同时操作多个数据库 。
 
改造点梳理:
 
  • 同时写入多个库,且是同一事务的接口6个:需改造数据源,需改造事务,需要关注分布式事务;
  • 同时写入多个库,且不是同一事务的接口50+:需改造数据源,需改造事务,无需关注分布式事务;
  • 同时读取多个库 或 读取一个库写入另一个库的接口200+:需改造数据源,但无需关注事务;
  • 涉及多个库的表的联合查询8个:需进行代码逻辑改造
 
梳理方式:
采用部门中的切面工具,抓取入口和表的调用关系(可识别表的读/写操作),找到一个接口中操作了多个表,并且多个表分属于不同业务库的情况;
分布式事务:
进行应用拆分和数据访问权限收口之后,是不存在分布式事务的问题的,因为操作第二个库会调用对应系统的RPC接口进行操作 。所以本次不会正式支持分布式事务,而是采用代码逻辑保证一致性的方式来解决;
方案一
微服务拆分治理最佳实践

文章插图
 
将service中分别操作多个库的mapper,抽取成多个service 。分别添加切换数据源注解和事务注解 。
问题:改动位置多,涉及改动的每个方法都需要梳理历史业务;service存在很多嵌套调用的情况,有时难以理清逻辑;修改200+位置改动工作量大,风险高;
方案二
微服务拆分治理最佳实践

文章插图
 
如图所示,方案二将数据源注解移动到Mapper上,并使用自定义的事务实现来处理事务 。
将多数据源注解放到Mapper上的好处是,不需要梳理代码逻辑,只需要在Mapper上添加对应数据源名称即可 。但是这样又有新的问题出现,


推荐阅读