对于一个用户访问量比较大的互联网系统,当用户数达到一定数量时,系统总会存在瓶颈或处理极限,即很难做出快速响应,处理效率逐步低下。对于如何应对用户量不断增长的情形,较直观的方案就是采用分布式系统架构。所谓分布式系统架构,简单的理解就是原来由一台服务器处理的业务,现在分摊给多台服务器处理;原来由一组服务器组处理的业务,现在由多个服务器组处理。

     本文多讨论的分布式系统架构是基于如下场景考虑的:整个系统分为Global(全局)和ServerGroup(服务器组),系统中只有一个Global,但有多个ServerGroup。

     Global:有对应的数据库和应用程序模块,存储全局性的基础数据及架构配置信息,对系统起全局控制作用,并协调各ServerGroup进行统一业务处理。

     ServerGroup:系统根据指定的规则可以划分成若干个ServerGroup,每个ServerGroup负责指定范围内的业务逻辑处理。例如对于即时通讯系统,ServerGroup可能只负责指定账号号段的用户业务处理。每个ServerGroup都有自己的应用程序和数据库,但各ServerGroup的应用程序及数据库结构都是相同的,只是负责处理的业务范围不一样而已。随着业务的发展,ServerGroup的数量会逐步增加的。

     在这种情形下,难以避免Global和ServerGroup之间以及ServerGroup和ServerGroup之间的通讯问题,因为Global的有些逻辑可能会访问ServerGroup中数据库的表,而ServerGroup的有些逻辑又需要访问Global或其他ServerGroup中数据库的表。对于这些Global及ServerGroup之间模块通讯方式,大致可采取如下三种方案:

     方案一:全部采用Http/TCP等接口进行通讯

            

       从架构图上可以看出:

       Global中的模块并不直接方案ServerGroup中的数据库,而是采用通过ServerGroup中提供的“Group接口”进行访问。同样,ServerGroup中的模块也只是通过Global提供的“Global”接口进行方案,而不会直接连接Global中的数据库。

       这么做的好处有:

        a) 较好体现面向对象和分层的思想,Global和ServerGroup的内部底层处理逻辑对外透明,外界只通过接口进行访问,且接口是从业务级别进行定义的,并不关心内部访问了哪个数据库,操作了哪些表;

        b) 有利于Global或Pool的内部后续改造,例如后续Global可能会进行“全局数据库”的切割或划分,由现在的一个库演变成多个库,或者以后会跨机房部署等;

       但也有值得顾虑的地方:

        a) 通过HTTP/TCP等接口的方式效率是否会较低?安全性和稳定性能否得到保障?

        b) 对于特定的模块是否在开发上有一定困难,例如有些ServerGroup中的模块逻辑就适合在存储过程中实现,但存储过程中又需要访问处于Global数据库中的表;

       c) 当Global和ServerGroup之间有表级别的数据需要同步时,传输的数据量有点大;

       d) 以后Global和ServerGroup采用的数据库会发生变更怎么办?(由Oracle改为MySql)


     方案二:数据库连接(DBLink)与HTTP/TCP接口相结合

          

      当Global需要访问ServerGroup的逻辑时,仍通过ServerGroup提供的“Group接口”进行访问。但当ServerGroup需要访问Global中的数据时,就直接访问Global数据库。

      由于整个系统中只有一个Global,故可以在每个ServerGroup数据库中建立访问Global数据库的连接(DBLink),这样在ServerGroup的模块中就能轻易访问Global数据库的表。

      这么做开发上可能会简便一些,而且直接访问数据库可能效率和安全性稳定性上都有所提高。但总有点耦合得偏紧的感觉,可能不利于后续的维护和扩展。

     方案三:全部采用直接方案数据库的方式

       

    这是一种完全不采用接口通讯而直接访问数据库的方式。

    同方案二,在每个ServerGroup的数据库中会创建对Global数据库的DBLink,ServerGroup中模块对Global数据的访问都直接通过DBLink的方式,和访问本地数据库没太大的差异。

    在Global中也会存放各ServerGroup数据库的连接字符串(DB ConnectionString),当Global需要访问ServiceGroup的数据时,根据对应的数据库连接字符串直接连接到ServerGroup数据库进行表操作。

    该方案所有通讯都是直接访问数据库的方式,效率可能会有进一步的提升,但耦合性更加紧密了。

 

     对于这种分布式系统的模块通讯没太多的经验,有点不好取舍。全部采取接口的方式,可能看起来接口更加清晰,逻辑层次感强,屏蔽对数据层的操作,但HTTP/TCP等接口方式能否保证系统的正常运行?采用直接访问数据库的方式可能对于开发人员更直观,或许工作量小,风险小,局部看性能较高,但是否又违背了一些设计理念呢?

      敬请各位指教!