分布式系统笔记(一)
分布式系统
计算机节点组成的系统,这些节点通过网络进行通信、为了完成共同的任务而协调工作。
《分布式系统与泛型》:
分布式系统时若干独立计算机的集合,这些计算机对于用户来说就像单个相关系统。
两个重要的含义
- 硬件独立
- 软件统一
所谓硬件独立,是指计算机本身时独立的。一个大型的分布式系统,会由若干台计算机来组成系统的基础设施。
而软件统一,是指对用户来说,用户就像是跟单个系统打交道。
后台运作,有几台服务器对于用户来讲是不可见的。
软件统一的另一个方面,是指分布式系统的扩展和升级都比较容易。分布式系统中某个节点发生故障不影响整体系统的可用性。
分布式系统具有透明性,要解决的问题本身就是和单机系统一样的,而且对外展现出来的特征就像一个单机系统一样。
集中式系统
集中式系统主要部署在IBM、SUN等小型机以上档次的服务器中,把所有功能都集成到主服务器上,这样对服务器的要求很高,性能也极其苛刻。
集中式系统主要流行于20世纪,现在还使用集中式系统的很少。
分布式系统和集中式系统刚好相反。分布式系统是通过中间软件来对现有的计算机的硬件能力和相应的软件功能进行重新配置和整合。
它是一种多处理器的计算机系统,各处理器通过网络互连构成统一的系统,。
系统采用分布式计算结构,即把原来系统内*处理器处理的任务分散给响应的处理器,实现不同功能各个处理器相互协调,共享系统的外设和软件。
为什么用分布式系统
上述分布式系统的特点加快了系统的处理速度,简化了主机的逻辑结构。
它甚至不需要很高的配置,一些低配置“退休”下来的主机也能被重新纳入分布式系统中使用,这样无疑就降低了成本,而且易于维护。
同时分布式系统往往由多个主机组成,任何一台主机宕机都不影响整体系统的使用,所以分布式系统的可用性往往比较高。
是为了用廉价的、普通的机器完成单个计算机无法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据。
单个节点的处理能力无法满足日益增长的计算、存储任务的时候,且硬件的提升(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,我们才需要考虑分布式系统。
两台A电脑协作的性能大于价值为2A的电脑工作的性能。
分布式系统通过分片**(partition)**的思想将任务分配给计算机节点。
优势:
1)提升性能和并发,操作被分发到不同的分片,相互独立
2)提升系统的可用性,即使部分分片不能用,其他分片不会受到影响
分布式系统挑战
而由于分布式系统多节点、通过网络通信的拓扑结构,会引入很多单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。。。
异构性
分布式系统中的机器,配置不一样,其上运行的服务也可能由不同的语言、架构实现,因此处理能力也不一样;节点间通过网络连接,而不同网络运营商提供的网络的带宽、延时、丢包率又不一样。
怎么保证大家齐头并进,共同完成目标,这四个不小的挑战。
缺乏全球时钟
在程序需要协作时,通过交换消息来协调他们的动作。
紧密的协调经常依赖于对程序动作发生时间的共识。但是,实际网络上计算机之间同步时钟的准确性受到极大的限制,即没有一个正确时间的全局概念。这是通过网络发送消息作为唯一通信方式这一事实带来的直接结果。
一致性
数据被分散或者复制到不同的机器上,如何保证各台主机上数据的一致性。
普遍的节点故障
一台电脑可能好几年都不出故障,但是大量计算机组成的系统可能每天都会有电脑出故障。
虽然单个节点的故障概率较低,但节点数目达到一定规模,出故障的概率就变高了。分布式系统需要保证故障发生的时候,系统仍然是可用的,这就需要监控节点的状态,在节点故障的情况下将该节点负责的计算、存储任务转移到其他节点
不可靠的网络
节点间通过网络通信,而网络是不可靠的。可能的网络问题包括:网络分割、延时、丢包、乱序。
相比单机过程调用,网络通信最让人头疼的是超时:节点A向节点B发出请求,在约定的时间内没有收到节点B的响应,那么B是否处理了请求,这个是不确定的,这个不确定会带来诸多问题,最简单的,是否要重试请求,节点B会不会多次处理同一个请求。
故障的独立性
任何计算机都有可能出现故障,且各种故障不尽相同。他们之间出现故障的时机也是相互独立的。一般分布式系统要设计成允许出现部分故障出现而不影响整体系统的正常使用。
并发
分布式系统的目的是为了更好的共享资源。那么系统中的每个资源都必须被设计成在并发环境中是安全的。
透明性
分布式系统中任何组件的故障,或者主机的升级、迁移,对于用户来说都是透明的、不可见的。
开放性
分布式系统由不同的程序员来编写不同的组件,组件最终集成为一个系统,那么组件所发布的接口必须遵守一定的规范且能够呗相互理解。
安全性
加密用于给共享资源提供适当的保护,在网络上所有传递的敏感信息都需要进行加密。
不确定性
不确定计算机什么时候crash、断电,不确定磁盘什么时候损坏,不确定每次网络通信要延迟多久,也不确定通信对端是否处理了发送的消息。而分布式的规模放大了这个不确定性。
有诸多的分布式理论、协议来保证在这种不确定性的情况下,系统还能继续正常工作。
可扩展性
系统要设计成随着业务量的增加,相应系统也必须能够扩展来提供相应的服务。
分布式系统的历史
分布式系统诞生于2008年
1.单应用架构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-90xojXYH-1598335072128)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824174908523.png)]
其应用服务和数据库服务,都部署在同一台服务器上。此时应用的实现简单,能够快速上线,为用户提供服务。比如很简单的可以使用Tomcat+Mysql部署在同一台机器上,提供服务。
但是随着用户数量的增加,业务内容的不断增加。其应用服务器的响应可能会慢慢变得迟缓,此时需要提升应用服务器的负载能力,保证用户的使用体验。因此需要采用更好的系统架构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ObOrVa4-1598335072133)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824183457701.png)]
2.应用服务器和数据库服务器分离
应用服务器和数据库服务器的分离,使得应用能够获得整个服务器的CPU资源来响应用户请求。应用服务器和数据库服务器的分离,也大大减少了应用的宕机风险。此时我们开始关注服务器的管理了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sSn82dGK-1598335072136)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824181124062.png)]
3.应用服务器集群
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MZxghXLP-1598335072140)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824183950413.png)]
随着用户量的继续增加,一台应用服务器可能不能满足系统的需求,因此我们需要采用应用服务器的集群架构。
通过将用户的请求分流到不同的应用服务器,从而提高整个系统的负载能力,保证用户的使用体验。
但是当应用服务器采用集群结构后,遇到了之前不存在的新问题,比如:
(1):用户的请求由谁来决定,分发给哪个服务器来处理(负载均衡问题)。
(2):用户在使用网站的过程中,如何维护用户session,保证不同的服务器响应请求时,能保证用户Session数据共享。
因此这个应用集群架构中,需要在应用服务器之上,新增一层进行负载均衡。
负载均衡器,可以分为软负载和硬负载。
软负载: Nginx或Apache等。
硬负载:F5等.
Session共享,可通过配置Tomcat的session共享来解决。但是由于Session在服务器间的复制,占用浪费带宽比较严重,此时建议Tomcat的实例不能过多。
4.数据库服务器读写分离
在完成了应用服务器的集群分布后,此时的系统瓶颈就卡在数据库服务这块了。在对数据库服务器进行分布式集群时,很容易碰到多个数据库实例上的数据不一致的问题,因此一般我们会根据提供的应用服务具体类型,综合考虑应用提供的读写服务频率等特点。可以考虑先把数据库服务的读写进行分离。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9gChh5FE-1598335072142)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824184521119.png)]
5.使用搜索引擎,缓解数据库读库压力
根据具体的业务类型,如果设计到很多模糊查询,而且数据量比较大,此时可以引入搜索引擎,如Elasticsearch。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WJxBr75j-1598335072146)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824184557450.png)]
引入了搜索引擎,则需要额外的工作,如维护索引的构建,数据同步到搜索引擎等。
6.引入缓存机制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qo2sLLXw-1598335072149)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824184632379.png)]
随着用户请求数量的增加,有一些热点数据,可能会不断的被用户访问,此时,可以把这些数据放进内存中,既避免访问数据库,又能加速响应用户请求。此时可以开始使用缓存技术,比如Redis,Memcache等。
使用缓存机制,能够缓存读库压力,提升应用性能,与读库相比,从缓存中读取数据,也能够更快的响应用户请求。
在有些使用场景中,可能需要使用一些数据,这些数据放在内存中不太合适,而放到数据库中又太麻烦,此时可以考虑使用NoSql产品,来代替传统的关系型数据库,保持这些数据。
在分布式系统中,使用NoSql时,也需要考虑缓存是否支持分布式集群。
7.数据库的水平/垂直拆分
随着业务量和数据量的持续增加,由于所有的数据都在同一个数据库中,数据库表非常多且杂,有些一个表中的数据记录已经达到了很大的数量。尽管采取了读写分离,缓存机制等,但是单个数据库中的并发连接数有一个上限,因此对数据库的访问依然会成为一个瓶颈。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bPZKTpTa-1598335072151)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824184720588.png)]
8.应用的拆分
随着业务越来越多,整个应用越来越复杂,工程规模也越来越大。此时的管理维护工作量会越来越复杂。可以考虑根据领域模型,对系统进行拆分
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DJDAj2iv-1598335072154)(C:\Users\18000\AppData\Roaming\Typora\typora-user-images\image-20200824184814150.png)]
对应用进行拆分后,可能有一些基本的操作,在每个子系统中,都会使用到,比如访问用户数据等,此时可以把这些相同的操作,抽象出来,通过提供服务的方式,提供给各个子系统使用。
因此此时遇到的一些新问题是,多个子系统之间如何进行远程通信。比如通过RPC技术(dubbo,webservice,hession,heep,RMI等),解决远程通信问题。
在系统不断进化时,整个系统也变得越来越复杂,管理难度越来越大,同时也会不断的出现新的技术,来解决不断出现的新问题,如微服务,Docker容器技术,容器编排等。
最重要的是,根据应用的实际情况,如用户量,并发数,数据量等采用最合适的架构。
分布式系统设计
分布式系统设计的本质就是:
如何合理地将一个系统拆分成多个子系统并部署到不同机器上。
由于拆分的子系统之间不可能孤立,必然存在有交互,所以他们之间如何通信就很重要,在通信过程中要识别敌我,防止信息在传递过程中被拦截和篡改(通信的安全),分布式系统要考虑不断增长的业务需求,就需要考虑其扩展性。
分布式系统还需要保证可靠性和数据的一致性。
- 如何将系统拆分为子系统
- 如何规划子系统间的通信
- 如何考虑通信过程中的安全
- 如何让子系统可以扩展
- 如何保证子系统的可靠性
- 如何实现数据的一致性
分布式结构体系
1.基于对象的体系结构
2.面向服务的架构
3.REST风格的架构
4.微服务架构(MSA)
5.容器技术
6.Servlet架构
主要的分布式技术
消息传递(Message Passing)
最初的通信机制
进行通信的两个进程使用发送原语(Send)和接收原语(Receive)进行消息的发送和接收
缺点:使分布式应用的开发成为一项繁杂的工作,开发出的程序极容易出错而又难于分析和调试
远程过程调用(Remote Procedure Call)
远程过程调用(RPC)隐蔽了网络的具体细节。使得用户调用远程服务就像进行一个本地函数的调用一样,但在通信过程中需要远程与本地进行频繁的交互。
远程求值
当要调用的过程在远程节点上并不存在,远程求职允许网络中的节点向远程节点发送子程序和参数信息。远程节点启动该“子程序”,一些初始请求可有该子程序发出,中间结果也有该子程序处理,子程序只是将最后的处理结果返回到源节点。
客户机/服务器模式(Client/Server,C/S)
通信双方有固定、预先定义好的角色:
服务器提供服务,客户使用服务。
RPC****模式和REV**模式都是客户机/服务器模式的一种。
代码点用(Code-on-demand)
针对C/S结构中资源过于集中的缺点,Code-on-demand模式使用了代码移动技术,即在需要远程服务时,首先从远程获得能执行该服务的代码。典型的例子时Java中的applet(应用小程序)和servlet(服务小程序)。
本文地址:https://blog.csdn.net/weixin_43442427/article/details/108219794