Files
CategoryResourceRepost/极客时间专栏/左耳听风/程序员练级攻略/81 | 程序员练级攻略:分布式架构入门.md
louzefeng d3828a7aee mod
2024-07-11 05:50:32 +00:00

184 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<audio id="audio" title="81 | 程序员练级攻略:分布式架构入门" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/37/eb/37043620aea394d126cb1bc07d9117eb.mp3"></audio>
学习分布式系统跟学习其它技术非常不一样,分布式系统涵盖的面非常广,具体来说涵盖如下几方面:
<li>
**服务调度**,涉及服务发现、配置管理、弹性伸缩、故障恢复等。
</li>
<li>
**资源调度**,涉及对底层资源的调度使用,如计算资源、网络资源和存储资源等。
</li>
<li>
**流量调度**,涉及路由、负载均衡、流控、熔断等。
</li>
<li>
**数据调度**,涉及数据复本、数据一致性、分布式事务、分库、分表等。
</li>
<li>
**容错处理**,涉及隔离、幂等、重试、业务补偿、异步、降级等。
</li>
<li>
**自动化运维**,涉及持续集成、持续部署、全栈监控、调用链跟踪等。
</li>
所有这些形成了分布式架构的整体复杂度,也造就了分布式系统中的很多很多论文、图书以及很多很多的项目。要学好分布式系统及其架构,我们需要大量的时间和实践才能真正掌握这些技术。
这里有几点需要你注意一下。
<li>
**分布式系统之所以复杂,就是因为它太容易出错了**。这意味着,**你要把处理错误的代码当成正常功能的代码来处理**。
</li>
<li>
**开发一个健壮的分布式系统的成本是单体系统的几百倍甚至几万倍**。这意味着,**我们要自己开发一个,需要能力很强的开发人员**。
</li>
<li>
**非常健壮的开源的分布式系统并不多,或者说基本没有**。这意味着,**如果你要用开源的那么你需要hold得住其源码**。
</li>
<li>
**管理或是协调多个服务或机器是非常难的**。这意味着,**我们要去读很多很多的分布式系统的论文**。
</li>
<li>
**在分布式环境下出了问题是很难debug的**。这意味着,**我们需要非常好的监控和跟踪系统,还需要经常做演练和测试**。
</li>
<li>
**在分布式环境下,你需要更科学地分析和统计**。这意味着,**我们要用P90这样的统计指标而不是平均值我们还需要做容量计划和评估**。
</li>
<li>
**在分布式环境下,需要应用服务化**。这意味着,**我们需要一个服务开发框架比如SOA或微服务**。
</li>
<li>
**在分布式环境下,故障不可怕,可怕的是影响面过大,时间过长**。这意味着,**我们需要花时间来开发我们的自动化运维平台**。
</li>
总之,在分布式环境下,一切都变得非常复杂。要进入这个领域,你需要有足够多的耐性和足够强的心态来接受各式各样的失败。当拥有丰富的实践和经验后,你才会有所建树。这并不是一日之功,你可能要在这个领域花费数年甚至数十年的时间。
# 分布式架构入门
学习如何设计可扩展的架构将会有助于你成为一个更好的工程师。系统设计是一个很宽泛的话题。在互联网上,关于架构设计原则的资源也是多如牛毛。所以,你需要知道一些基本概念,对此,这里你先阅读下面两篇文章。
<li>
[Scalable Web Architecture and Distributed Systems](http://www.aosabook.org/en/distsys.html) ,这篇文章会给你一个大概的分布式架构是怎么来解决系统扩展性问题的粗略方法。
</li>
<li>
[Scalability, Availability &amp; Stability Patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns) 这个PPT能在扩展性、可用性、稳定性等方面给你一个非常大的架构设计视野和思想可以让你感受一下大概的全景图。
</li>
然后我更强烈推荐GitHub上的一篇文档 - [System Design Primer](https://github.com/donnemartin/system-design-primer) ,这个仓库主要组织收集分布式系统的一些与扩展性相关的资源,它可以帮助你学习如何构建可扩展的架构。
目前这个仓库收集到了好些系统架构和设计的基本方法。其中包括CAP理论、一致性模型、可用性模式、DNS、CDN、负载均衡、反向代理、应用层的微服务和服务发现、关系型数据库和NoSQL、缓存、异步通讯、安全等。
我认为上面这几篇文章基本足够可以让你入门了因为其中基本涵盖了所有与系统架构相关的技术。这些技术足够这世上90%以上的公司用了,只有超级巨型的公司才有可能使用更高层次的技术。
# 分布式理论
下面,我们来学习一下分布式方面的理论知识。
首先,你需要看一下 [An introduction to distributed systems](https://github.com/aphyr/distsys-class)。 这只是某个教学课程的提纲我觉得还是很不错的几乎涵盖了分布式系统方面的所有知识点而且辅以简洁并切中要害的说明文字非常适合初学者提纲挈领地了解知识全貌快速与现有知识结合形成知识体系。这也是一个分布式系统的知识图谱可以让你看到分布式系统的整体全貌。你可以根据这个知识图Google下去然后你会学会所有的东西。
然后,你需要了解一下拜占庭将军问题([Byzantine Generals Problem](https://en.wikipedia.org/wiki/Byzantine_fault_tolerance)。这个问题是莱斯利·兰波特Leslie Lamport于1982年提出用来解释一致性问题的一个虚构模型[论文地址](https://www.microsoft.com/en-us/research/uploads/prod/2016/12/The-Byzantine-Generals-Problem.pdf))。拜占庭是古代东罗马帝国的首都,由于地域宽广,守卫边境的多个将军(系统中的多个节点)需要通过信使来传递消息,达成某些一致的决定。但由于将军中可能存在叛徒(系统中节点出错),这些叛徒将努力向不同的将军发送不同的消息,试图会干扰一致性的达成。拜占庭问题即为在此情况下,如何让忠诚的将军们能达成行动的一致。
对于拜占庭问题来说,假如节点总数为 `N`,叛变将军数为 `F`,则当 `N &gt;= 3F + 1`问题才有解即拜占庭容错Byzantine Fault TolerantBFT算法。拜占庭容错算法解决的是网络通信可靠但节点可能故障情况下一致性该如何达成的问题。
最早由卡斯特罗Castro和利斯科夫Liskov在1999年提出的实用拜占庭容错Practical Byzantine Fault TolerantPBFT算法是第一个得到广泛应用的BFT算法。只要系统中有2/3的节点是正常工作的则可以保证一致性。PBFT算法包括三个阶段来达成共识预准备Pre-Prepare、准备Prepare和提交Commit
这里有几篇和这个问题相关的文章,推荐阅读。
<li>
[Dr.Dobbs - The Byzantine Generals Problem](http://www.drdobbs.com/cpp/the-byzantine-generals-problem/206904396)
</li>
<li>
[The Byzantine Generals Problem](http://blog.jameslarisch.com/the-byzantine-generals-problem)
</li>
<li>
[Practicle Byzantine Fault Tolerance](http://pmg.csail.mit.edu/papers/osdi99.pdf)
</li>
拜占庭容错系统研究中有三个重要理论CAP、FLP和DLS。
<li>
[CAP定理](https://en.wikipedia.org/wiki/CAP_theorem)CAP理论相信你应该听说过不下N次了。CAP定理是分布式系统设计中最基础也是最为关键的理论。CAP定理指出分布式数据存储不可能同时满足以下三个条件一致性Consistency、可用性Availability和 分区容忍Partition tolerance。 “在网络发生阻断partition你只能选择数据的一致性consistency或可用性availability无法两者兼得”。
论点比较直观如果网络因阻断而分隔为二在其中一边我送出一笔交易“将我的十元给A”在另一半我送出另一笔交易“将我的十元给B”。此时系统要不是a无可用性即这两笔交易至少会有一笔交易不会被接受要不就是b无一致性一半看到的是A多了十元而另一半则看到B多了十元。要注意的是CAP理论和扩展性scalability是无关的在分片sharded或非分片的系统皆适用。
</li>
<li>
[FLP impossibility](http://the-paper-trail.org/blog/a-brief-tour-of-flp-impossibility/),在异步环境中,如果节点间的网络延迟没有上限,只要有一个恶意的节点存在,就没有算法能在有限的时间内达成共识。但值得注意的是, [“Las Vegas” algorithms](https://en.wikipedia.org/wiki/Las_Vegas_algorithm)这个算法又叫撞大运算法其保证结果正确只是在运算时所用资源上进行赌博一个简单的例子是随机快速排序它的pivot是随机选的但排序结果永远一致在每一轮皆有一定机率达成共识随着时间增加机率会越趋近于1。而这也是许多成功的共识算法会采用的解决问题的办法。
</li>
<li>
容错的上限,从[DLS论文](http://groups.csail.mit.edu/tds/papers/Lynch/jacm88.pdf) 中我们可以得到以下结论:
<ul>
<li>
在部分同步partially synchronous的网络环境中即网络延迟有一定的上限但我们无法事先知道上限是多少协议可以容忍最多1/3的拜占庭故障Byzantine fault
</li>
<li>
在异步asynchronous的网络环境中具有确定性质的协议无法容忍任何错误但这篇论文并没有提及 [randomized algorithms](http://link.springer.com/chapter/10.1007%2F978-3-540-77444-0_7)在这种情况下可以容忍最多1/3的拜占庭故障。
</li>
<li>
在同步synchronous网络环境中即网络延迟有上限且上限是已知的协议可以容忍100%的拜占庭故障但当超过1/2的节点为恶意节点时会有一些限制条件。要注意的是我们考虑的是"具有认证特性的拜占庭模型authenticated Byzantine",而不是"一般的拜占庭模型";具有认证特性指的是将如今已经过大量研究且成本低廉的公私钥加密机制应用在我们的算法中。
</li>
当然还有一个著名的“8条荒谬的分布式假设[Fallacies of Distributed Computing](http://en.wikipedia.org/wiki/Fallacies_of_distributed_computing))”。
1. 网络是稳定的。
1. 网络传输的延迟是零。
1. 网络的带宽是无穷大。
1. 网络是安全的。
1. 网络的拓扑不会改变。
1. 只有一个系统管理员。
1. 传输数据的成本为零。
1. 整个网络是同构的。
阿尔农·罗特姆-盖尔-奥兹Arnon Rotem-Gal-Oz写了一篇长文 [Fallacies of Distributed Computing Explained](http://www.rgoarchitects.com/Files/fallacies.pdf) 来解释为什么这些观点是错误的。另外,[加勒思·威尔逊Gareth Wilson的文章](https://shimo.im/docs/gYpKDyQv6CXGgHTr) 则用日常生活中的例子对这些点做了通俗的解释。为什么我们深刻地认识到这8个错误是因为这要我们清楚地认识到——在分布式系统中错误是不可能避免的我们在分布式系统中能做的不是避免错误而是要把错误的处理当成功能写在代码中。
下面分享几篇一致性方面的论文。
<li>
当然关于经典的CAP理论也存在一些误导的地方这个问题在2012年有一篇论文 [CAP Twelve Years Later: How the Rules Have Changed](https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed) [中译版](http://www.infoq.com/cn/articles/cap-twelve-years-later-how-the-rules-have-changed)中做了一些讨论主要是说在CAP中最大的问题就是分区也就是P在P发生的情况下非常难以保证C和A。然而这是强一致性的情况。
其实在很多时候我们并不需要强一致性的系统所以后来人们争论关于数据一致性和可用性时主要是集中在强一致性的ACID或最终一致性的BASE。当时BASE还不怎么为世人所接受主要是大家都觉得ACID是最完美的模型大家很难接受不完美的BASE。在CAP理论中大家总是觉得需要“三选二”也就是说P是必选项那“三选二”的选择题不就变成数据一致性(consistency)、服务可用性(availability) 间的“二选一”?
然而现实却是P很少遇到而C和A这两个事工程实践中一致性有不同程度可用性也有不同等级在保证分区容错性的前提下放宽约束后可以兼顾一致性和可用性两者不是非此即彼。其实在一个时间可能允许的范围内是可以取舍并交替选择的。
</li>
<li>
[Harvest, Yield, and Scalable Tolerant Systems](https://pdfs.semanticscholar.org/5015/8bc1a8a67295ab7bce0550886a9859000dc2.pdf) 这篇论文是基于上面那篇“CAP 12年后”的论文写的它主要提出了Harvest和Yield概念并把上面那篇论文中所讨论的东西讲得更为仔细了一些。
</li>
<li>
[Base: An Acid Alternative](https://queue.acm.org/detail.cfm?id=1394128) [中译版](http://www.cnblogs.com/savorboard/p/base-an-acid-alternative.html)本文是eBay的架构师在2008年发表给ACM的文章是一篇解释BASE原则或者说最终一致性的经典文章。文中讨论了BASE与ACID原则的基本差异, 以及如何设计大型网站以满足不断增长的可伸缩性需求,其中有如何对业务做调整和折中,以及一些具体的折中技术的介绍。一个比较经典的话是——“在对数据库进行分区后,为了可用性Availability牺牲部分一致性Consistency可以显著地提升系统的可伸缩性(Scalability)”。
</li>
<li>
[Eventually Consistent](https://www.allthingsdistributed.com/2008/12/eventually_consistent.html) 这篇文章是AWS的CTO维尔纳·沃格尔Werner Vogels在2008年发布在ACM Queue上的一篇数据库方面的重要文章阐述了NoSQL数据库的理论基石——最终一致性对传统的关系型数据库ACIDTransaction做了较好的补充。
</li>
# 小结
好了总结一下今天分享的内容。文章的开头我给出了学习分布式架构需要注意的几个关键点然后列出了入门学习的资源基本涵盖了所有与系统架构相关的技术。随后讲述了拜占庭容错系统研究中有三个重要理论CAP、FLP和DLS以及8条荒谬的分布式假设从理论和认知等角度让你更为清楚地理解分布式系统。最后分享了几篇一致性相关的论文很实用很经典推荐阅读。
下篇文章中,我将推荐一些分布式架构的经典图书和论文,并给出了导读文字,几乎涵盖了分布式系统架构方面的所有关键的理论知识。敬请期待。
下面是《程序员练级攻略》系列文章的目录。
- [开篇词](https://time.geekbang.org/column/article/8136)
<li>入门篇
<ul>
- [零基础启蒙](https://time.geekbang.org/column/article/8216)
- [正式入门](https://time.geekbang.org/column/article/8217)
- [程序员修养](https://time.geekbang.org/column/article/8700)
- [编程语言](https://time.geekbang.org/column/article/8701)
- [理论学科](https://time.geekbang.org/column/article/8887)
- [系统知识](https://time.geekbang.org/column/article/8888)
- [软件设计](https://time.geekbang.org/column/article/9369)
- [Linux系统、内存和网络系统底层知识](https://time.geekbang.org/column/article/9759)
- [异步I/O模型和Lock-Free编程系统底层知识](https://time.geekbang.org/column/article/9851)
- [Java底层知识](https://time.geekbang.org/column/article/10216)
- [数据库](https://time.geekbang.org/column/article/10301)
- [分布式架构入门(分布式架构)](https://time.geekbang.org/column/article/10603)
- [分布式架构经典图书和论文(分布式架构)](https://time.geekbang.org/column/article/10604)
- [分布式架构工程设计(分布式架构)](https://time.geekbang.org/column/article/11232)
- [微服务](https://time.geekbang.org/column/article/11116)
- [容器化和自动化运维](https://time.geekbang.org/column/article/11665)
- [机器学习和人工智能](https://time.geekbang.org/column/article/11669)
- [前端基础和底层原理(前端方向)](https://time.geekbang.org/column/article/12271)
- [前端性能优化和框架(前端方向)](https://time.geekbang.org/column/article/12389)
- [UI/UX设计前端方向](https://time.geekbang.org/column/article/12486)
- [技术资源集散地](https://time.geekbang.org/column/article/12561)