点击上方"Java学习之道",选择"关注"公众号

每天早晨,干货准时奉上!

本文张帆

来源:https://dwz.cn/BBzqf89J

如果现在让你阐述一下什么是“分布式系统”,你脑子里第一下跳出来的是什么?我想,此时可以用苏东坡先生的一句诗,来形象地描述大家对分布式系统的认识:横看成岭侧成峰,远近高低各不同。

1 “分布式系统”等于 SOA、ESB、微服务这些东西吗?

我觉得每个人脑子里一下子涌现出来的肯定是非常具象的东西,就像下面这些:

“分布式系统”等于 SOA、ESB、微服务这些东西吗?

如果你一下子想到的是 XX 中心、XX 服务,意味着你把服务化的模式(SOA、ESB、微服务)和分布式系统错误地划上了等号。

那么,什么是“服务化”呢?服务化就像企业当中将相同岗位的人员划分到同一个部门管理,以此来收敛特定的工作入口,再进行二次分配,以提高人员利用率和劳动成果的复用度。服务化的本质是“分治”,而“分治”的前提是先要拆,然后才谈得上如何治。这时,高内聚、低耦合的思想在拆分过程中起到了一个非常重要的作用,因为这可以尽可能地降低拆分后不同组件间进行协作的复杂度。所以重要的是“怎么拆“,还有如何循序渐进地拆,而这个过程中你究竟是采用了何种服务化模式(比如 SOA、ESB、微服务等)并不是关键。

为什么说“怎么拆”最重要呢?我来举个例子,企业的组织架构包括三种模型:职能型、项目型、矩阵型。你可以把这里的企业理解为一个“分布式系统”,把后面的 3 种模型理解为这个分布式系统的 3 种形态。作为这个“系统”的所有人,你需要考虑如何拆分它,才能使得各功能组件相互之间可以更好地协作。假设,你要将一个总计 10000 名员工的企业按“职能型”拆分成 20 个部门,得到的结果是每个部门 500 人。

这时,如果工作是流水线式的上下游关系。一个部门完工了再交给下一个部门。

那么这时候是高内聚、低耦合的。因为一个工种只与另一个工种产生了关联,并且仅有一次。

但如果工作需要频繁的由不同职能的人员同时进行,会导致同一个部门可能与多个部门产生联系。

那么,这时是低内聚、高耦合的。因为一个工种需要和其他多个工种产生关联并且远不止一次。

可以看到服务化体现了“分治”的效果,这也是分布式系统的核心思想,因此从“分治”这个本质上来看,服务化的确是分布式系统,但分布式系统不仅仅停留在那些服务化的模式上。

我相信,你在工作中参与开发的任何软件系统,到处都存在着需要拆分的地方,除非它的功能极简到只需要计算一个 1+1。比如,当我们在电商平台点击“提交订单”的时候,会涉及生成订单、扣除积分、扣除库存等等动作。电商系统初期所有的功能可能都在一个系统里面,那么这些操作可以写在一个方法体里吗?我想只要代码能够成功运行,大部分人是不会管你怎么写的。但是如果这时需要增加一个红包功能呢?相信你或多或少遇到过在几百上千行代码中去增改功能的事情,其中的痛苦应该深有体会。

要解决这个问题就是要做拆分,通过梳理、归类,将不同的紧密相关的部分收敛到一个独立的逻辑体中,这个逻辑体可以是函数、类以及命名空间,等等。所以,从这个角度来说“分治”的问题其实早就存在我们的工作中,就看我们是否有去关注它了。因此,这并不只是我们在进行服务化时才需要考虑的问题。

那么如何才能做好这个事情,更好的拆分能力正是我们需要掌握的。如果只是因为看到其他人这么拆,我也这么拆,根据“二八原则”,或许“依样画葫芦”可以达到 80% 的契合度,但是往往那剩下的 20% 会是耗费我们 80% 精力的“大麻烦”。要知道,只有掌握了核心主旨,才能更快地找到最理想的高内聚、低耦合方案

2 “分布式系统”是各种中间件吗?

又或许,听到分布式系统,你想到了某某 MQ 框架、某某 RPC 框架、某某 DAL 框架,把运用中间件和分布式系统错误地划上了等号。

这里需要搞清楚的是,中间件起到的是标准化的作用。中间件只是承载这些标准化想法的介质、工具,可以起到引导和约束的效果,以此起到大大降低系统复杂度和协作成本的作用。我们来分别看一下:

  • MQ 框架标准化了不同应用程序间非实时异步通信的方式。

  • RPC 框架标准化了不同应用程序间实时通讯的方式。

  • DAL(Data Access Layer,数据访问层)框架标准化了应用程序和数据库之间通讯的方式。

所以,虽然分布式系统中会运用中间件,但分布式系统却不仅仅停留在用了什么中间件上。你需要清楚每一类中间件背后是对什么进行了标准化,它的目的是什么,带来了哪些副作用,等等。只有如此,你才能真正识别不同技术框架之间的区别,找到真正适合当前系统的技术框架。

那么标准是拍脑袋决定的吗?肯定不是,正如前面所说每一次标准化都是有目的的,需要产生价值。比如,大部分中间件都具备这样一个价值:

为了在软件系统的迭代过程中,避免将精力过多地花费在某个子功能下众多差异不大的选项中。

在现实中,这点更多时候出现在技术层面的中间件里,比如,数据库访问框架的作用是为了标准化操作不同数据库的差异,使得上层应用程序不用纠结于该怎么与 mysql 交互或者该怎么与 SQL SERVER 交互。因为与业务相比,技术层面“稳定”多了,所以做标准化更有价值,更能获得长期收益。但“稳定”是相对的,哪怕单纯在业务层面也存在相对稳定的部分。

比如,你可以想象一下“盛饭”的场景,在大多数情况下其中相对稳定的是什么,不稳定的是什么。想完之后看下面的示例。

...基类:人继承基类的子类:男人、女人

基类:碗继承基类的子类:大碗、小碗、汤碗

基类:勺子继承基类的子类:铁勺、陶瓷勺、塑料勺

function 盛饭(参数 人,参数 碗,参数 勺子){    do 人拿起碗    do 人拿起勺子    do 人用勺子舀起饭    do 人把勺子放到碗的上方并倒下

}...

从这个示例里我们发现,不稳定的部分都已经成为变量了,那么剩下的这个方法体起到的作用和前面提到的中间件是一样的,它标准化,标准化了盛饭的过程。所以识别相对稳定的部分是什么,如何把它们提炼出来,并且围绕这些点进行标准化,才是我们需要掌握的能力。而锻炼这个能力和需要这个能力的地方同样并不局限于分布式系统。

列举这些现象只是想说,我们在认知一个分布式系统的时候,内在胜于表象,掌握一个扎实的理论基本功更为重要。而且,这些训练场无处不在。

3 海市蜃楼般的“分布式系统”

我相信,自从进入移动时代以来,各种高大上的系统架构图越来越频繁地出现,你的眼前充斥着各种主流、非主流的眼花缭乱的技术框架。你不由得肃然起敬一番,心中呐喊着:“对,这就是我想去的地方,我想参与甚至实现一个这样牛逼的分布式系统,再也不想每天只是增删改查了。”

得不到的事物总是美好的,但往往我们也会过度地高估它的美好。与此类似,高大上的架构图背后呈现的系统的确也是一个成熟分布式系统的样貌,但我们要清楚一点:罗马不是一日建成的。

而且,“分布式”这个词只是意味着形态上是散列状的,而“一分为二”和“一分为 N”本质上并没有区别。所以,很多小项目或者大型项目的初期所搭配的基础套餐“单程序 + 单数据库”,同样可以理解为分布式系统,其中遇到的问题很多同样也存在于成熟的分布式系统中。

想象一下,下面的场景是否在“单程序 + 单数据库”项目中出现过?

  • log 记录执行成功,但是数据库的数据没发生变化;

  • 进程内的缓存数据更新了,但是数据库更新失败了。

这里我们停顿 30 秒,思考一下为什么会出现这些问题?

这里需要我们先思考一下“软件”是什么。软件的本质是一套代码,而代码只是一段文字,除了提供文字所表述的信息之外,本身无法“动”起来。但是,想让它“动”起来,使其能够完成一件我们指定的事情,前提是需要一个宿主来给予它生命。这个宿主就是计算机,它可以让代码变成一连串可执行的“动作”,然后通过数据这个“燃料”的触发,“动”起来。这个持续的活动过程,又被描述为一个运行中的“进程”。

那么除了我们开发的系统是软件,数据库也是软件,前者负责运算,后者负责存储运算后的结果(也可称为“状态”),分工协作。

所以,“单程序 + 单数据库”为什么也是分布式系统这个问题就很明白了。因为我们所编写的程序运行时所在的进程,和程序中使用到的数据库所在的进程,并不是同一个。也因此导致了,让这两个进程(系统)完成各自的部分,而后最终完成一件完整的事,变得不再像由单个个体独自完成这件事那么简单。这就如“两人三足”游戏一样,如何尽可能地让外部看起来像是一个整体、自然地前进。

所以,我们可以这么理解,涉及多个进程协作才能提供一个完整功能的系统就是“分布式系统”。

那么再回到上面举例的两个场景,我们在思考“单程序 + 单数据库”项目中遇到的这些问题背后的原因和解决它的过程时,与我们在一个成熟的分布式系统中的遭遇是一样的,例如数据一致性。当然,这只是分布式系统核心概念的冰山一角。

维基百科对“分布式系统”的宏观定义是这样的:

分布式系统是一种其组件位于不同的联网计算机上的系统,然后通过互相传递消息来进行通信和协调。为了达到共同的目标,这些组件会相互作用。

我们可以再以大小关系来解释它:把需要进行大量计算的工程数据分割成小块,由多台计算机分别计算,然后将结果统一合并得出数据结论的科学。这本质上就是“分治”。而“单程序 + 单数据库”组合的系统也包含了至少两个进程,“麻雀虽小五脏俱全”,这也是“分布式系统”。

4 总结

现在,我们搞清楚了,看待一个“分布式系统”的时候,内在胜于表象。以及,只要涉及多个进程协作才能提供一个完整功能的系统,就是“分布式系统”

我相信还有很多其他景象出现你的脑海中,但这大多数都是分布式系统的本质产生的“化学反应”,进而形成的结果。如果停留在这些表象上,那么我们最终将无法寻找到“分布式系统”的本质,也就无法得到真正的“道”,更不会真正具备驾驭这些形态各异的“分布式系统”的能力。

所以,希望你在学习分布式系统的时候,不要因追逐“术”而丢了“道”。没有“道”只有“术”是空壳,最终会走火入魔,学得越多,会越混乱,到处都是矛盾和疑惑。

因此,我们这个系列除了教给你在具体场景下的最佳实践,还会和你讲解为什么这样做,以及该如何去权衡不同方案。不会过多的讲述具体的技术框架,大部分内容围绕理论展开,欲使每个人能够掌握好这些分布式中的基础理论和思路,修炼好自己的内功。

我将在后续的文章中,以一个项目的初期到成熟期作为路线图,带领你循序渐进地深入到分布式系统中,层层递进地去剥开它的本质,并且围绕这个本质去思考(是什么问题,有哪些方式可以解决,什么时候该用何种种方式等等),让你知其然且知其所以然,形成一套完整的知识体系,完成核心“骨架”的塑造。而在此之后,你自己在课外学习时,就可以去填充“血肉”部分,逐渐丰满自己。未来,大家的区别就在于胖一点和瘦一点,但只要能很好地完成工作,胖瘦又有何影响?

最后,你心目中的分布式系统是怎么样的一个“外形”呢?欢迎在评论区留言一起讨论。


 | 更多精彩文章 -


  • 我在 GitHub 上看到了一个丧心病狂的开源项目!
  • 怎样才能把源码读的明明白白?
  • 提升效率:优化Java代码的35个小技巧
  • 为什么阿里巴巴规定超过3张表,禁止join?

  • 关于Mybaits,我总结了 10 种通用的写法

  • Google 出品的 Java 编码规范,强烈推荐,既权威又科学!

  • 不用找了,大厂的分库分表方案,都在这里了!

  • 为什么阿里巴巴禁止使用Executors创建线程池?

  • 彻底透析SpringBoot jar可执行原理

-资源助手-

>>>CSDN下载服务 || 技术讨论群<<<


写留言   
觉得有用就点个在看吧

可能是讲分布式系统最到位的一篇文章相关推荐

  1. 可能是全网把 ZooKeeper 概念讲的最清楚的一篇文章

    前言 相信大家对 ZooKeeper 应该不算陌生.但是你真的了解 ZooKeeper 是个什么东西吗?如果别人/面试官让你给他讲讲  ZooKeeper 是个什么东西,你能回答到什么地步呢? 我本人 ...

  2. 可能是把Docker的概念讲的最清楚的一篇文章

    本文只是对Docker的概念做了较为详细的介绍,并不涉及一些像Docker环境的安装以及Docker的一些常见操作和命令. 阅读本文大概需要15分钟,通过阅读本文你将知道一下概念: 容器 什么是Doc ...

  3. 这可能是把Docker的概念讲的最清楚的一篇文章

    转载自  这可能是把Docker的概念讲的最清楚的一篇文章 Docker 是世界领先的软件容器平台,本文主要来介绍下关于Docker的那些事儿,主要包含以下内容: 容器 什么是Docker? Dock ...

  4. 【转载】可能是把Docker的概念讲的最清楚的一篇文章

    本文只是对Docker的概念做了较为详细的介绍,并不涉及一些像Docker环境的安装以及Docker的一些常见操作和命令.我觉得是很适合当做睡前读物了~~~~? 阅读本文大概需要15分钟,通过阅读本文 ...

  5. java eden区_(转)可能是把Java内存区域讲的最清楚的一篇文章

    写在前面 本节常见面试题: 问题答案在文中都有提到 如何判断对象是否死亡(两种方法). 简单的介绍一下强引用.软引用.弱引用.虚引用(虚引用与软引用和弱引用的区别.使用软引用能带来的好处). 如何判断 ...

  6. java主要内存区域_可能是把Java内存区域讲的最清楚的一篇文章

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄 ...

  7. [No0000187]可能是把Java内存区域讲的最清楚的一篇文章

    写在前面(常见面试题) 基本问题: 介绍下 Java 内存区域(运行时数据区) Java 对象的创建过程(五步,建议能默写出来并且要知道每一步虚拟机做了什么) 对象的访问定位的两种方式(句柄和直接指针 ...

  8. 不用数学也能讲清贝叶斯理论的马尔可夫链蒙特卡洛方法?这篇文章做到了

    作者 | Ben Shaver 翻译 | 刘畅 编辑 | Donna 大多数时候,贝叶斯统计在结果在最好的情况下是魔法,在最糟糕时是一种完全主观的废话.在用到贝叶斯方法的理论体系中,马尔可夫链蒙特卡洛 ...

  9. 全文搜索引擎Elasticsearch,这篇文章给讲透了

    之前已经分享过Elasticsearch的使用和原理的知识,由于近期在公司内部做了一次分享,所以本篇主要是基于之前的博文的一个总结,希望通过这篇文章能让读者大致了解Elasticsearch是做什么的 ...

  10. 一直对zookeeper的应用和原理比较迷糊,今天看一篇文章,讲得很通透,分享如下(转)...

    本文转自http://blog.csdn.net/gs80140/article/details/51496925 一直对zookeeper的应用和原理比较迷糊,今天看一篇文章,讲得很通透,分享如下: ...

最新文章

  1. MyBatis3 用log4j在控制台输出 SQL
  2. Oracle的时区问题
  3. 为什么下一个十年的主战场在 Serverless?
  4. Spring Cloud Alibaba:Sentinel 热点参数限流
  5. Eigen入门之密集矩阵 4 - 块操作
  6. Maven配置tomcat和jetty插件来运行项目
  7. 车纷享:基于阿里云HBase构建车联网平台实践
  8. react实现全选和反选_全选的实现
  9. java redis 重连机制_redis在java中的客户端连接
  10. 曾经很火但消失了的软件,你还记得几个?
  11. linux 移动硬盘 大于4g,Linux下挂大于2G的NTFS格式移动硬盘方法
  12. centos java7安装_Centos7 JDK7安装配置
  13. 设计模式:(工厂模式)
  14. Zip函数教程(简单示例)
  15. 2020暑期牛客多校训练营第九场(C)Groundhog and Gaming Time(数学期望,线段树,逆元)
  16. Variational Inference入门:variational bayesian EM
  17. 【A40I-LVDS】
  18. AForge.NET Framework2.25--图像视觉处理学习(五)---颜色转换
  19. 关于 MyBatis动态sql,这里有 10 种超好用的写法
  20. 字符串常量和变量是什么?

热门文章

  1. 上标和下标复制大全(含0~9、字母、特殊字符)
  2. DB---数据模型的三要素
  3. 【原生】JS 获取今天日期
  4. 使用pandas sns绘图
  5. reCAPTCHA打不开的解决方法
  6. 考研计算机320分什么水平,考研320分算什么水平,能上211、985吗?很多人都答不上...
  7. 牛客练习赛53 老瞎眼 pk 小鲜肉[思维+离线+线段树]
  8. 本地计算机无法启动dhcp服务,提示Windows无法启动DHCP Client服务如何解决
  9. 腾讯开放平台开发者星级服务:全面监控Crash
  10. 荣耀10手机计算机科学计算器,荣耀赵明回应手机计算器10%问题:国外计算小费使用...