微服务架构中,每个服务都有自己的独立数据库。
然而现在有个需求,需要生成一张实时的报表,该报表包含两个服务的数据。
如服务A,服务B。B中仅包含A的主键id作为关联。
而此报表的搜索条件包含A服务实体中的字段也包含B服务实体中的字段。
现有方案
1、如果搜索条件中包含A的条件,则先去服务A中搜索,得到所有结果的主键,在服务B中使用where A.id IN (ids) 再次查询
想法:当A.id数量庞大时,这个查询极其缓慢! 而A.id数量庞大的情况很多
2、使用搜索引擎
想法:感觉杀鸡用牛刀
请教各位大牛有更好的方案吗
泻药
如果是线上业务数据(OLTP),那么方案一是微服务的标准做法。如果线上要频繁做这种关联的查询,就说明两个服务(及其两个库)的耦合非常严重,那当初何必要把它们拆开来呢?
如果是分析报表,那就属于OLAP范畴了,方案二确实是一种可取的方案。如果使用搜索引擎觉得杀鸡用牛刀的话,不妨试试在从库上做各种报表分析操作,比如线上的A库和B库都实时同步到一个只读库中,然后在只读库里JOIN一下就搞定了。
微服务的一个设计原则是业务没有关联的服务拆开成单独的服务,你这个业务之间有交叉了。
其实这种问题在微服务中很常见,比如说需要通过商品上的一些信息查询订单,订单和商品分别属于两个微服务,该类问题的解决方案除了你自己两种方案,还有
将数据聚合放入数据仓库,实时聚合A和B中的数据放入另外一个库中(不一定是mysql,也可以是Hbase),报表拉的数据都从数据仓库中拉去
表设计的时候适当冗余一些字段,就如你说的在B上可预见性的冗余一些A的字段
方法1有一个很致命的缺点,一旦涉及到分页,这种方式必定不可行.具体采用哪种方案,还是需要根据你的数据对应的数量级来决定,如果对应的数据量不是很大,可以采用方法1,如果速度比较慢,可以多开几个线程分批捞相应的数据(id数量太多分批拉,批量查询都是可以减少超时情况和时间的有效解决方案);如果数据量很大,建议采用数据仓库的方式,采用数据仓库的主要好处是,对主库不会产生压力,因为聚合表的产生可以通过Binlog来获取;因为报表还是属于离线数据的范畴,如果真的需要像订单查询那样实时,效率很高期间还伴随着状态的该表,并且搜索条件巨多无比,那么搜索引擎是一个很好的选择
所以,可以根据实际情况采用方法1和方法3
生成报表这样的需求就不应该放在业务数据库系统中,你可以在后端做一套otter汇聚库,实时同步多个服务的数据进来,然后在这个汇聚库中你想怎么玩就怎么玩