HTML5技术

高性能、高可用、高扩展、分布式ERP系统架构设计 - 刘彻(2)

字号+ 作者:H5之家 来源:H5之家 2017-12-03 15:03 我要评论( )

很显然,传统一个数据库中,我们只需要简单的join操作,即可关联这两张表,外加关联品类和仓库表即可查询出我们所要的数据。但是现在我们的架构中,物料表和商品表不在同一个数据库实例中,我们不能使用join操作了

        很显然,传统一个数据库中,我们只需要简单的join操作,即可关联这两张表,外加关联品类和仓库表即可查询出我们所要的数据。但是现在我们的架构中,物料表和商品表不在同一个数据库实例中,我们不能使用join操作了,那我们该怎么实现需求呢?

        新的架构,只允许我们通过对方的服务接口来获取数据,不能直接关联对方服务的私有数据库。至少从架构上,服务化角度来说不能直接访问对方服务的数据库。这种情况下,假设web模块子系统调用仓库子系统来获取数据,则我们需要在仓库模块中创建一个service方法来装配这些数据。然后返回给web子系统。如下图所示,仓库管理方法首先获取本地库存表的物料编码、和仓库表的仓库名称字段信息,并且分页完后最终准备返回20条数据到Web模块前,将这20条数据中的物料ID作为参数请求商品模块子系统,商品子系统返回这20个物料ID相关的商品信息给到仓库管理模块,然后仓库管理模块重新组装上列表所需的物料名称和品类两个字段数据,实现最终要返回给Web子系统的数据。

        也许你会说,这太麻烦了,这种方法的性能肯定没有直接join来的高,解决不了性能问题。咋看起来好像是这么回事,但是仔细考虑看看,在系统并发量低、数据量小、业务不算繁忙的环境下,的确性能还不如传统一个数据中join方式来的快速。但我们想想以后吧!我们现在的架构设计是将一个数据库拆成多个数据库,每个数据库可以运行在单独的服务器上去,这样以后就能负载数据库的压力了。整体来说这样才能不会让数据库成为未来业务繁忙时候的性能瓶颈了。想想都觉得让人兴奋不已,是不是?

       这时候有人又会问,那以后系统数据量、业务更大了,连你这个拆分成几个数据库还不够用怎么办呢?我的方法是,可以基于拆分的数据库,单独每个库可以做读写分离、使用缓存等。甚至可以继续拆分下去,将子系统再次拆分成多个孙子系统。视业务模块繁忙程度而定。

报表系统

        有人又会问,有些列表查询逻辑非常复杂,关联十多张表,如果按上述方法拆分数据,那简直是灾难啊!是的,你说的没有错。这种情况下我的方案是将这种更加复杂的报表级别的数据查询展示需求,可以单独做个报表系统。报表数据库设计采用数据仓库方式。为了更高的读取性能,我们可以将数据库表设计成很多冗余字段方式也就是反范式设计,以及建立非常多的组合索引。

       这种系统成功的关键就是数据和主ERP系统业务库的同步问题了。一般可以写一个定时同步程序,将ERP主业务系统的数据经过帅选、转化等方式直接生成报表视图所需的最终或中间数据,简化关联查询。报表系统也可以采用微服务架构设计。如下图所示:

        如果报表所需的数据要求实时的,我们可以让ERP系统业务操作时,触发同步数据的请求,实时同步至报表库。

分布式事务

       也许有人又又问了,ERP系统很多操作都要求事务性,你拆分系统后怎么实现事务性,保障数据一致性呢?

这个问题很好,也是我决定写这篇文章前思考的最后一个问题。在微服务架构中,实现夸服务的事务并不容易,至少不像本地应用使用本地数据库事务那样方便,性能高效,数据一致性好。

        也许你听过分布式事务这个概念。有两种情景,一种是一个应用中使用多个数据库,为保障数据一致性,需要使用分布式事务。还有一种情况就是针对我们这个架构而言的。微服务环境下的分布式事务,具体来说打个比方。采购入库这个操作设计在仓库管理服务中。入库后,需要更新采购子系统中的采购单中的入库数量。这个过程要求数据一致性,也就是采购单入库成功后写入了库存表中的数量,同时要更新采购单表中的入库数量。我们不能直接在仓库服务中去访问采购服务中的数据库,必须通过采购服务提供的服务接口才行。如果这样,我们怎么能保证数据一致性呢?因为很有可能库存表写入成功,但调取采购服务写入采购单数据时失败了。可能是网络问题原因导致的,这样数据就不一致了。

       在分布式事务技术中,有实现最终一致性这么一说,意思就是只要我能保证两边数据最终实现了一致性就行,不一定要使用事务。这样说来就有方案了。如仓库子系统在处理采购入库时需要增加入库单数据和更新库存数据等多个表。这多个表都在仓库子系统中,我们可以使用一个本地事务来保证仓库子系统中的表数据一致性。然后调用采购子系统更新采购单里的入库数量。为了防止这个过程突然中断导致调用失败,我们考虑增加一个消息队列中间件如ActiveMQ。如果接口返回失败我们就往MQ里写入这个处理请求,等到采购子系统恢复正常后,MQ通知采购子系统处理这个更新操作。由于消息消费掉以后不会再有通知了,采购子系统处理过程中发生异常导致更新失败,需要将问题写入本地的日志库,以便通知管理员做后续补偿处理。就这样通过各种办法来达到数据的最终一致性即可。虽然听上去有点坑,但这就是解决方案。没有其他更好的了。或者更新失败后重新调用仓库子系统回滚入库单和库存数据,达到最终一致性!如图所示:

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 一个高性能、轻量级的分布式内存队列系统--beanstalk - 静儿1986

    一个高性能、轻量级的分布式内存队列系统--beanstalk - 静儿1986

    2017-10-12 11:01

  • [高并发]EntityFramework之高性能扩展 - Never、C

    [高并发]EntityFramework之高性能扩展 - Never、C

    2017-07-07 10:02

  • 轻量级高性能ORM框架:Dapper高级玩法 - 云中客

    轻量级高性能ORM框架:Dapper高级玩法 - 云中客

    2017-07-02 13:02

  • 高性能迷你React框架anu在低版本IE的实践 - 司徒正美

    高性能迷你React框架anu在低版本IE的实践 - 司徒正美

    2017-06-14 09:01

网友点评
l