介绍
这是关于分布式架构新手入门的第五篇文章。这一篇文章主要介绍通过计算分布式系统中的单次请求成功率,以及重复请求的稳定率获得系统的稳定性估值。依据软件结构评估性能及其冗余。通过对系统的分析判断出潜在的性能瓶颈。为设计分布式系统提供数据支持。
您可以点击以下链接找到前面四篇文章。
l Distributed Method of Web Services
l ITDSD - 1. Splitting in Microservice Architecture
l ITDSD - 2. Practice of Splitting in Microservice Architecture
l ITDSD - 3. Overview of Distributed Software Engineering
有共享数据的网络必然是异步网络
当多个任务试图共同使用一个数据时。任务通常需要排队轮流使用这个数据。因为同时使用数据会造成数据损坏,通常为每个任务分别修改了数据的一部分导致数据整体损坏。这种多个任务对一个数据不可同时运行的情况称为数据的原子性。这时的数据在多个任务之间是负有一致性功能的协议,因而在多个任务运行关系中具有无法替代的作用。而对数据的轮流使用保证了任务之间通过数据地址进行的信息交换。异步模型和同步模型描述了在使用数据时任务的执行状态。例如一个任务正在使用数据而另一个任务在等待。则等待的任务被称为同步执行。如图1。
在分布式环境下客户端和服务器通过消息触发相关任务的执行。客户端的任务发送请求触发服务器的任务被执行。通常在服务器执行请求并返回前客户端会阻塞任务的执行等待返回。客户端的阻塞保证了客户端的状态在服务端返回前不会发生变化。这样服务端返回后可以继续当前客户端的处理。我们称这时客户端是同步执行请求。而服务器是异步执行请求。因为服务处理完这个请求后不会阻塞,并等待客户端其他的指令。这样保证了服务可以依次处理其他的客户端请求。按连接等待还是按处理请求等待是同步和异步的重要区别。如图2。
为了证明由具有共享数据的单线程服务器组成的网络必然是异步网络。首先假设客户端和服务器创建链接后都使用同步方式,并且能与其他客户端共享数据。即任意方处理完消息后都阻塞等待对方发送新的消息。这样的链接方式称为完全同步模式。在完全同步模式下,只要客户端保持链接,则服务器就不能处理其他的客户端请求。假设客户端的链接时间为无穷大时则服务器被占用的时间也为无穷大。那么服务器也就在无穷大的时间内无法处理其他的客户端请求。如图3所示。
则服务器必然在无穷大的时间里无法与其他客户端共享数据。这与我们的假设相互矛盾。所以我们得到了定理1。
定理1,由共享数据的单线程服务器组成的网络必然是异步网络。
有共享数据的异步网络的特点就是基于延迟时间t的一致性。所谓延迟时间t的一致性是指,任意获得信息的一方所获得信息都是经过了延迟时间t之后的信息。或者说任何接收端所获得的信息都是发送端在时间t之前的信息。信息的发送一方并不保证在这段时间中信息是否会发生改变。延迟时间t是基于能量守恒而得到的推论。因为服务器硬件是遵守能量守恒定律。所以在服务器硬件上任何信息的传输也遵守能量守恒定律。所以我们得到了推理1。
推理1,任意两点间的信息同步都会存在延迟时间t。
推理1表明了任意点拿到的数据都是名义上较旧的数据。例如用户在服务器上查询到的比赛分数。用户在看到数据时服务端可能已经被更新成不一样的分数了。如果在为了保证用户所看到的数据在其使用过程中保证一致。那么就是要锁住服务器也就是使链接变为同步模式。由定理1得知同步模式下的网络不能共享数据。推理1也表明了信息的传递是有方向性的。这种传递会触发任务的执行,进而产生的信息也是有方向性的。顺着这种方向性便产生了对分布式网络定量分析的基础。因为在任务执行的方向上,所涉及到的硬件和软件构成了分布式系统。
串行和并发的概率
当客户端发送请求到分布式系统后,分布式系统会在一系列的服务器上执行请求。标记这些服务器为1到n其中n为任意整数。假设每个服务器都有一个出现错误的概率。这个错误包括硬件的宕机,软件的崩溃等。我们将这个出现错误的概率记为x1,则由概率公式得知多个服务器串行执行成功的概率为x1*x2*x3…xn,我们得到了公式1。例如有一个任务请求,需要通过网关服务器,web服务器,内存数据库和硬盘数据库再返回给客户端。假设这4个服务器运行正常的概率为99%,90%,96%,96%则请求成功的概率为0.99*0.9*0.96*0.96=0.82。
虽然单次的请求失败的概率较高,但当用户重复发起请求时由并发概率公式可以得知。独立事件重复请求的成功概率为1-((1-x1)*(1-x2)*(1-x3)…(1-xn)),我们得到公式2。计算两次重复请求任意一次通过的概率为,1-(1-0.82)*(1-0.82)=0.97,所以这次重复请求让概率提高了约15个百分点。可见重复请求的成功率提升,抵消了系统串行执行的成功率下降。虽然与数学上幂等的概念很相似。但依据定理1分布式系统是一个动态变化的系统,所以两次请求从结果还是过程来看都是分别独立的。
当一个系统是由多个连续的请求和并发的请求组成的复杂的系统时。例如一个由3台s1,s2,s3服务器组成的系统。其请求成功的概率分别为90%, 95%, 99%。运行着有3个r1,r2,r3请求的软件系统。其中r1调用服务器s1,s3记为r1(s1,s3)。其他的两个请求分别为r2(s1,s2,s3),r3(s2,s3)。那么我们可以分别得到 r1,r2,r3的成功概率为r1(0.9*0.99)=0.89,r2(0.9*0.95*0.99)=0.85,r3(0.95*0.99)=0.94,则系统运行概率为1-((1-0.89)*(1-0.85)*(1-0.94))=99.9%。也就是说系统所有服务都停止响应的概率为0.1%。如图4所示。
内存数据库和硬盘数据库的特性
虽然连续请求提高系统响应的概率,但系统的整体稳定性并不取决于响应成功的概率。因为如果数据库无法使用则会造成数据丢失。数据丢失会使系统彻底丧失服务能力。假设一个系统内只有内存数据库而没有硬盘数据库。则内存数据库运行正常的概率为96%。一旦内存数据库运行失败导致数据丢失则系统彻底丧失运行能力。所以系统整体的稳定性的上限就为96%。内存数据库就如同木桶中最短的那个板子一样。决定了系统整体稳定性的低点。
因为硬盘数据库可以在服务重起后仍然保证一定时间的数据不丢失。所以硬盘数据库成为系统稳定的上限。只要硬盘不损坏到无法使用导致数据丢失,即使系统重起也不会导致系统无法使用。在一份由数据备份厂商backblaze提供的硬盘故障率报告[1]中指出。其使用最多的硬盘故障率为2.22%。可以通过使用硬盘阵列RAID0,在双硬盘备份时的数据丢失率为0.05%。并且可以通过更多备份进一步降低数据丢失的概率。那么系统在使用硬盘数据库后其稳定性将大幅提升。
虽然内存数据库远没有硬盘数据库稳定。但内存数据库运行度要远快于硬盘数据库。随机读取可以达到千倍的差距,而顺序读写也有10倍左右的差距。由稳定性排序由最高到最低依次为硬盘数据库,内存数据库和服务容器。而从响应速度来看由最快到最慢依次为服务容器,内存数据库和硬盘数据库。响应速度指对用户发起的请求做出的回应。如果服务容器不使用内存数据库和硬盘数据库则处理速度是最快的。因为处理请求的响应较快所以支持的并发量是最高。当然这里的稳定性是相对的,即使是稳定最差的服务器容器。正在开发过程的服务容器会频繁的人为更新。任何更新的行为都会导致潜在停机的可能。管理得当的服务容器可以保证95%以上的平稳运行。考虑因为任何硬件都有1%到5%损坏的可能。软件稳定率已经非常接近硬件稳定率。所以内存数据库更多的是充当临时数据备份的功能。在更换服务容器期间保存数据使用。
二义性
当在分布式系统中存有多个数据时,例如内存数据库和硬盘数据库都同时存有用户账户信息称为数据的二义性。由推论1得知这种二义性存在着延迟时间t的一致性。分布式系统中的二义性会带来无法调和的数据错误。假设有如下系统,在服务器容器接受用户数据并返回,并将数据依次传播到内存数据库和硬盘数据库。如图5所示。
假设在传播的过程中写入硬盘数据库失败,而这时已经返回给用户操作成功。当用户下线退出,内存数据库被删除。用户再次上线时就会发现数据丢失。这是用户返回和实际存储发生了二义性。
另一种可能是写入硬盘数据库成功,写入内存数据库失败。用户查询数据始终是错误的,导致用户反复操作进一步扩大了错误的影响。
在由服务容器向内存数据库和硬盘数据库传播的过程中。因为延迟时间t的存在,在这段时间内发生错误导致有的设备写入成功,有的设备写入失败时就产生了二义性。因为是异步系统在写入的过程中可能还伴随着其他的异步操作。导致删除错误操作变得极为困难。这种分布式中的二义性错误是因为我们试图改变延迟时间t的一致性的传播方向引起的。原本的传播方向是服务容器到内存数据库到硬盘数据库。而我们试图使用内存数据库或硬盘数据库的数据来恢复服务器容器的错误。这中间的延迟时间t和分布式的可用概率必然会产生数据错误的风险。高性能伴随着较高的风险,高稳定伴随着较低的风险。唯有风险是无法被彻底消除的。
通过将系统进行分布式可以进一步降低系统的风险。例如将多个系统拆分,分别处理不同的请求。如图6。
这时我们得到了新的方法来处理系统的风险。由公式2得知对系统进行分布式可以大幅降低系统整体无法使用的概率。那么当我们系统风险较高需要较高性能时。如果为分布式结构那么将大幅降低系统整体的风险。也就是受系统影响的用户减少为1/n其中n为分布式的数量。例如某个网站设计为服务容器,内存数据库和硬盘数据库结构。某日推广活动大量意外用户涌入导致峰值的半小时中硬盘IO写入堵塞。网站采用的是偏性能设计,忽略了硬盘数据库写入失败。在半小时内除了用户无法登陆外,已经登陆的用户所有操作都没有受到任何影响。事后分析如果拥堵时间超过1小时,内存数据库数据将被清除,就会导致用户这段时间内的操作丢失。受到拥堵影响的部分为总共10部分的分布式系统中的2部分。所以潜在可能操作丢失的用户为全部用户的2/10。
在计算机系统内也存在基于延迟时间t的一致性进行传播的过程。CPU内的缓存到内存再到硬盘就是一个传播的过程。这个过程也有数据不一致的概率,只是时间极短导致其非常的低而已。如图7。
AP-树形结构的传播
把数据从最开始被改变的地方向其他硬件进行传播的过程称为AP方法或AP关系。因为把数据单单只放在一个硬件内会导致在这个硬件使用过程中其他硬件被阻塞的问题。这种传播导致读取数据并不是最新的也不是绝对一致的而是基于延迟时间t的一致性。所以在AP关系下传播的数据不能用于具有原子关系的操作。也就是不能把AP网络内的数据再反向写入AP网络。因为延迟时间t的存在将会用较旧的数据覆盖较新的数据。如图8所示。
服务器的备份就可能导致这种旧数据覆盖新数据的情况,当主服务器下线备用服务器上线时,备用服务器内较旧的数据叠加新的请求会导致数据混乱。例如一件商品主服务器记录存货为0件,而备份服务器记录还有1件。则备份服务器上线后就会导致用户买到不存在的物品。
AP关系为我们带来了在几乎任何情况下都不会被阻塞的访问。并且可以利用树形传播的方式进行扩在。这种扩展带来了近乎于无限的流量和硬件支持。在分布式领域这是非常重要的设计方法。其被应用于内容分发,DNS,ZooKeeper等重要的分布式工具中。其分发的形式也多种多样例如gossip,路由协议等。我们也可以使用阻塞的方法保证数据不受延迟时间t的影响。或者使用竞争的算法例如Bitcoin来消除延迟时间t的影响。
在ZooKeeper这个树形发散的网络里分为了读取和写入两个不同的操作。对于读取的成功概率可以直接使用公式2得出。而写入的概率则分为了不同的阶段。对于最初的原点其写入的概率就是原点可用的概率。当原点扩散到下一层后,其再次扩散成功的概率为当前层所有节点使用公式2得出的概率。即任意节点扩散成功就认为扩散的行为还在继续。可见在AP关系中写入行为一旦开始扩散,已经扩散成功的节点越多,成功完成全部扩散的概率就越高。并且读取成功率更是高得惊人。如图9所示
协议和数据
由定理1得知分布式网络是异步网络下围绕共享数据建设的。外部的请求到达网络后要找到对应数据集,并触发任务操作数据集合。当一个数据集合在分布式网络中有多个备份时。需要选择一个数据集合进行写入然后扩散到其他的数据备份中。而这个选择被写入的数据集合必须是在分布式网络中具有唯一性。否则就会产生数据的二义性。这个数据集合一旦被选定,多个所有关于这个数据集合的操作都会被固定下来。这个选定的点成为了处理指定数据集合的硬件软件交汇点。这个点就成为了指定数据集合操作的协议。注意这里已经不仅仅局限于数据。当在分布式系统中有多个数据备份时这个选定的协议必须是唯一的。也就是说分布式系统是围绕着数据协议展开建设的。这个协议的实体就是存储着数据的硬件。没有成为协议的数据被称为备份数据或只读数据。在备份数据或只读数据上写入是无效的。
当分布式集群中计算机依据计算产生结果数据集时这个数据就已经存在了。我们可能会在存入内存数据库或硬盘数据库之后才返回客户端报告执行成功。但这个报告无论是否返回其实并不影响数据的稳定性。因为硬盘也有丢失数据的情况,只是这个可能性比较低而已。数据由开始产生再扩散到其他硬件。其源头也就是链接任务和数据的那个点称为协议。这个协议即是任务与任务之间的协议,也是任务和数据的协议。例如它可能被命名为“用户信息”的数据和注册的任务。
既然称为协议它就是有方向性的。即任务处理完成到发布为写入数据。写入数据再通过AP关系在分布式系统中扩散。如图10
读取和写入对数据是两种操作,但对于任务是执行的输入和执行的输出。所以写入数据是判断任务之间原子关系的重要依据。在异步网络下任何任务在任意时间都会被执行,所以任意两个任务之间有共同写入的数据就构成了写入冲突。也就是两个任务构成了原子关系。
异步网络下原子关系是个有趣的概念。例如我和妻子都喜欢吃牛排,那么在任何情况下两个人都可能使用做牛排的看煎锅。所以对于看煎锅的使用要进行排队。否则可能就变成我有煎锅需要牛肉,妻子有牛肉需要煎锅,谁也不能做牛排的尴尬。所以每次想做牛排的时候都要去检查日历,看看煎锅是否被占用。而实际情况是一年来我都没有做过牛排,煎锅一直被妻子使用。这个例子揭示了潜在的冲突和发生的频次有关。频次较低的情况,冲突发生的概率较低。如果假定这个煎锅是我们社区唯一的煎锅。任何社区的居民制作牛排都只能使用这个煎锅。那么我想才比较符合异步网络下对于原子关系的定义。我和所有的邻居都构成了对于煎锅的原子关系。
分布式系统设计中的性能分析
在只有一台服务器容器和一台硬盘数据库的小型系统里。一个请求的完成,从服务容器到数据库,要经过(a)服务软件,(b)服务器容器,(c)网络链接,(d)数据库软件,(e)硬盘。哪么请求成功的概率为(a)*(b)*(c)*(d)*(e)=f。如果直接将数据存入硬盘则请求要经过(a)服务软件,(b)服务器容器,(e)硬盘则请求成功的概率为(a)*(b)*(e)=g。因为0<(c)*(d)<1所以f<g,所以一台服务容器和一台硬盘数据库的小型系统请求成功率小于单独的服务容器。因为系统可以无限制的重试提高请求成功率。所以系统的整体稳定性取决于硬盘的稳定性。f和g都使用了硬盘所以整体稳定性相同。当有多个服务容器共同使用中心数据库时。如图11所示。
在之前我用社区共享的煎锅做了例子。假设其中一个服务容器正在使用煎锅那么另一个请求煎锅的服务容器将会等待。那么这个并行系统就退化为串行系统。系统将遵守Amdahl定律。即系统并行化的部分性能得到了提高,而串行化的部分阻塞在数据库。如果串行化导致数据库处理性能下降影响了数据分发功能进而影响并行化处理能力,那么将导致系统整体处理能力的下降。假设因为串行化的占用导致每个服务容器受到的影响相同为x,则n个链接被占用的时间为x*x*x…x^n,即数据库的串行化会导致整体处理能力成指数级别下降。出现的问题越多掉线或重试导致性能需求越大进而导致问题更严重。串行化的部分没有得到很好的解决。例如锁住表1请求表2和锁住表2请求表1的两个任务会形成死锁。如图12所示
在互联网软件系统中有80%的数据是非活跃数据。这些数据存储在硬盘上并不需要计算。而20%的数据是当前需要计算的数据。硬盘数据库定位是管理这80%的数据并且提供多维度的大数据分析功能。当数据因为用户使用被激活时需要调入服务容器进行处理。假设硬盘阵列有288T容量,那么系统运行时需要56T的内存。单台服务器无法提供这么多的运行内存,所以系统需要分布式服务器。
数据集中并被剥离的方式有助并行部分的分布式。有助于分布式系统内性能的优化,例如降低硬盘数据库的计算能力。但对串行化的部分没有任何帮助。其本质是软件的AP化,即数据的可用性和协议性。如图11所示,数据的可用性的提高对分布式的性能的提升是有限的。提升到一定的程度就会受限于串行化部分。因为在这个系统的串行部分都高度集中在数据库。即使是两个不互相影响的串行化也都必须在数据库完成。因为数据库无法知道软件系统如何使用数据并建立原子关系。对于数据库来说任何表之间都有可能串行化。因为对无限可能的准备,即任意表都可能串行。数据库只有把所有表都集中放在一起。这种集中导致了数据库承担的功能无法被分解。因为串行化的部分,必须放在单一线程内保证处理的原子性。这点Amdahl定律已经证实了。软件中可并行的部分可以使用尽可能多的计算能力来承载访问压力。也就是并行部分的性能和所提供的硬件数量是线性关系。而串行部分只能在一个单独的服务容器内运行。所以串行部分无法因为硬件的增加而提高性能。所以串行部分的性能在系统内将是一个固定值。例如上个例子中的中心数据库,因为整个系统的串行部分都在数据库中执行。那么串行部分的计算需求的和其服务容器的计算能力的比值就是整个分布式系统的性能比率。例如中央数据库的当前CPU的使用率为50%,因为所有串行操作都在中央数据库,所以就相当于整个分布式系统的计算能力已经使用50%。
假如我们有两个中心数据库来处理串行化的部分。其中一台CPU使用率为100%另一台为50%那么我们整体使用率是否为75%呢?显然不是,因为100%的服务器有大量潜在计算需求无法处理濒临崩溃。如果小于100%可以近似的认为需求得到满足,如果任意服务器已经大于100%则超出了正常使用范围。
可见在分布式系统中决定系统性能的是串行部分,也就是具有原子关系的部分。也就是在RP方法中有读写或只写数据的任务。串行部分也不是完整不可分割的,依据写入数据的不同可以进行分割。考虑有两个Amdahl的系统运行在同一组硬件内。
那么其两个串行部分放在同一个硬件内就会导致整体性能较低,而拆开放在两个不同的硬件内就会提高整体性能。一个复杂的软件系统可能存在多个Amdahl系统。找到这些Amdahl系统并将其各自放到独立硬件中就可以大幅提高分布式系统处理上限。RP方法就是为了找到这些隐藏的Amdahl系统。从根本上提高分布式系统的处理能力的上限。
当我们找到所有软件系统内隐藏的Amdahl系统后,就可以依据Amdahl系统的数量乘以使用的硬件得出分布式系统的可承载能力的上限。例如我们有2个Amdahl系统分别为支付和购买,每个系统的单用户请求需要大约0.001秒进行处理。那么将这两个Amdahl系统放入分别放入两台服务器中。则支付和购买的用户没秒并发的上限为2000人。
结论
软件系统是由可并行部分和串行部分组成。串行部分又有多个串行部分组成。按Adam定理,并行部分的性能与硬件数量成正比。串行部分与硬件性能成正比。因为串行部分通常只占软件系统全部的20%,所以通常分布式系统只是解决了80%的并行部分。再叠加80%的软件系统并不会有高强度的并发访问。这样分布式系统大约只有4%的部分是涉及高强度的访问。并且只有非常少数的顶级公司会关注这4%的串行问题。所以串行问题可能带来的各种问题常常被人们忽略。甚至这些串行问题被简单的当成了系统bug。并不是说一般的公司和系统不需要分布式系统。因为不出问题只是概率上较低而已。一旦出现问题对公司的技术团队将是致命的打击。技术人员应当关注任何可能出现的系统缺陷。
在下一章中我将用网上商场的网站举例如何创建一个分布式系统。如何在分片,缓存,硬盘之间做到平衡。
引用
1,https://www.backblaze.com/blog/backblaze-hard-drive-stats-q1-2019/
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。