今年一直在和团队作微服务的架构改造(相关的一些详情,有兴趣的朋友,能够参见以前的这篇分享)。可是作过改造的朋友都知道 从“All-In-One” 到 “Micro-Service” 都须要迈过的一个坎,那就是垂直分库, 根据不一样的子服务,将数据库拆分为不一样的子服务库。前端
那么问题就来了,在开始作微服务改造前,我发如今摇旺的老系统中,有不少后台报表或者前端详情页所需的数据是经过SQL Join来完成的。可是,咱们微服务改造后,每一个服务背后的数据库已经在分布不一样的实例中了,因此咱们已经不能继续简单在SQL中使用join了,那么解决“跨库Join”就摆上了议事日程。数据库
经过讨论和调研,垂直分库后,对于“跨库查询”的解决,能够采用如下几个思路:缓存
1. 依赖字段较少:字段冗余架构
A库中的Tab1表须要关联B库中的Tab2表中的字段F, 咱们就将字段F冗余到表Tab1中,那么查询时候,Tab1和Tab2就不须要作Join,单独查A库中的Tab1表就能够解决问题。分布式
这是一个野路子,由于这是违反正常的范式设计的,但在依赖字段较少的状况下仍是能够解决问题的,达到空间来换取时间的目的。不过这个方法最大的短板在于2点: 1. 依赖字段不能太多,2. 数据一致性问题。Tab2中的F字段一但改变,必需要同步到Tab1中,不然就会引发脏数据的问题。因此,须要在业务代码创建必要的同步机制,若是出错,还须要考虑引入人工补偿。微服务
2. 依赖字段较多:表同步工具
在不少场景下,咱们字段的依赖是不少的,乃至查询的时候可能须要跨多张表,这个时候方法1就没法直接用了,咱们就须要进行表级别的数据同步,能够采用ETL工具来作到跨库的表同步。不过须要注意的是,数据同步不建议实时性太高,不然数据库的性能会受到比较大的影响。因此对于实时性不高的查询要求,表同步仍是比较奏效的。性能
3. 静态字段依赖:数据字典表设计
对于不一样库中的静态字段,能够创建一张数据字典表,能够将这类表在其余每一个数据库中均保存一份,从而避免跨库join查询。若是静态数据表中的某些字段数据须要修改,能够采用一套脚本统一更新。对象
4. 服务层代码进行数据组装
经过各类服务查询到一个数据集,经过代码进行二次组装,而后生成咱们须要返回给前端的对象。在实践过程当中,对于处理过的查询集,咱们能够将它们缓存在咱们的分布式缓存中,减小服务间的RPC调用次数和数据库的查询压力。同时,注意设置好过时时间,把控好数据一致性和有效性。
以上就是4种应对跨库Join的思路,实战中,必定是将这4类方案进行组合使用的,同时,须要注意的是,相比这些解决思路,更重要的是表结构的合理设计。不然要完全解决跨库是很困难的。
分布式事务的处理方式
除此以外,分库后,还有一个难题,就是分布式事务的处理。具体的事例,能够参见我以前的这两篇文章1和 文章2。里面会提到在微服务下,服务间事务回滚的几个思路,但愿对你们有用