分布式

《浅析分布式系统》笔记

2017-05-09  本文已影响161人  天之蓝色

以下内容都是腾讯WeTest《浅析分布式系统》博文的摘抄,说是摘抄其实跟原文照搬差不了多少,原文地址腾讯WeTest浅析分布式系统

1. 什么是分布式系统

要理解这个问题可以从它的适用场景入手,一个非常适用于高承载量互联网业务的系统。什么叫高承载量,简单地可以理解为就是业务有非常高的被访问频率,如一个网站或者一个APP或者一网游或视频直播等每天有百万千万甚至亿级别用户访问。
当一个互联网业务架构不能够满足高承载量的需求时,对于用户的感受就是:网页打开慢,游戏或者视频卡顿。

2. 分布式系统的特性

一个分布式系统应该具备以下几点特性:
高吞吐、高并发、低延迟和负载均衡。

3. 分布式系统如何承载海量业务

分布式系统逻辑图 分布式业务架构

在实际的业务架构中,分布式系统会设计成多个层次的,为了把请求交给正确的进程处理,需要设计很多专门用于转发请求的进程和服务器,这些进程常以Proxy或者Router命名。这些代理很多时候是通过TCP来连接前端和后端,但是tcp有故障后不容易恢复的问题且其网络编程复杂,所以有了更好的进程间通讯机制----消息队列。

为了让分层模式(代理、路由)变得高效简单,又采用了很多相关技术。如:

Memcache缓冲系统示意图

Memcache不能直接组建一个集群系统,如果一个Memcache不够用,就要手工用代码去分配,哪些数据应该去哪个Memcache进程。

Memcache的每笔请求,都要经过网络传输,才能去拉取内存中的数据,而没有将请求者本身的内存利用起来。为了解决这个问题就可以利用LRU算法,把数据放在一个哈希表结构的堆内存中。

因为Memcache不支持集群,为了又能将缓存分布到不同的机器上,因此出现了读写分离技术,即缓存每次写都写到多个缓冲进程中去,但是读的时候可以读取任何一个进程。读写分离的方案很适用于有明显读写不平衡的业务数据。

对于读写没有明显不平衡的业务系统如:社区、游戏,读写分离就不在适用于它们。在这些系统中要同时将请求方本地内存和远端进程的内存缓存结合起来使用,就需要使用到“一致性哈希算法”,以实现一个数据不在同时写往多个缓存进程上,而是按一定规律分布在多个进程上。这样做的好处是当某一个进程失效时,不会影响整个集群中所有的缓存数据,其它缓存进程不用修改缓存记录。

CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。---------百度百科

分布式系统CAP理论示意图

在很多互联网业务中并不需要很复杂的关系型数据库,数据表来存储数据,对于索引也只是需要能够根据主索引搜索即可, 所以就产生了NoSQL数据库,早期的有MangoDB,现在比较流行的是Redis。

NoSQL相较于SQL型数据库具有更快、承载量更大的优势。它们只需要按照一条索引来检索和写入数据,利用分布式进行部署,在部署时我们可以按这条主索引来定义数据存放的进程(服务器)。这样就可以很方便的将数据存放在不同的服务器上,形成分布式部署。

4. 分布式系统在管理上存在的问题

分布式系统中网络线路出现故障的机率也很高,这时要让系统软件具备自我维护和冗余的功能。

对于线上业务进行扩容,有可能会造成用户数据丢失或者错误。所以线上扩容适用于无状态的服务上,我们都知道HTTP就是属于无状态的连接,所以web服务一般可以进行在线扩容。但对于类似游戏这种有状态的服务几乎是不可能进行在线扩容的。

当硬件资源处于闲置状态时,分布式系统还应该对硬件资源进行缩容,将这部分资源放入其它的业务系统中。

软件版本升级,有时候还涉及到数据格式的更改,如修改数据表结构,所以软件在架构之初就应该考虑到这些,做些预设准备。

客户端程序的升级,有时候会涉及到跟服务器的通信协议改变的问题,而一般客户端升级不会和服务器同步,这就会造成一个问题,网络中需要为不同版本的客户端部署不同的服务端系统。为了避免同时维护多套服务器系统,在软件架构之初时应该使用“版本兼容”的协议定义方式。

Google Map Reduce的示意图

5. 解决分布式系统管理性问题的基本手段

一个目录服务是用来记录集群中运行的进程的状态的。集群中的进程会自动和目录服务关联,这样系统在容灾、扩容、负载均衡时可以自动根据目录服务里的数据来调整请求的目的地,从而绕开故障机器,连接新的服务器。

目录服务示意图

zookeeper是用来实现目录服务的开源软件。目录服务需要进行集群部署以防单点故障导致整个分布式系统工作异常。zookeeper可以启动奇数个进程,以组成一个集群。zookeeper的数据存储结构,是一个类似文件目录的树状系统,所以需要利用它的功能,把每个进程都绑定到其中一个分支上,通过检查这些分支来进行请求的转发,还可以在这些分支上标记负载状态,以实现负载均衡。

分布式系统中进程间更有效的通讯模型是消息队列模型。这一模型就是把进程间的交互,抽象成对一个个消息的处理,这些消息本身都有一些队列,也就是管道来对消息进行缓存,每个进程可以访问一个或者多个队列,从里面读取消息(消费)或写入消息(生产)。消息本身的路由,是由存放的队列决定的,这样就把复杂的路由问题,变成了如何管理静态的队列的问题。

一个事务的处理过程都必须在整个集群中可见,需要将事务处理每步的状态都写到目录服务上。

分布式系统中服务的变化需要用到自动的软件部署工具,如Chef,这一可编程的通用部署系统,比rpm更简便。

Chef工作原理示意图

Docker也具备强大的自动部署能力,下图为Docker的原理示意图:

Docker原理示意图 日志染色
在开源界有名为log4x的日志家族,最为出名的是log4j日志组件库。 日志服务架构示意图

6. 分布式系统给开发带来的挑战及应对

分布式系统软件开发除了满足业务需求的功能外,还需要一些功能来让多进程的系统稳定可靠地运行,这些功能的实现可以交由微服务框架来完成。

现在流行的微服务框架有EJB(企业JavaBean)、WebService。微服务框架包含了服务进程之间通讯所涉及的消息的路由、编码解码、服务状态的读写等,在开发分布式系统软件时候使用微服务框架可以简化这一过程。 WebService则是把复杂的路由、编解码等操作简化成常见的一次HTTP操作。

分布式系统复杂之处就在于需要把容灾、扩容、负载均衡等功能都融合到跨进程调用里。所以使用一套通用的代码来为所有的跨进程通讯,统一的实现容灾、扩容、负载均衡、过载保护、状态缓存命中等非功能性需求,可以大大简化整个分布式系统的复杂性。

微服务框架在路由阶段会对整个集群所有节点的状态进行观察,如哪些地址上运行了哪些服务的进程,以及这些服务进程的负载如何,是否可用,然后对于有状态的服务,还会使用一致性哈希算法,去尽量试图提高缓存的命中率。当集群中的节点状态发生变化的时候,微服务框架下的所有节点都能尽快的获得这个变化的情况,重新规划服务路由方向,从而实现自动化的路由选择,避开那些负载过高或失效的节点。

Future/Promise模型也是用于改善回调函数的写法,这种写法的基本思路是”一次性把所有回调写到一起”。

lamda模型是另一种改善回调函数的方法,lamda意味着闭包。

随着业务模型成熟到可以抽象为一些固定的软件时,分布式系统会变得更加易用,计算能力不再是代码和库,而是一个个通过网络提供服务的云---SaaS,这样使用者只需要申请一个接口,填上预期的容量额度就能直接使用了。

7. 分布式系统问题的解决方式汇总

分布式系统问题的解决方式

8. 总结

腾讯WeTest的这篇干货长文,对于接触Linux生态圈还不长的我来说,实在是干货满满。对于从整体上理解分布式系统很有帮助,所以近乎原版地将它摘抄在此,值得多读几次加深理解。

上一篇 下一篇

猜你喜欢

热点阅读