AICon上海|与字节、阿里、腾讯等企业共同探索Agent 时代的落地应用 了解详情
写点什么

详解分布式系统本质:“分治”和“冗余”

  • 2018-11-16
  • 本文字数:3573 字

    阅读完需:约 12 分钟

详解分布式系统本质:“分治”和“冗余”

站在全局角度看,分布式系统的本质是什么?其实说白了,就是两点:“分治”和“冗余”。


分治和冗余使得分布式系统具备了核心价值,那么它的价值是什么?

分布式系统的价值

谈到分布式系统的价值,可能就得从 1953 年说起了。在这一年,埃布·格罗希(Herb Grosch)提出了一个他观察得出的规律——Grosch 定律。维基百科中是这样描述的:


计算机性能随着成本的平方而增加。如果计算机 A 的成本是计算机 B 的两倍,那么计算机 A 的速度应该是计算机 B 的四倍。


这一论断与当时的大型机技术非常吻合,因而使得许多机构都尽其所能购买最大的单个大型机。其实,这也非常符合惯性思维,简单粗暴。


然而,1965 年高登·摩尔(Gordon Moore)提出了摩尔定律。经过几年的发展,人们发现摩尔定律的预测是符合现实的。这就意味着,集中式系统的运算能力每隔一段时间才能提升一倍。


那么,到底要隔多久呢?这个“时间”有很多版本,比如广为流传的 18 个月版本,以及 Gordon Moore 本人坚持的 2 年版本。这里我们不用太过纠结于实际情况到底是哪个“时间”版本,因为这其中隐含的意思更重要,即:如果你的系统需承载的计算量的增长速度大于摩尔定律的预测,那么在未来的某一个时间点,集中式系统将无法承载你所需的计算量


而这只是一个内在因素,真正推动分布式系统发展的催化剂是“经济”因素。


人们发现,用廉价机器的集合组成的分布式系统,除了可以获得超过 CPU 发展速度的性能外,花费更低,具有更好的性价比,并且还可以根据需要增加或者减少所需机器的数量。


所以,我们得到一个新结论:无论是要以低价格获得普通的性能,还是要以较高的价格获得极高的性能,分布式系统都能够满足并且受规模效应的影响,系统越大,性价比带来的收益越高


之后,进入到互联网快速发展的时期,我们看到了分布式系统相比集中式系统的另一个更明显的优势:更高的可用性。例如,有 10 个能够承载 10000 流量的相同的节点,如果其中的 2 个挂了,只要实际流量不超过 8000,系统依然能够正常运转。


而这一切的价值,都是建立在分布式系统的“分治”和“冗余”之上的。

分治

分治,字面意思是“分而治之”,和我们的大脑在解决问题时的思考方式是一样的。我们可以将整个过程分为 3 步:分解 -> 治理 -> 归并。而分治思想的表现形式多样,分层、分块都是它的体现。



这么做的好处是:问题越小越容易被解决,并且,只要解决了所有子问题,父问题就都可以被解决了。但是,这么做的时候,需要满足一个最重要的条件:不同分支上的子问题,不能相互依赖,需要各自独立。因为一旦包含了依赖关系,子问题和父问题之间就失去了可以被“归并”的意义。在软件开发领域,我们把这个概念称为“耦合度”和“内聚度”,这两个度量概念非常重要。


耦合度,指的是软件模块之间相互依赖的程度。比如,每次调用方法 A 之后都需要同步调用方法 B,那么此时方法 A 和 B 间的耦合度是高的。


内聚度,指的是模块内的元素具有的共同点的相似程度。比如,一个类中的多个方法有很多的共同之处,都是做支付相关的处理,那么这个类的内聚度是高的。


内聚度通常与耦合度形成对比。低耦合通常与高内聚相关,反之亦然。


所以,当你打算进行分治的时候,耦合度和内聚度就是需要考虑的重点。


下面我们来看个例子,体会一下耦合度和内聚度的含义。(图仅用于表达含义,切勿作其他参考)


假设一个电商平台,为了应对更大的访问量,需要拆分一个同时包含商品、促销的系统。如果垂直拆分,是这样:



而如果水平拆分,则是这样的:



假如我们面对的场景仅仅是具体的商品详情展示页面,很显然,用水平拆分的效果会更好。因为传统的商品展示必然会同时展示促销,所以,如果用水平拆分,一次请求即可获取所有数据,内聚度非常高,并且此时模块间完全没有耦合。而如果是垂直拆分的话,就需要同时请求 2 个节点的数据并进行组合,因此耦合度更高、内聚度更差。


但是,这样的假设在真实的电商场景中是不存在的。从全局来看,订单、购物车、商品列表等许多其他场景也需要促销信息。并且这个时候我们发现引入了一些新的主体,诸如订单、购物车、商品分类等等。这个时候,水平拆分带来的好处越来越小,因为这样只解决了多个耦合中的一个,低耦合丧失了。并且随着商品和促销与外界的关联越来越多,必然有些场景仅仅涉及到商品和促销的其中一个,但是处理的时候,我们还需要避免受到另一个的影响。如此,高内聚也丧失了。


这个时候,反而通过垂直拆分可以获得更优的耦合度和内聚度,如下图。



这个时候,最高的耦合关系从原先的 6 降到了 4,并且商品和促销各自的处理相互不受影响。


所以,你会发现随着业务的变化,耦合度与内聚度也会发生变化。因此,及时地进行梳理和调整,可以避免系统的复杂度快速增长,才能最大程度的发挥“分治”带来的好处。


综上,分治可以简化解题的难度,通过高内聚、低耦合的协作关系达到更好“性能与经济比”,来承载更大的流量。而“冗余”则带来了系统可以 7*24 小时不间断运作的希望。

冗余

这里的冗余并不等同于代码的冗余、无意义的重复劳动,而是我们有意去做的、人为增加的重复部分。其目的是容许在一定范围内出现故障,而系统不受影响,如下图。



此时,我们可以将冗余的节点部署在一个独立的环境中。这个独立的环境,可能是处于同一个局域网内的不同主机,也可能是在不同的局域网,还可能是在不同的机房。很显然,它们能够应对的故障范围是逐步递增的。


但是,像这种单纯地为了备用而做的冗余,最大的弊端是,如果没有出现故障,那么冗余的这部分资源就白白浪费了,不能发挥任何作用。所以,我们才提出了诸如双主多活、读写分离之类的概念,以提高资源利用率。


当然,除了软件层面,硬件层面的冗余也是同样的道理。比如,磁盘阵列可以容忍几块之内磁盘损坏,而不会影响整体。


不过也很显然,当故障影响范围大于你冗余的容量时,系统依然会挂。所以,既然你无法预知故障的发生情况,那么做冗余的时候需要平衡的另一端就是成本。相比更多的冗余,追求更好的性价比更合理一些。


在我们生活中的冗余也到处存在。比如,大部分的飞机和直升机的发动机都是偶数的,汽车中的电子控制系统的冗余机制等。就好比替身与真身的关系,冗余的就是替身。它可以和真身同时活动,也可以代替真身活动。


分治和冗余讲究的都是分散化,最终形成一个完整的系统还需要将它们“连接”起来。天下没有免费的午餐,获得分布式系统价值的同时,这个“再连接”的过程就是我们相比集中式系统要做的额外工作。

再连接

如何将拆分后的各个节点再次连接起来,从模式上来说,主要是去中心化与中心化之分。



前者完全消除了中心节点故障带来的全盘出错的风险,却带来了更高的节点间协作成本。后者通过中心节点的集中式管理大大降低了协作成本,但是一旦中心节点故障则全盘出错。


另外,从技术角度来说,如何选择通信协议和序列化机制,也是非常重要的。



虽然很多通讯协议和序列化机制完全可以承担任何场景的连接责任,但是不同的协议和序列化机制在适合的场景下才能发挥它最大的优势。比如,需要更高性能的场景运用 TCP 协议优于 HTTP 协议;需要更高吞吐量的场景运用 UDP 协议优于 TCP 协议,等等。

总结

不管系统的规模发展到多大,合理地拆分,加上合适的连接方式,那么至少会是一个运转顺畅、协作舒服的系统,至少能够正常发挥分布式系统应有的价值。


如今,我们发现分布式系统还可以发挥更多的作用。


比如,只要基于一个统一的上层通信协议,其下层的不同节点可以运用不同的技术栈来发挥不同技术各自的优势,比如用 Go 来应对高并发场景,用 Python 来做数据分析等。


再比如,提高交付的速度,如下图。



通过分配不同的团队、人员同时进行多个模块的开发,虽然总的耗时增加了,但是整体的交付速度加快了。


事物最本质的东西是恒定的、不变的,可以指引我们的工作方向。分布式系统的本质也是这样。例如,这样的“分治”方案耦合度和内聚度是否最优,这样做“冗余”带来的收益是否成本能够接受。只要持续带着这些思考,我们就好像拿着一杆秤,基于它,我们就可以去衡量各种变量影响,然后作权衡。比如成本、时间、人员、性能、易维护等等。也可以基于它去判断什么样的框架、组件、协议更适合当前的环境。


需要不断的权衡,也意味着分布式系统的设计工作一定不是一步到位,而是循序渐进的。因为过分为未知的未来做更多的考量,最终可能都会打水漂。所以,建议以多考虑 1~2 步为宜。假如以你所在的团队中对重大技术升级的频率来作为参考的话,做可供 2 个升级周期的设计,花一个升级周期的时间先实现第一阶段,下个阶段可以选择直接实现剩下部分,也可继续进行 2 个升级周期设计,开启一个循环,持续迭代,并且不断修正方向以更贴近现实的发展,就如下图这样。


思考题

在你的工作或者学习中,觉得分布式系统还具备哪些价值呢?可以在下方评论区留言。



延伸阅读

分布式系统系列文章第一篇《拨云见日看什么是分布式系统?》


2018-11-16 07:004412

评论

发布
暂无评论
发现更多内容

使用 QuTrunk+Amazon Deep Learning AMI(TensorFlow2)构建量子神经网络

亚马逊云科技 (Amazon Web Services)

深度学习 量子计算

记录一次还算优雅的代码设计

京东科技开发者

线程 cpu 优雅 代码设计 企业号 2 月 PK 榜

设计模式-策略模式详解

C++后台开发

设计模式 策略模式 后端开发 Linux服务器开发 C++开发

从 await-to-js 到 try-run-js

jump-jump

JavaScript 异步 优化 Async 重试

直播预告丨 立即解锁 ALB Ingress 高级特性

阿里巴巴云原生

阿里云 容器

从一个Demo说起Zookeeper服务端源码

宋小生

zookeeper

Apifox 1 月更新 | 将接口调试做到「极简」的新模式上线

Apifox

Apifox API

物联网平台选型葵花宝典:盘点开源、SaaS及通用型平台的优劣对比

AIRIOT

物联网 物联网平台选型 平台选型

直播预约|数据库掌门人论坛召开,共谋中国数据库生态发展新路径

镜舟科技

数据库 大数据 开源

分布式缓存服务DCS:企业版性能更强,稳定性更高

华为云开发者联盟

云计算 后端 华为云 企业号 2 月 PK 榜 华为云开发者联盟

优秀实践案例征集火热开启,快来投稿!

Apache RocketMQ

消息列队

南宁等级测评机构有几家?分别是哪几家?

行云管家

等保 南京 等级保护 等级

【等保小知识】过等保后可以收到哪些资料?

行云管家

等保 等级保护 过等保

关于小游戏引擎你还了解哪些?

没有用户名丶

小程序游戏

OpenInfra峰会议程已公布,特色主题演讲,百余场专题会议等你来参与!

极客天地

有了 ETL 数据神器 dbt,表数据秒变 NebulaGraph 中的图数据

NebulaGraph

数据库 大数据 数据处理 图数据库

高级java体系课第1期第二周作业

刘博

VSCode一键接入Notebook体验算法套件快速完成水表读数

华为云开发者联盟

人工智能 华为云 企业号 2 月 PK 榜 华为云开发者联盟

火山引擎DataLeap:3个关键步骤,复制字节跳动一站式数据治理经验

字节跳动数据平台

大数据 数据治理 数据研发 实际应用 企业号 2 月 PK 榜

使用 NineData GUI 创建与修改 ClickHouse 表结构

NineData

MySQL 分布式数据库 Clickhouse Dbeaver NineData

“采访”ChatGPT看看它对我们GreatSQL社区有什么看法

GreatSQL

MySQL greatsql greatsql社区

提升软件质量?为什么不试试华为云CodeArts Check

华为云开发者联盟

云计算 华为云 企业号 2 月 PK 榜 华为云开发者联盟

基于 Kubernetes 的企业级大数据平台,EMR on ACK 技术初探

阿里巴巴云原生

阿里云 容器 云原生

什么是智能制造,为什么它对传统制造业影响如此之大?

PreMaint

智能工厂 智能制造

给 Databend 添加 Aggregate 函数 | 函数开发系例二

Databend

统一观测丨如何使用Prometheus 实现性能压测指标可观测

阿里巴巴云原生

阿里云 云原生 Prometheus 压测

云原生技术在容器方面的应用

统信软件

容器 云原生 云服务

新思科技解读2023年软件安全行业六大趋势

InfoQ_434670063458

新思科技 软件安全

OpenHarmony 3.2 Beta多媒体系列——视频录制

OpenHarmony开发者

OpenHarmony

聊一聊,我对DDD的关键理解

阿里技术

DDD

详解分布式系统本质:“分治”和“冗余”_架构_张帆_InfoQ精选文章