Lecture 1:分布式系统的主要技术思想 (MIT6.824)

笔者的个人理解以注释的方式书写。

1.1 分布式系统的驱动力和挑战(Drivens and Challenges)

分布式系统的核心是通过网络来协调,共同完成一致任务的一些计算机。分布式计算之所以如此重要的原因是,许多重要的基础设施都是在它之上建立的,它们需要多台计算机或者说本质上需要多台物理隔离的计算机。在你设计一个系统时或者面对一个你需要解决的问题时,如果你可以在一台计算机上解决,而不需要分布式系统,那你就应该用一台计算机解决问题。有很多的工作都可以在一台计算机上完成,并且通常比分布式系统简单很多。在选择使用分布式系统解决问题前,你应该要充分尝试别的思路,因为分布式系统会让问题解决变得复杂。

需要分布式的原因

  1. 性能-例如parallelism 并行计算
  2. 容错 fault tolerance-例如一台故障切换到另一个
  3. physical-天然的物理上的分布(非单台机器),例如银行间转账
  4. security / isolated 分布式带来的隔离问题
    最后一个原因是,人们构建分布式系统来达成一些安全的目标。比如有一些代码并不被信任,但是你又需要和它进行交互,这些代码不会立即表现的恶意或者出现bug。你不会想要信任这些代码,所以你或许想要将代码分散在多处运行,这样你的代码在另一台计算机运行,我的代码在我的计算机上运行,我们通过一些特定的网络协议通信。所以,我们可能会担心安全问题,我们把系统分成多个的计算机,这样可以限制出错域

代码有bug,如果是某种特定条件下触发,最终导致fail-stop可以容错,如果是正常代码逻辑一定会触发或者带来错误数据的是无法容错,详见4.1

  • 因为系统中存在很多部分,这些部分又在并发执行,你会遇到并发编程和各种复杂交互所带来的问题,以及时间依赖的问题(比如同步,异步)。这让分布式系统变得很难。
  • 另一个导致分布式系统很难的原因是,**分布式系统有多个组成部分,再加上计算机网络,你会会遇到一些意想不到的故障。**如果你只有一台计算机,那么它通常要么是工作,要么是故障或者没电,总的来说,要么是在工作,要么是没有工作。而由多台计算机组成的分布式系统,可能会有一部分组件在工作,而另一部分组件停止运行,或者这些计算机都在正常运行,但是网络中断了或者不稳定。所以,局部错误也是分布式系统很难的原因。
  • 最后一个导致分布式系统很难的原因是,人们设计分布式系统的根本原因通常是为了获得更高的性能,比如说一千台计算机或者一千个磁盘臂达到的性能。但是实际上一千台机器到底有多少性能是一个棘手的问题,这里有很多难点。所以通常需要倍加小心地设计才能让系统实际达到你期望的性能

1.2 课程结构(Course Structure)

本课通过课程讲解性能和容错,物理隔离和主要通过案例分析。
目标:通过这些论文可以让你们弄清楚,什么是基本的问题,研究者们有哪些想法,这些想法可能会,也可能不会对解决分布式系统的问题有用。
论文中的一些实施细节与实际构建软件系统有很多关联。
人们是如何通过系统容错性和性能来评估一个分布式系统。

1.3 分布式系统的抽象和实现工具(Abstraction and Implementation)

本课程主要是关于应用基础架构 infrastructure for application, 即使课程中会介绍一些关于用户或者其它基于基础架构开发的应用,但是本课程的主要关注点还是这些基础设施,主要是存储,通信(网络)和计算。

infrastructure

  1. storage–>这个概念比较清晰直观,而且已经有一些关于构建replicated、fault tolerance、high-performance(多副本,容错的,高性能)系统的实现
  2. communication–>对于本课程主要是使用
  3. computation–>eg MR

感觉存储相对来说抽象性不那么强,所以用来介绍分布式系统比较方便。网络通信对本课主要是工具。

Abstraction

将存储和计算抽象为简单的接口,这样应用使用时就无需考虑底层的分布式特性。
通过抽象构建一个接口,使其看起来像一个非分布式存储和计算系统一样,但是实际上又是一个有极高的性能和容错性的分布式系统。实际上很难能找到一个抽象来描述分布式的存储或者计算,使得它们能够像非分布式系统一样有简单易懂的接口。

应该是将低层进程抽象和封装,暴露出来的接口对于应用来说使用起来和单机系统一样简单,但是完全实现这种很难,现在也只是不断去完善。

Implementation

  • RPC(Remote Procedure Call)。RPC的目标就是掩盖我们正在不可靠网络上通信的事实。
  • threads 线程,本质是对了对多核CPU的利用效率,对本课程来说是提供了一种结构化的并发操作方式,从程序员角度来说可以简化并发操作。
  • concurrency control 并发控制,比如锁,多线程对应

1.4 performance

可扩展性(Scalability)scalable speed-up–>2xComputer–>2xPerformance/throughput

这里是指:如果我用一台计算机解决了一些问题,当我买了第二台计算机,我只需要一半的时间就可以解决这些问题,或者说每分钟可以解决两倍数量的问题。两台计算机构成的系统如果有两倍性能或者吞吐,就是我说的可扩展性。
你构建了一个系统,并且只要增加计算机的数量,系统就能相应提高性能或者吞吐量,这将会是一个巨大的成果,因为计算机只需要花钱就可以买到。花钱请程序员来修补这些代码,使它们运行的更快,通常会是一个昂贵的方法。我们还是希望能够通过从十台计算机提升到一千台计算机,就能扛住一百倍的流量。必须要时刻考虑可扩展性,需要仔细设计系统,才能获得与计算机数量匹配的性能。
有关扩展性是这样:我们希望可以通过增加机器的方式来实现扩展,但是现实中这很难实现,需要一些架构设计来将这个可扩展性无限推进下去。

可扩展性感觉在应对突发情况时比较好用,例如大促,只需要扩容即可满足需求。
看来机器扩容要比找程序员优化快速+省钱,前提是满足可扩展性,但是这种系统设计的时候就要考虑的更为复杂,而且并不能无限推进,因为后面可能会出现其它的瓶颈问题。

容错Fault tolerance

大型分布式系统中一些很罕见的问题会被放大。
软件故障(系统、进程),硬件故障(硬盘、风扇、内存等等等),网络故障。
在一个大规模分布式系统中,各个地方总是有一些小问题出现。所以**大规模系统会将一些几乎不可能并且你不需要考虑的问题,变成一个持续不断的问题。**一台计算机正常工作很长时间并不少见。然而如果你通过数千台计算机构建你的系统,那么即使每台计算机可以稳定运行一年,对于1000台计算机也意味着平均每天会有3台计算机故障。
因为错误总会发生,必须要在设计时就考虑,系统能够屏蔽错误,或者说能够在出错时继续运行。同时,因为我们需要为第三方应用开发人员提供方便的抽象接口,我们的确也需要构建这样一种基础架构,它能够尽可能多的对应用开发人员屏蔽和掩盖错误。

容错特性
  1. 可用性(Availability),某些系统经过精心的设计,这样在某些特定的错误类型下(并非所有),系统仍然能够正常运行,仍然可以像没有出现错误一样,为你提供完整的服务。某些系统通过这种方式提供可用性。比如,你构建了一个有两个拷贝的多副本系统,其中一个故障了,另一个还能运行。当然如果两个副本都故障了,你的系统就不再有可用性。可用系统通常是指,在特定的故障范围内,系统仍然能够提供服务,系统仍然是可用的。如果出现了更多的故障,系统将不再可用。
  2. **自我可恢复性(recoverability)。**如果出现了问题,服务会停止工作,不再响应请求,之后有人来修复,并且在修复之后系统仍然可以正常运行,就像没有出现过问题一样。这是一个比可用性更弱的需求,因为在出现故障到故障组件被修复期间,系统将会完全停止工作。但是修复之后,系统又可以完全正确的重新运行,所以可恢复性是一个重要的需求。对于一个可恢复的系统,通常需要做一些操作,例如将最新的数据存放在磁盘中,这样在供电恢复之后(假设故障就是断电),才能将这些数据取回来。

实际上availability的系统,也需要recoverability,因为故障太多,系统依然会停止,这时recoverability就非常重要了。

容错的常用方式
  1. 非易失存储(non-volatile storage,比如硬盘)。当出现类似电源故障,可以使用非易失存储,比如硬盘,闪存,SSD之类的。用来存放checkpoint或者系统状态的log,从而能够从中读取系统最新的状态,并从那个状态继续运行。避免频繁的写入非易失存储:移动磁盘臂并等待磁碟旋转非常缓慢。
  2. **复制(replication)。**任何一个多副本系统中,都会有一个关键的问题,本来应该是有着相同的系统状态,这两个副本总是会意外的偏离同步的状态,而不再互为副本。对于任何一种使用复制实现容错的系统,我们都面临这个问题。多副本之间的状态理论上应该是一致的,但是容易出现不一致的状态。

一致性(Consistency)

例如:假设我们在构建一个KV分布式存储系统,只支持put操作(存入key,value);get(key–>value)。整体就像是一个大的key-value表单,这是一个简单又实用的分布式存储系统,非常适合用来举例。
**一致性就是用来定义操作行为的概念。从性能和容错的角度来说,我们通常会有多个副本,**在一个分布式系统中,由于复制或者缓存,数据可能存在于多个副本当中,于是就有了多个不同版本的key-value对。
假设服务器有两个副本,那么他们都有一个key-value表单,两个表单中key 1对应的值都是20。可能发给服务器A,PUT(1,21)之后客户端挂了,服务器A成功更新,B依然是旧数据,这样后面旧可能读取到旧数据。因此需要确定put/get操作的一些规则。

一致性的定义
  • 强一致(Strong Consistency),例如get请求可以得到最近一次完成的put请求写入的值。
  • **弱一致,不保证get请求可以得到最近一次完成的put请求写入的值。事实上,构建一个弱一致的系统也是非常有用的。**虽然强一致可以确保get获取的是最新的数据,但是实现这一点的代价非常高,比如肯定需要大量通信。为了尽可能的避免通信,尤其当副本相隔的很远的时候(机房物理距离很远,还是有很高的代价的,大概是:距离21.5(光纤里走折线)/光速 详见杨传辉书中),人们会构建弱一致系统,并允许读取出旧的数据。弱一致性也有很多规则,最终一致性、会话一致性等等,这些规则可以更具实用性。

为什么副本需要相隔很远:
多副本是为了容错,因此需要降低副本之间的关联性,提升各自的独立性,因此放在较远的机房中。但是这样带来的通信耗时大概几毫秒到几十毫秒,远大于处理器执行的速度。较远的机房甚至能避免因为自然灾害带来的毁灭性错误。
有很多关于弱一致性的研究,主要是制定一定的规则,从而能够对应用来说有实用性,同时有较高的性能

感觉就是强一致性虽然好,但是有固有弊端,弱一致性的话就需要在实用和性能之间权衡,那总不能只强调性能,但是客户端使用起来很麻烦,甚至需要自己的业务逻辑去处理,即不满足1.3中的Abstraction。

感觉研究一个系统,研究其关于performance方面的实现是一方面,但是关于其接口的抽象也是很重要的一点。

参考文献:
https://pdos.csail.mit.edu/6.824/schedule.html
https://mit-public-courses-cn-translatio.gitbook.io/mit6-824/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值