分布式的原理
Posted ling-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式的原理相关的知识,希望对你有一定的参考价值。
分布式系统是建立在网络之上的多台计算机,这些计算机通过网络协调工作,共同完成某个任务的系统。
分布式系统具有以下主要特点:
- 多台计算机:由多台网络连接的计算机组成。
- 分布式数据存储:数据存放在多台计算机上,需要进行分布式数据管理。
- 分布式计算:任务在多台计算机上共同完成,需要进行负载均衡和协调。
- 无共享内存:多台计算机之间没有共享内存,需要通过网络通信实现数据交换。
- 分散管理:多台计算机有各自的局部管理,需要统一起来进行全局管理和协调。
- 异步通信:计算机之间通过网络进行异步数据交换与远程调用。
- 容错性:任何一台计算机的故障都不会使系统崩溃,需要进行错误处理和容错。
- 并发性:系统可能同时处理来自不同计算机的多起事件或请求,需要进行并发控制。
分布式系统需要解决以下主要问题:
- 通信协议:计算机网络间通信使用的协议,如HTTP、RPC等。
- 统一命名:在网络中命名计算机、进程、数据等的统一方式。
- 数据一致性:复制或者分片的数据在多台计算机间的一致性问题。
- 并发控制:当多个计算机同时访问或操作数据时的协调问题。
- 故障恢复:当某些计算机发生故障时,如何恢复系统运作的问题。
- 加载均衡:控制任务或请求在不同计算机间的分布,充分利用系统资源。
- 状态管理:管理计算机之间远程调用或长连接的状态信息。
理解分布式系统的原理与实现是后端开发人员很重要的技能,通过学习可以理解很多工程化的方案与解决方案。分布式系统也是很多互联网公司考察的重点,掌握分布式知识会有很大帮助。
分布式事务原理解析
1. 分布式事务原理解析
1.1. TCC分布式事务
了解过TCC分布式事务的都知道它有三个阶段:try,confirm,cancel,但很多文章就只有原理图,和对原理图的解释,看一遍也留不下印象,这里用实际场景举个例子,说明TCC分布式事务原理
- try阶段:假设我们又订单系统,它需要调用库存和积分系统,try阶段我们进行的是预处理,比如下单1个商品,在try操作中,我们在库存表设置个冻结字段,表示冻结1个商品,商品的存量先不扣除,而积分表同样添加个预增加积分字段,添加个预积分比如10
- confirm阶段:我们为什么要经历try阶段?,为了尽可能的保证各个系统都是正常工作的,数据库,服务都没有挂掉,资源没有不足,则可以最大程度上保证confirm阶段能正确执行,confirm阶段也就是正式的扣除库存和增加积分
- cancel阶段:若try阶段执行错误,则会对前面已经执行的try阶段的系统执行cancel操作,也就是反向SQL回滚,冻结的商品-1,预积分-10。到这里有没有疑问?我首先想到的是若confirm或cancel操作再执行失败怎么办?这里就要由TCC分布式事务框架保证了,它会记录事务活动日志,再confirm或cancel失败后不断尝试调用confirm和cancel的逻辑,所以这里需要开发者自己保证,你的SQL是正确的
TCC分布式框架推荐:ByteTCC,tcc-transaction,himly
1.2. 最终一致性分布式事务
1.2.1. 原理
最终一致性方案一般都是有消息中间件来完成的,核心流程如上图所示
- 假设上游服务为服务A,可靠消息服务为服务B,下游服务为服务C,首选A发送请求给B表示我将要发消息了,你准备下,然后B记录下待确认的数据;
- A服务正式走完本地数据库逻辑,在发送B确认消息,说我执行完了,你可以确认了,然后B就更新消息的状态为已发送,并把消息发送给MQ
- 此时服务C订阅了MQ,接收到B通过MQ发送过来的消息,并执行本地数据库操作,在执行完毕后手动ack确认消费完毕,这就走完了全部流程
1.2.2. 问题
下面来考虑这中间会有什么问题了,为什么这样能保证分布式事务的最终一致性?
- 首先是服务A调用B过程中若不成功或者服务B若没保存待确认消息,那就直接返回的就是失败,还没有操作数据库,所以没有影响
- A操作数据库和发送确认消息,我们需要放在同一个本地事务中,确保同时成功或失败,这样成功了当然没问题,失败了呢?因为B服务的数据库已经存在待确认消息,可以在B服务开条线程定时判断待确认消息,若发现待确认消息很久没被确认,则主动向A发起请求,判断该操作是否成功了?成功则改状态为已确认,继续执行,失败则删掉该记录
- B到MQ的过程,若是失败了,MQ挂了之类的,我们可以在B服务后台起个线程,定时判断已确认的消息,在一定时间后是否变成已发送,没有发送的再主动发送
- 这样后就只剩MQ到C服务了,MQ有重试机制,所以只要业务逻辑没问题,就可以保证最终一致性(这个过程中需要保证MQ到C服务,接口方法需要幂等性)
- 上述流程需要特别注意的一个点就是MQ,我们需要保证MQ的高可用,否则一旦全部MQ宕机,依赖MQ的分布式事务都不能完成
1.2.3. MQ挂了怎么办
越大的公司,考虑的就越多,任何组件都可能挂掉,MQ如果就一个集群,就要考虑这个集群压力过大到爆掉了怎么办?资金雄厚并发压力大的公司可以直接搞再搞一套备用的,当MQ请求不通后,立即自动切换到备用MQ集群,当然这肯定会造成资源的浪费,毕竟要再搞一套MQ不运行一直放那里,这里再给出一套参考方案(如果你们有redis集群的话)
- redis有种队列的数据结构,它是可以用来临时充当消息队列的,所以这里要讨论的是,如果用redis当备用方案需要考虑什么问题?
- 通知机制:当MQ挂了,我们需要将所有用到MQ事务的系统都切换到备用redis方案,所以我们要有个通知机制,本来吗这个类似广播模式的通知应该是MQ完成的,但没了MQ,我们要有其它方案,比如zookeeper的watch机制,zk有监听机制可以通知监听它节点的系统,打开降级开关,达到通知其它系统的效果
- 消息读取热点问题:我们把消息放到redis的队列会有个对应的key,我们不能把所有消息都放一个key的value中,这样会导致这个value数据量过大;所以这里给出方案:划分上百个队列,对消息hash后放入这些队列,这样尽可能的把消息分散到不同的key
- 故障的恢复:当我们把MQ恢复过来时,我们也要通知系统,该切换回来了,这个该怎么做呢?可以开启一个线程,每隔一段时间尝试给MQ投递一个消息查看是否恢复,若恢复了,就可以再次通过zookeeper来关闭降级开关
以上是关于分布式的原理的主要内容,如果未能解决你的问题,请参考以下文章
分布式技术专题「分布式协调原理」全流程透析分析Zookeeper的原理实现