分布式理论涵盖分布式系统设计模块、算法和微服务相关的理论知识。文章结尾推荐了一篇近期看到的一篇关于淘宝架构演进的文章,学习到一定程度再从全局看一下分布式架构的整体,有一种豁然开朗的感觉(当然肯定还有很多不足之处哈哈),分享给大家。
重定向(redirect)
这种方式,是通过将请求全部发送到前置机,由前置机通过算法得出要分配给哪台应用服务器,然后响应给客户端,由客户端重定向到应用服务器的一种方式。由于每一个请求,都要重定向一下,所以效率不是很高。
反向代理(转发forward)
这种方式,是通过在前置机,使用反向代理的方式,将请求分发到应用服务器,客户端无需再请求一次,实现方式通常有两种,一种是用交换机实现,还有一种是用nginx这一类的软件实现。由于不需要再次重定向,所以较第一种,效率较高,但是由于请求和响应都是通过前置机来的,所以对前置机的考验很大
数据链路返回
这种方式,通过给应用服务器设置虚拟IP,然后通过修改mac地址的方式,将请求分发出去,而应用服务器收到请求后,可以直接响应给客户端,而不需要经过前置机。由于前置机只需要接受请求,不需要响应数据,所以,效率较第二种较高。
负载均衡算法:
将请求按顺序轮流地分配到后端服务器上,它均衡地对待后端的每一台服务器,而不关心服务器实际的连接数和当前的系统负载。
通过系统的随机算法,根据后端服务器的列表大小值来随机选取其中的一台服务器进行访问。由概率统计理论可以得知,随着客户端调用服务端的次数增多,其实际效果越来越接近于平均分配调用量到后端的每一台服务器,也就是轮询的结果。
源地址哈希的思想是根据获取客户端的IP地址,通过哈希函数计算得到的一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果便是客户端要访问服务器的序号。采用源地址哈希法进行负载均衡,同一IP地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问。
不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。
与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。
引用微服务之父,马丁.福勒的话,此为译文:
就目前而言,对于微服务业界并没有一个统一的、标准的定义(While there is no precise definition of this architectural style ) 。
但通常来说,微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分成一组小的服务,每个服务运行独立的自己的进程中,服务之间互相协调、互相配合,为用户提供最终价值。
服务之间采用轻量级的通信机制互相沟通(通常是基于 HTTP 的 RESTful API ) 。每个服务都围绕着具体业务进行构建,并且能够被独立地部署到生产环境、类生产环境等。
另外,应尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务。可以使用不同的语言来编写服务,也可以使用不同的数据存储。
SOA与微服务的区别在于如下几个方面:
CAP:要满足分区容错性的分布式系统,只能在一致性和可用性两者中,选择其中一个。
BASE(basically available, soft state, eventually consistent)是对CAP定理的延伸,是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的。其核心思想是即使无法做到强一致性(Strong consistency),但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。【拓展】
(1)基本可用:出现故障的时候,允许损失部分可用性,即,保证核心可用。
如,电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务
(2)软状态:允许系统存在中间状态,而该中间状态不会影响系统整体可用性。
软状态本质上是一种弱一致性,允许的软状态不能违背“基本可用”的要求。如,分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时(某些时刻副本数低于3)。
(3)最终一致性:系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。软状态的终极目标是最终一致性。如,分布式存储的副本数最终会达到稳定状态。
1.如何将系统拆分成多个子系统
2.如何规划子系统的通信问题
3.如何实现通信过程中的安全
4.如何才能实现子系统的可扩展性
5.如何保证子系统的可靠性
6.如何实现数据的一致性
幂等性:
对于同一个系统,在同样条件下,一次请求和重复多次请求对资源的影响是一致的,就称该操作为幂等的。
就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品使用支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额发现多扣钱了,流水记录也变成了两条,这种情况就是不幂等的。
经典解决一致性问题的方法:
此方案的核心是将需要分布式处理的任务通过消息日志的方式来异步执行。消息日志可以存储到本地文本、数据库或消息队列,再通过业务规则自动或人工发起重试。人工重试更多的是应用于支付场景,通过对账系统对事后问题的处理。
消息日志方案的核心是保证服务接口的幂等性。
BASE 的可用性是通过支持局部故障而不是系统全局故障来实现的。
如果产生了一笔交易,需要在交易表增加记录,同时还要修改用户表的金额。这两个表属于不同的远程服务,所以就涉及到分布式事务一致性的问题。
eBay提出了一个经典的解决方法,将主要修改操作以及更新用户表金额的消息放在一个本地事务来完成。同时为了避免重复消费用户表消息带来的问题,达到多次重试的幂等性,增加一个更新记录表 updates_applied 来记录已经处理过的消息。
在第一阶段,通过本地的数据库的事务保障,增加了 transaction 表及消息队列 。
在第二阶段,分别读出消息队列(但不删除),通过判断更新记录表 updates_applied 来检测相关记录是否被执行,未被执行的记录会修改 user 表,然后增加一条操作记录到 updates_applied,事务执行成功之后再删除队列。
通过以上方法,达到了分布式系统的最终一致性。【拓展】
MySql
Zk
Redis
基于数据库的分布式锁, 常用的一种方式是使用表的唯一约束特性。当往数据库中成功插入一条数据时, 代表获取到锁。将这条数据从数据库中删除,则释放锁。
什么原因造成的?比如请求量过大造成的:
可用方法:缓存、服务降级、限流。
缓存,就是用内存来顶替一部分DB的查询+数据的处理。这应该是所有业务开发人员的必修课。业务上大致可以把缓存分为三类:浏览器缓存(HTTP Cache-Control Header),CDN和服务器业务缓存。而业务缓存根据实现的结构可以分多个层级,可以用in-memory cache (如Guava Cache),或者是分布式共享Cache(如Redis)。在设计缓存一致性更新模式时,无非就是Cache Aside、Read/Write Through和Write Behind这三大种模式。有些超级NB的缓存系统自带Cluster加持(比如Ehcache即可单机用,也可以组集群)。限于本文主题,具体的缓存设计不赘述。
留意下这里说的缓存仅仅是利用了内存访问比磁盘访问快得多的特性(大概可以理解为2~3个数量级),并不会让用户感知到数据一致性哪里不对劲(与下面的降级不同)。
服务降级,是指通过降低服务质量的方法,达到节省资源的目的。简单来说就是弃车保帅。比如你的服务有ABC,平时消耗差不多的资源。突发事件时,A的请求量极大的增高了,B和C没有变化。那么可以比如减少或者暂停B和C的服务,省出资源给A用。
再比如,一个热点新闻的业务,有新闻内容,有评论,有点赞数等等。一旦新闻热点了,就可以把所有这些内容“静态化”,不必再查DB。这时虽然评论,点赞的数暂时就不准了,但是主要的服务——内容,还是让用户可以看到。这就足够了。
可以看到,降级的具体的方案,要结合业务和系统实现来综合设计,并没有定法。
降级很多时候也会用到缓存。只不过这时候使用缓存的方法就可能会以牺牲数据一致性为代价——内存里的数据和DB不一样,就不一样吧,业务上可接受,并且这段热点时间段过去了,能够恢复为一致就可以。
限流,即限制用户的请求流量。具体的做法有计数器、滑动窗口、滴漏、服务token、请求队列化等办法。这些方法的详细解释,在这里都说得比较清楚,所以我就不重复了。只是值得注意的是,现在很多生产级别的服务都是多节点分布式架构。很多单机上容易做的算法和控制逻辑到了分布式下就会带来一些实现上的麻烦。这又涉及到了分布式一致性、CAP的权衡等等问题。【拓展】
数据库分库分表后需要有一个唯一ID来标识一条数据,数据库的自增ID显然不能满足需求;特别一点的如订单、优惠券也都需要有唯一ID做标识。此时一个能够生成全局唯一ID的系统是非常必要的。那么这个全局唯一ID就叫分布式ID。
ID生成器:
Snowflake ID组成结构:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特),总共64比特组成的一个Long类型。
【详解】
在 DNS 协议中,域名每个解析记录都有 TTL(Time to live) 属性,当我们用浏览器访问网站时,首先查看这个域名在本地的缓存,若最后更新的时间距离现在没有超过 TTL,则直接使用,否则去 DNS server上获取该域名的IP。所以我们在 Name Server 上修改某条记录后,不会立刻扩散(同步)到所有的缓存服务器上,而是由各个层级的服务器根据自己的缓存判断是否过期,若过期才去同步数据。最终 的含义就在于此,由此可见如果修改一条 DNS 解析记录,最长可能要等待一个 TTL 周期才能获取最新数据,同样如果你用的 DNS 服务器如果已经有人尝试更新,服务器就不需要再次去 Name Server 更新数据了。这种分布式方式通过层层缓存大大降低了 Name Server 的负载。当然代价是一定时间更新延迟。
state machine replication: 通过记录log来保存操作的路径流程。
零、2PC (两阶段提交)协议:
两阶段:propose 》 commit
两阶段:propose 》barrier 》 commit
【参考】
关键词:proposer、acceptor、编号、多数
这里的Quorum一般是指多数派,但是你也可以设置成其他比例。
(以上情况由多个Proposer保证可用性)-----》multi Paxos
活锁:proposer不断提交议案,并且编号不断增加,则acceptor就一直不能成功决议,谓之活锁。解决办法是设置timeout再重新提交。
三、Multi Paxos (选老大)
只有唯一一个proposer选leader。
N号老大提出第I号内容为Vm的提案,则议员必须接受。(只有一次RPC,除了第一次选老大两次RPC)
简化角色(servers中选一个老大(上图中proposer和acceptor合并))
四、Raft算法(paxos简化版)
关键词:leader、follower、heartbeat、log replication、 timeout、 term(第几任leader)
以下讲解log replication:同步log到其他节点上。【详解】【动画演示】
以上演示了写请求的全部过程,大致可以分成两个步骤:
以上过程即为选举和日志拷贝的过程。
如何保证leader election呢?
election timeout
来自leader的心跳周期发送给follower,follower超过随机事件timeout未收到心跳则认为无leader。第一个timeout到期的节点会先投票给自己,之后发送投票请求给其他follower,如果接收到请求的follower还未投票就会投票给他,之后超过半数票即成为leader。注意,数据也包含在心跳包中。
总结一下,timeout分两种,一种是follower变candidate的时间,比如两个candidates同时选leader时,随机事件后在变candidate重新选;另一种是如上描述的心跳周期。
指的是两个节点同时到期,并选举自己,咋办?他们再等待随机事件后再发请求。
如下脑裂情况如何保证一致性呢?
一般来说,节点总数一般为奇数个,这样任意分割总有一个集群超半数,比如上图中的上半部分和下半部分,下集群小于半数,所以任何改动都不会提交。patition恢复时,term更低的leader会自动退出(感觉这个部分还是会有点问题,如果分出去的是少数部分且leader任期更高的话?)
以上截图来源:Raft
五、ZAB算法
六、Gossip算法
Gossip算法每个节点都是对等的,即没有角色之分。Gossip算法中的每个节点都会将数据改动告诉其他节点,节点收到数据改动,又会再次将改动传播给其他4个节点,传播路径表示为较粗的4条线。
《服务端高并发分布式架构演进之路》
关键词:分布式 负载均衡 缓存 数据库 集群 CDN
内容分发网络(Content Delivery Network,简称CDN)是建立并覆盖在承载网之上,由分布在不同区域的边缘节点服务器群组成的分布式网络。
假设通过CDN加速的域名为www.a.com
,接入CDN网络,开始使用加速服务后,当终端用户(北京)发起HTTP请求时,处理流程如下:
www.a.com
下的指定资源发起请求时,首先向LDNS(本地DNS)发起域名解析请求。www.a.com
的IP地址记录。如果有,则直接返回给终端用户;如果没有,则向授权DNS查询。www.a.com
时,返回域名CNAME www.a.tbcdn.com
对应IP地址。