系统拆分是单体程序向分布式系统演变的关键一步,也是很重要的一步,拆分的好坏直接关系到未来系统的扩展性、可维护性和可伸缩性等,拆分工作不难理解,但是如何正确拆分、有什么样的方法和原则能帮助我们拆分得到一个我们理想中的系统:高可用、可扩展、可维护、可伸缩的分布式系统。

MartinFowler的《重构改善既有代码的设计》一书给重构的定义:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。拆分也是在不改变系统行为的前提下,对系统进行各种拆解,所以可以看出拆分就是重构,是重构的一种方式。

这里主要从三个方面来分析系统拆分工作:拆分需求、拆分原则和拆分方法;

一、拆分需求

什么情况下系统才需要进行拆分? 当然并不是所有的系统都需要拆分,也并不是所有的系统都适合进行拆分,因为系统拆分是一个耗时、耗力又风险比较高的工作,在决定对系统进行拆分前,多问自己几次真的需要进行拆分吗?还有其它更好的方法吗?

拆分的需求主要来源于下面几个方面:

1、组织结构变化:从最初的一个团队逐渐成长并拆分为几个团队,团队按照业务线不同进行划分,为了减少各个业务系统和代码间的关联和耦合,几个团队不再可能共同向一个代码库中提交代码,必须对原有系统进行拆分,以减少团队间的干扰。

2、安全:这里所指的安全不是系统级别的安全,而是指代码或成果的安全,尤其是对于很多具有核心算法的系统,为了代码不被泄露,需要对相关系统进行模块化拆分,隔离核心功能,保护知识产权。

3、替换性:有些产品为了提供差异化的服务,需要产品具有可定制功能,根据用户的选择自由组合为一个完整的系统,比如一些模块,免费用户使用的功能与收费用户使用的功能肯定是不一样的,这就需要这些模块具有替换性,判断是免费用户还是收费用户使用不同的模块组装,这也需要对系统进行模块化拆分。

4、交付速度:单体程序最大的问题在于系统错综复杂,牵一发而动全身,也许一个小的改动就造成很多功能没办法正常工作,极大的降低了软件的交付速度,因为每次改动都需要大量的回归测试确保每个模块都能正确工作,因为我们不清楚改动会影响到什么,所以需要做大量重复工作,增加了测试成本。这时候就需要对系统进行拆分,理清各个功能间的关系并解耦。

5、技术需求:

1)单体程序由于技术栈固定,尤其的是比较庞大的系统,不能很方便的进行技术升级,或者说对引入新技术或框架等处于封闭状态;每种语言都有自己的特点,单体程序没有办法享受到其它语言带来的便利;对应到团队中,团队技术相对比较单一。

2)相比于基于业务的垂直拆分,基于技术的横向拆分也很重要,使用数据访问层可以很好的隐藏对数据库的直接访问、减少数据库连接数、增加数据使用效率等;横向拆分可以极大的提高各个层级模块的重用性。

6、业务需求:由于业务上的某些特殊要求,比如对某个功能或模块的高可用性、高性能、可伸缩性等的要求,虽然也可以将单体整体部署到分布式环境中实现高可用、高性能等,但是从系统维护的角度来考虑,每次改动都要重新部署所有节点,显然会增加很多潜在的风险和不确定定性因素,所以有时候不得不选择将那些有特殊要求的功能从系统中抽取出来,独立部署和扩展。

上面通过从团队、产品、交付、技术以及业务方面分析了系统拆分的需求,从更大的范围来看,拆分可以分为两种:纵向和横向。纵向拆分主要从业务角度进行,根据业务分割为不同的子系统;而横向拆分侧重于技术的分层,每个层级的技术侧重点不同,可以充分发挥和培养团队中每个人的技术特长。

二、拆分原则

有了拆分需求,下面就要对系统进行拆分了,面对动辄百万行代码的系统,我们从哪里下手呢?要注意哪些问题?等等一系列问题接踵而来,下面就介绍几个系统拆分的基本原则,可以帮助我们快速的开始对系统进行拆分:

1、业务优先:每个系统天然都会按业务功能分成多个模块,每个模块又包含许多业务相关的功能,在系统拆分时,我们就可以优先考虑按照业务边界进行切割,切割完成后再针对每个模块进行拆解,循序渐进,逐渐迭代深入,最终完成系统的拆解。这个过程类似庖丁解牛,要找到关节之处下刀,方能事半功倍。

2、循序渐进:系统拆分过程中包含两个非常重要的工作:拆分和测试。二者缺一不可,并且二者是并行进行的,一定要边拆分边测试。每一步拆分完成都要保证系统功能是完整的,保证系统的测试是完整的。拆分要小步前进,如此以来可以减少累计错误的发生。这一点在《重构》这本书中也讲到了。

3、兼顾技术:系统不能为了分布式而分布式,系统拆分的代价相当昂贵;当然如果有拆分的需要,我们也不能白白浪费这么好的学习机会:

重构:拆分过程不仅仅是业务梳理的过程,也是系统进行重构的过程。通过系统的重构我们可以使用一些模式让代码结构更清晰,具有更好的可读性,并且方便日后的修改。

分层:拆分可以让系统分解为许多功能单一的系统,这些系统可以根据需要使用不同的技术和架构进行实现,可以让熟悉不同技术的人做不同的事,工作更高效,产品质量也可以提高。比如那些熟悉UI技术的人可以专注用户体验方面的研发,那些JAVA,C++方面的专家就可以把精力放在服务端程序的开发上,而那些熟悉数据库技术的人就可以话更多精力在数据库的优化上,术业有专攻,合适的人做合适的事。

4、可靠测试:“重构之前,首先检查自己是否有一套可靠的测试机制”,这是MartinFowler在《重构》这本书中说到的,它同样对系统拆分有效。拆分是在对系统进行大手术,每一次的改动都要保证系统保持原来的行为不变。测试使得我有足够的信心进行下一步的拆分或重构,不至于在错误的道路上越走越远,以至于错误累积。测试与拆分如影随形,每一步都要有足够的测试。没有测试的拆分和重构我真的不敢想象结果会是什么样子。

三、拆分方法

前面介绍了那么多,都在为拆分做准备,如何进行拆分这才是重点。拆分分为数据拆分和功能拆分。数据拆分主要指数据库的拆分和数据访问对象的拆分。在系统拆分过程中,一般情况下我会先进行数据拆分,难后再进行功能拆分。

数据拆分

首先对数据库按照业务进行拆分,把需要拆分的业务的相关表放到一个新的数据库中,但是保持上层系统结构不变(如下图)。

数据库的拆分相对于业务的拆分来说比较容易,对系统的影响也容易判断。拆分数据库时,对于一些公共数据(既出现在A系统又出现在B系统或者其它系统的具有公共属性的数据表),可以分两步进行处理:

第一步、在A、B系统中保留两份相同的数据,注意这里指的是具有公共属性的表,不包括那些与业务相关的数据表,虽然业务数据也会被其它模块引用。拆分过程一定要把握好业务边界,只有定义清晰的业务边界才能拆分出具有清晰定义的模块,这一点非常重要。

第二步、处理公共数据,主要有两种方式:

1、        建立公共服务模块

将这部分数据连同业务拆分为独立的服务模块,通过API对外提供服务,在系统拆分或重构的过程中,很有必要首先将一些公共的基础功能拆分为基础服务。如果将系统拆分工作看作是一个主干,那构建公共服务模块的工作就是一些分支,拆分的过程需要处理大量的公共功能,因为拆分就是要将不相关的功能分开,把相关的功能合并的过程。做完这些公共模块的工作还是要回到主干继续下面的工作。

2、  对于不需要抽象为公共服务的数据,可以保持一定的数据冗余,但是冗余的数据拷贝数不要太多,这会对数据同步提出很高的要求;根据数据的不同使用不同的数据同步机制确保各个模块中数据的一致性,至于要实现强一致性还是最终一致性要根据业务需求来定,不同的数据库在数据一致性方面的都有相关的实现,这里不再赘述。

第三步:建立数据服务层,在拆分后的数据库基础之上建立一层数据服务层,对数据库访问进行封装和隐藏,对外提供数据访问接口。

功能拆分

完成数据拆分后,就可以开始业务的拆分;拆分过程中需要坚持一个基本原则:高内聚、低耦合。拆分的实际工作就是解耦,下面主要介绍基于Proxy-Façade模式的系统拆分方法:

1)找出A模块中对其它模块的调用或引用,在A模块中建立一层代理(Proxy),用于代理A对其它模块的访问,所有的外部访问都需要通过这些代理对象实现。

2)找出所有外部模块对A模块内的类和对象的调用或引用,同样在A模块内建立一些Façade类,其它模块对A模块的访问都需要动过Façade类, Façade类隐藏了A模块的内部实现细节。

为什么使用Proxy-Façade模式?Proxy-Façade模式的优点在哪里?

系统拆分最重要的目标就是要实现服务化,隐藏模块内部的实现细节,以接口形式提供服务和使用服务,实现高内聚低耦合的目的。Proxy-Façade模式可以很好的满足这一目标,Proxy将模块与外部模块的通信进行封装和隐藏,使用方不用关心对方的业务实现,通过Proxy就像直接与相应的模块在通信;Façade隐藏了模块的内部实现细节,对外提供友好的接口。Proxy-Façade模式不仅可以隐藏业务细节,还可以隐藏通讯实现,使用方无需关心服务是本地调用还是通过RPC的远程调用。Proxy-Façade模式不仅实现业务的高内聚而且也能够保证模块间的低耦合。

至此我们已经知道了如何拆分一个系统的方法和原则,但是实际拆分工作会非常复杂和繁琐,比如接口的膨胀化、接口的改变、重复业务的重构等;我们有时候将重构和拆分比喻为表面风平浪静下面却暗流涌动的海洋。

分布式架构之系统拆分相关推荐

  1. 架构方案(17) 分布式架构系统拆分原则、缘由、以及实战如何拆分步骤

    分布式架构率先开始的就是应用工程拆分,如何拆分,什么情况拆分,拆分的原则是什么,能否实战详解拆分步骤?让我一一娓娓道来. 为什么需要应用拆分 我以淘宝技术架构演进为例,淘宝从一个大系统工程向分布式架构 ...

  2. 分布式架构系统拆分原则、需求、微服务拆分步骤

    为什么需要应用拆分 我以淘宝技术架构演进为例,淘宝从一个大系统工程向分布式架构演变过程,你就能很清楚的知道为什么要需要进行应用拆分. 1 人员的角度 维护一个代名工程Denali的百万级代码怪兽(虽然 ...

  3. 清华学霸花了三年时间对java理解: Java分布式架构

    什么是分布式架构 分布式系统(distributed system)是建立在网络之上的软件系统. 内聚性是指每一个数据库分布节点高度自治,有本地的数据库管理系统. 透明性是指每一个数据库分布节点对用户 ...

  4. JavaEE架构之传统三层架构,集群架构,分布式架构,微服务架构

    javaEE架构 1.传统三层架构(all in one项目) 传统三层架构大致可以分为表现层,业务层和持久层(数据访问层).其中表现层负责接受请求和转发请求.业务层负责处理请求(注:事务管理,日志记 ...

  5. 基于Spring+SpringMVC+Mybatis的分布式敏捷开发系统架构(附源码)

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:推荐19个github超牛逼项目!个人原创100W +访问量博客:点击前往,查看更多 作者:zheng gitee ...

  6. 分布式面试 - 为什么要进行系统拆分?

    分布式面试 - 为什么要进行系统拆分? 面试题 为什么要进行系统拆分?如何进行系统拆分?拆分后不用 dubbo 可以吗? 面试官心理分析 从这个问题开始就进行分布式系统环节了,现在出去面试分布式都成标 ...

  7. 基于Spring+SpringMVC+Mybatis分布式敏捷开发系统架构zhen项目

    原项目链接:https://github.com/shuzheng/zheng 目前看过做完整的项目,大家一起学习一下,详情请点击原项目链接的地址 前言 zheng项目创建于2016年10月4日,正在 ...

  8. Spring+SpringMVC+Mybatis分布式敏捷开发系统架构(附源码)

    前言 zheng项目不仅仅是一个开发架构,而是努力打造一套从 前端模板 - 基础框架 - 分布式架构 - 开源项目 - 持续集成 - 自动化部署 - 系统监测 - 无缝升级 的全方位J2EE企业级开发 ...

  9. 大型分布式电商系统架构是如何从0开始演进

    大型分布式电商系统架构是如何从0开始演进的?本文是学习大型分布式网站架构的技术总结.对架构一个高性能.高可用.可伸缩及可扩展的分布式网站进行了概要性描述,并给出一个架构参考.文中一部分为读书笔记,一部 ...

最新文章

  1. web 平台搭建-LAMP-源码包(CentOS-6)
  2. mysql 3/17/2016
  3. Android 更新项目名称
  4. Xshell 命令后台执行
  5. 书------编程(理论方面)
  6. 经验DELL电脑突然无法进去系统,一直在戴尔的图标上无限重启
  7. linux如何实现相关功能源代码
  8. 第2章 Python 数字图像处理(DIP) --数字图像基础4 -- 像素间的一些基本关系 - 邻域 - 距离测试
  9. MFC实现Windows锁屏
  10. java学习(133):泛型
  11. MYSQL列中的数据以逗号隔开,如何查询
  12. j2me解决模拟器乱码
  13. JasperReport| JasperReport中使用自定义字体(font)
  14. 新手入门fedora9 如何打开终端
  15. glm/glm.hpp_从GLM到GBM(第2部分)
  16. 炸薯片和AI生产新闻一样样的!拢共分六步
  17. 2021-01-12 DataGrip2020.3 离线安装驱动
  18. 智能灯控制页面用HTML编写,3分钟教你创建手机APP控制全彩智能灯泡应用,图形化编程!...
  19. 电气专业出来如何月入过万?
  20. matlab手写输入,基于matlab的手写输入板

热门文章

  1. Scratch3.0----克隆(1)
  2. Excel文件打开时提示连接被禁用却找不到连接
  3. 通过商品ID获取到京东商品详情页面数据,京东商品详情API接口,京东APP详情接口,可以拿到sku价格,销售价格,优惠价格,主图等页面上面有的数据参数
  4. OSChina 初十乱弹 ——我说能,你就信啦?
  5. 用友ERT T6 技术解析(四)采购入库 下
  6. FLUENT直管流动压力损失仿真分析问题
  7. var的理解与基本使用方法
  8. C++ 集合set 详解
  9. App内购买退款流程2017
  10. 浏览器下载文件时,总是中断然后重头开始重复下载的解决办法