每日分享最新,最流行的软件开发知识与最新行业趋势,希望大家能够一键三连,多多支持,跪求关注,点赞,留言。
你不能忽视现实世界,如果要走得更远,您必须了解现实世界如何建模和创建可靠的系统。
在设计系统时,了解反模式和陷阱通常比了解模式更有用,因此我决定写这篇博客文章,根据我在设计(主要是)分布式企业应用程序的经验中,我认为会导致产生不可靠系统的因素。
我很高兴知道您的相关经历和对此事的评论。
什么是建模?
人脑是一种模式寻找装置。然而,这是一个代价高昂的过程,思考的主要目标是首先终止/解决导致该过程开始的原因;因此它开发了几种机制来防止它过于频繁地发生;与我们在这里讨论有关的是心智模型。现实很复杂,混乱,太混乱,我们有限的大脑能力和资源无法理解(如果可能的话);所以我们的大脑会尝试创建一个非常简单且(大多数情况下)易于理解的替代现实,这就是建模的全部内容!从我们如何看待自然如何运作,例如在科学中,到适当的社会行为,到害怕或寻求什么,所有这些都是我们心智模式的结果。值得注意的是,模型既不是客观现实,也不应如此!
所有模型都是错误的,但有些模型是有用的。
— 乔治盒子
一般来说,有两种模型:
- 没用(在上下文中)
- 有用的(在上下文中)
上下文部分在这里非常重要,例如,牛顿的引力理论(顺便说一下,理论也是模型!)与广义相对论,两者都在不同的上下文中有用(平面时空在在可能弯曲的时空中低速与近光速)并且一个不会取代另一个,因为历史上的一些记者试图说服人们事实就是如此,科学已经改变了主意!无偏见的上下文感对于设计成功、可靠的系统 (恕我直言) 至关重要。
什么是可靠性?
软件可靠性的含义没有全球公认的定义;有人说它关乎运行可靠性,有人说它关乎客户体验,有人说它强调程序的正确性,还有一些人将它与容错性和可用性混为一谈!(然而,在某些情况下,这些可能是一些因素)所以我需要在本文的上下文中定义我所说的可靠性。我使用我们在英语中使用的可靠性;一个可靠的系统是我们可以信任的系统,它可以尽可能完美地完成我们的意思,并且不会做任何我们不希望它做的事情。乍一看似乎是正确的,但我认为这是它的超集;例如,您不会依赖每分钟崩溃的缓慢系统,但如果有足够的时间,它会完成它的工作!
建模如何影响系统的可靠性?
解决问题的过程
你不能忽视现实,走得很远!这里的推理非常直观,但大多数时候都被忽略了。
让我解释:
我们想让事情变得更容易,消除任何成本、金钱或精神能量。
- 我们开始将我们的条件视为要解决的问题。
- 为了解决这个问题,我们需要收集数据。
- 将现实映射到一个更简单的模型以适应我们的想法。
- 定义要解决的问题,然后开始试验模型。
- 希望我们能在一些迭代后解决这个问题。
- 我们需要找到一种方法在现实中实施解决方案,以实现我们的第一个目标。
当我们想要实施解决方案时,实际上,我们有很多选择。最常见的方法之一(也是我们在这里感兴趣的方法)是通过编程来利用计算机系统。
你的思维可能解决现实世界中的问题的唯一原因是你的思维模型与现实世界之间存在关系,所以如果你没有对建模给予足够的关注,你就无法在没有任何模型的情况下开始实施; 这意味着您正在隐式地实现一个幼稚的模型,这增加了面临我们在本文中讨论的严重问题的机会,并且也大大降低了模型与现实的相关性。例如,您最终将进入幻想世界!
拥有一个与现实不完全相似的模型也是一种负担,因为现实在上述模型中以意想不到的方式表现。例如,托勒密的太阳系地心模型,它比圆形轨道的日心模型更精确,但在描述他那个时代未知的其他现实部分时遇到了很多麻烦,而椭圆轨道的日心模型则解决了这些问题,因为它既更直截了当,也更准确地描述了现实。注意,这并不是说有正确的模型,其他模型都是错误的!如前所述,模型只是我们理解和解决问题的工具。我们不应该将它们与现实混为一谈。
托勒密本人在他的《天文学大成》中指出,任何描述行星运动的模型都只是一种数学装置。由于无法知道哪个是正确的,因此应使用获得正确数字的最简单模型。
忽略业务
回到软件行业,如果你在设计一个企业软件系统,你就是在为一个建立在人员沟通、组织结构和业务流程(本身就太复杂!)的系统的现有模型建模;创建另一个具有任何逻辑和概念不匹配的模型会非常迅速地增加复杂性并同时降低生活幸福感。
您无法通过更多的技术努力来解决业务问题!
这就是领域驱动设计帮助建模的地方。DDD 是指战略模式和想法,而不是像实体和存储库这样的战术模式,它教会我们发现现有的业务模型,而不是试图创建可能不匹配的另一个模型,从而降低整体复杂性并考虑整体社会技术因素。
当现有模型是已经存在了一段时间并且已经成熟的业务时尤其如此。
过于简化的系统
一切都应该尽可能简单,但不能简单。
- 艾尔伯特爱因斯坦
一个试图过度简化现实的系统最多会丢失一些重要的业务概念,或者在最坏的情况下会走错方向。
我最喜欢的这种现象的例子是,当软件开发人员试图引入比所需更多的一致性时,最终结果总是缺少一个重要的概念,然后需要这个概念来处理业务流程中可能出现的冲突,并且还会创建缓慢的可怕软件片段和意大利面条在性质上。例如,在银行交易中,资产不会立即转移(以原子方式),并且有一段时间资产处于软状态,即既不在源账户也不在目标账户;尝试以原子方式对其进行建模将需要 2PC,这(几乎)始终是不良建模的标志. 或者,就此而言,更常见的一种是购物车试图以原子方式进行仓储,但由于没有考虑到仓库缺货或物品在事故后调整的可能性,因此遇到了同样的问题这导致一些货物成为浪费!
这种建模问题几乎总是在竞争条件下结束!
除非您错过了一个概念,否则现实世界中没有竞争条件!
过度抽象
呆伯特:哦不!极端的抽象程度让我们失重了!
另一个糟糕的建模情况是过度抽象的情况,这也会丢失重要的概念;例如,虽然我们可以从数学的角度将方法调用替换为远程调用,但这会隐含地假设网络是可靠的,但事实并非如此!并且充其量会使许多错误处理复杂化,或者由于忽略分布式系统的性质而引入了无法正确处理的错误。
解释前者,您无法知道该方法是否在远程位置执行并且响应没有及时到达,或者它从未到达目的地;这是一个根本性的问题,它很努力地告诉我们不能这样解决!
另一个常见示例是将本质上的异步交互建模为同步交互。这只会使事情复杂化,因为您将可能的场景缩小到一个不够大的问题空间,因此您要么忽略问题,要么尝试非常努力地理解启发式方法以部分缓解与您的主要问题无关的问题,但是一个坏模型引入的问题!
这就是为什么在设计可靠的分布式系统时 RPC 几乎总是一个坏主意。
忽略物理
当您引入并发或任何分布时,您正在改变有关程序运行方式的物理定律;你正在改变时间的本质,从牛顿世界观(有一个独特的全球时钟)到广义相对论中的多体物理学(每个物体都有自己的相对时钟);您还将普通逻辑更改为时间逻辑,如果不考虑时间行为就无法得出结论。
你的问题变得复杂了好几个数量级,你不能忽视这些问题,最多继续工作几天!将分布式系统添加到组合中;您最终将获得更多数量级的复杂性!
不了解分布式/并发系统与大多数开发人员所习惯的系统有何不同是导致许多业务失败以及相关人员痛苦和痛苦的原因。
我的分布式对象设计第一定律:不要分发你的对象。
— 马丁·福勒
这是一个如此广泛的话题,需要一本书才能触及表面!但我会提到一些常见的谬误:
- Time:正如我前面提到的,时间及其所有导数(例如速度,...)都是相对于观察者而言的,并且没有全局时间,这意味着在分布式系统中,您无法比较时间,并且总排序是不明确的。
- 排序:您必须显式地建模您的排序,因为没有隐含的,最常见的方法是使用相关 ID,这将创建偏序,这可以解决前面提到的所有问题,将时间替换为我们使用时间的意思,这是因果关系。
- 同步:在分布式系统中,你是异步的;您无法做出其他决定,因为自然是异步的;这样想,甚至光、电和核力都是事件驱动的 :) 因为它们是通过发送微小粒子(例如光子、胶子、W 和 Z 波松子)作为消息来传输的,所以之后没有同步行为我们离开了量子领域。
请注意,我所说的异步不是指使用消息代理,而是异步通信!这可以使用 HTTP 来实现,例如,拉取与推送等待,就像在 Atom 提要与 RPC 中一样。 - Delivery:上述属性的一个结果是,我们既不能保证只发送一次,也不能保证消息的排序。正如以下引文中幽默地指出的那样:
分布式系统中只有两个具有挑战性的问题:
2. 一次性交货
1.保证消息的顺序
2. 一次性交货
— 马蒂亚斯·维拉斯
- 延迟:计算机很快!但不幸的是,没有什么能比光传播得更快,虽然它非常快,但它不是即时的,甚至光也不够快,无法覆盖糟糕的建模错误!
其他因素
忽略组织
为现实世界的应用程序建模是一项复杂的任务,每个规模很大的系统都需要大量的团队合作,而且远远超出了个人的能力。团队合作很难;它必须像任何其他技能一样掌握,但对许多人来说似乎并不那么自然,因此通常需要指导和良好的管理才能实现。这是一项复杂的任务,因为它需要管理技能和正确的使用条件,而且大多数个人甚至团队都无法控制。
但如果碰巧出现这种情况,可靠的系统似乎是在可靠的组织中建立的,那里有持续改进的文化和开放的沟通结构,团队围绕能力而构建,并有足够的自主权来做需要的事情,并且可以在需要时影响和改进整个组织。僵化的组织无法创建可靠的系统,因为这是一种迭代改进的努力,无法在这类组织中实施。例如,围绕权威形成的组织与产生良好结果的组织完全相反,因为没有自主权。人们不会用最相关的信息和技能做出决定。
根据康威定律:
任何设计系统(定义广泛)的组织都将产生其结构是组织通信结构副本的设计。
— 梅尔文·E·康威
我们可以得出结论,组织结构在决定系统的外观方面起着至关重要的作用。通过补充说组织是人的系统,我们可以推断出忽视人们的需求和背景以及管理不善是创建不可靠系统的最有保证的方式;垃圾进垃圾出!
忽略人和团队
虽然这听起来微不足道或太明显,但并非每个团队或个人都具备开发或设计各种系统所需的相关技能。人们有不同的技能、不同的背景和独特的动机。同时,大多数软件开发工作似乎都是大多数开发人员熟悉的简单 CRUD 应用程序(至少来自外部!),但大多数以可靠性为最重要问题的关键系统却不是!
强迫不感兴趣或缺乏所需技能的团队或个人是创建不可靠系统、失败和可能高员工流动率的秘诀。
您可以选择与哪些人组成团队,但您无法人为地塑造一个凝聚力好的团队。你不能伪造它;没有捷径;您需要在相当长的一段时间内投入大量精力并投资于团队和个人,如果您足够幸运,您将拥有正确的人和一些凝聚力好的团队。
最后但同样重要的是,说到知识工作者环境中的管理,人不是人力资源,也不能从方程式中分解(例如工时);不这样想是我们上面讨论的不匹配心智模型的确切问题,但在社会系统领域!
忽略目标
专注于工具而不是对实际问题进行建模太常见了!大多数时候,你可以从没有经验的建筑师那里听到类似下面的话,或者根本没有建筑师的时候!
我们可以通过在此处引入 Kafka、MongoDB 和 Django 来解决这个问题,并将所有这些部署在三大洲的高可用性 k8s 集群上,以防世界末日!
— 一种以简历为导向的设计方法,用于设计一个每月有 10 个访问用户的电子商务购物网站
这主要是由于闪亮对象综合症或简历驱动的开发,它有它的宣言!
这不会以接近好的结果结束。
忽略维护和进化
Miles Glacier Bridge 的一部分,带有“kludge”(临时修复)以使桥梁在地震损坏后可用。
有时在必要和紧急的情况下应用变通方法是可以的,但从长远来看,失去大局会扼杀模型;人类曾经拥有的最有用和最出色的设计在被忽视时毫无用处。
软件应该是柔软的、可延展的和易于更改的。它也很复杂,因为它主要试图解决复杂的问题,因为过去解决了简单的问题。随着技术的进步,我们正在解决越来越复杂的问题。设计复杂系统的陷阱之一是您无法轻松弄清楚事物之间的关系,因此您无法计划如何去做。有些人会尝试解决复杂系统的复杂问题。
它不会像一个人可以一次构建一个复杂的系统一样工作。说明她完全可以理解,所以本来就不复杂!复杂系统始终是对更简单的工作系统进行增量和迭代更改的结果。
一个有效的复杂系统总是被发现是从一个有效的简单系统演变而来的。从头开始设计的复杂系统永远无法运行,也无法对其进行修补以使其运行。你必须从一个简单的工作系统重新开始。—盖尔定律
但是,忽略进化和迭代设计以及持续改进通常不会导致系统不可靠,因为达到设计需要几乎无限的时间,并且当它准备好时(如果它准备好了!),它已经没有用了;并且根本不会生产任何系统,不管它是否可靠!
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.