系统架构演化历程-初始阶段架构
初始阶段 的小型系统 应用程序、数据库、文件等所有的资源都在一台服务器上通俗称为LAMP
特征:
应用程序、数据库、文件等所有的资源都在一台服务器上。
描述:
通常服务器 *** 作系统使用Linux,应用程序使用PHP开发,然后部署在Apache上,数据库使用MySQL,汇集各种免费开源软件以及一台廉价服务器就可以开始系统的发展之路了。
系统架构演化历程-应用服务和数据服务分离
好景不长,发现随着系统访问量的再度增加,webserver机器的压力在高峰期会上升到比较高,这个时候开始考虑增加一台webserver
特征:
应用程序、数据库、文件分别部署在独立的资源上。
描述:
数据量增加,单台服务器性能及存储空间不足,需要将应用和数据分离,并发处理能力和数据存储空间得到了很大改善。
系统架构演化历程-使用缓存改善性能
特征:
数据库中访问较集中的一小部分数据存储在缓存服务器中,减少数据库的访问次数,降低数据库的访问压力。
描述:
系统访问特点遵循二八定律,即80%的业务访问集中在20%的数据上。
缓存分为本地缓存和远程分布式缓存,本地缓存访问速度更快但缓存数据量有限,同时存在与应用程序争用内存的情况。
系统架构演化历程-使用应用服务器集群
在做完分库分表这些工作后,数据库上的压力已经降到比较低了,又开始过着每天看着访问量暴增的幸福生活了,突然有一天,发现系统的访问又开始有变慢的趋势了,这个时候首先查看数据库,压力一切正常,之后查看webserver,发现apache阻塞了很多的请求,而应用服务器对每个请求也是比较快的,看来 是请求数太高导致需要排队等待,响应速度变慢
特征:
多台服务器通过负载均衡同时向外部提供服务,解决单台服务器处理能力和存储空间上限的问题。
描述:
使用集群是系统解决高并发、海量数据问题的常用手段。通过向集群中追加资源,提升系统的并发处理能力,使得服务器的负载压力不再成为整个系统的瓶颈。
系统架构演化历程-数据库读写分离
享受了一段时间的系统访问量高速增长的幸福后,发现系统又开始变慢了,这次又是什么状况呢,经过查找,发现数据库写入、更新的这些 *** 作的部分数据库连接的资源竞争非常激烈,导致了系统变慢
特征:
多台服务器通过负载均衡同时向外部提供服务,解决单台服务器处理能力和存储空间上限的问题。
描述:
使用集群是系统解决高并发、海量数据问题的常用手段。通过向集群中追加资源,使得服务器的负载压力不在成为整个系统的瓶颈。
系统架构演化历程-反向代理和CDN加速
特征:
采用CDN和反向代理加快系统的 访问速度。
描述:
为了应付复杂的网络环境和不同地区用户的访问,通过CDN和反向代理加快用户访问的速度,同时减轻后端服务器的负载压力。CDN与反向代理的基本原理都是缓存。
系统架构演化历程-分布式文件系统和分布式数据库
随着系统的不断运行,数据量开始大幅度增长,这个时候发现分库后查询仍然会有些慢,于是按照分库的思想开始做分表的工作
特征:
数据库采用分布式数据库,文件系统采用分布式文件系统。
描述:
任何强大的单一服务器都满足不了大型系统持续增长的业务需求,数据库读写分离随着业务的发展最终也将无法满足需求,需要使用分布式数据库及分布式文件系统来支撑。
分布式数据库是系统数据库拆分的最后方法,只有在单表数据规模非常庞大的时候才使用,更常用的数据库拆分手段是业务分库,将不同的业务数据库部署在不同的物理服务器上。
系统架构演化历程-使用NoSQL和搜索引擎
特征:
系统引入NoSQL数据库及搜索引擎。
描述:
随着业务越来越复杂,对数据存储和检索的需求也越来越复杂,系统需要采用一些非关系型数据库如NoSQL和分数据库查询技术如搜索引擎。应用服务器通过统一数据访问模块访问各种数据,减轻应用程序管理诸多数据源的麻烦。
系统架构演化历程-业务拆分
特征:
系统上按照业务进行拆分改造,应用服务器按照业务区分进行分别部署。
描述:
为了应对日益复杂的业务场景,通常使用分而治之的手段将整个系统业务分成不同的产品线,应用之间通过超链接建立关系,也可以通过消息队列进行数据分发,当然更多的还是通过访问同一个数据存储系统来构成一个关联的完整系统。
纵向拆分:
将一个大应用拆分为多个小应用,如果新业务较为独立,那么就直接将其设计部署为一个独立的Web应用系统
纵向拆分相对较为简单,通过梳理业务,将较少相关的业务剥离即可。
横向拆分:将复用的业务拆分出来,独立部署为分布式服务,新增业务只需要调用这些分布式服务
横向拆分需要识别可复用的业务,设计服务接口,规范服务依赖关系。
系统架构演化历程-分布式服务
特征:
公共的应用模块被提取出来,部署在分布式服务器上供应用服务器调用。
描述:
随着业务越拆越小,应用系统整体复杂程度呈指数级上升,由于所有应用要和所有数据库系统连接,最终导致数据库连接资源不足,拒绝服务。
Q:分布式服务应用会面临哪些问题?
A:
(1) 当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
(2) 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
(3) 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
(4) 服务多了,沟通成本也开始上升,调某个服务失败该找谁?服务的参数都有什么约定?
(5) 一个服务有多个业务消费者,如何确保服务质量?
(6) 随着服务的不停升级,总有些意想不到的事发生,比如cache写错了导致内存溢出,故障不可避免,每次核心服务一挂,影响一大片,人心慌慌,如何控制故障的影响面?服务是否可以功能降级?或者资源劣化?
Java分布式应用技术基础
分布式服务下的关键技术:消息队列架构
消息对列通过消息对象分解系统耦合性,不同子系统处理同一个消息
分布式服务下的关键技术:消息队列原理
分布式服务下的关键技术:服务框架架构
服务框架通过接口分解系统耦合性,不同子系统通过相同的接口描述进行服务启用
服务框架是一个点对点模型
服务框架面向同构系统
适合:移动应用、互联网应用、外部系统
分布式服务下的关键技术:服务框架原理
分布式服务下的关键技术:服务总线架构
服务总线同服务框架一样,均是通过接口分解系统耦合性,不同子系统通过相同的接口描述进行服务启用
服务总线是一个总线式的模型
服务总线面向同构、异构系统
适合:内部系统
分布式服务下的关键技术:服务总线原理
分布式架构下系统间交互的5种通信模式
request/response模式(同步模式):客户端发起请求一直阻塞到服务端返回请求为止。
Callback(异步模式):客户端发送一个RPC请求给服务器,服务端处理后再发送一个消息给消息发送端提供的callback端点,此类情况非常合适以下场景:A组件发送RPC请求给B,B处理完成后,需要通知A组件做后续处理。
Future模式:客户端发送完请求后,继续做自己的事情,返回一个包含消息结果的Future对象。客户端需要使用返回结果时,使用Future对象的get(),如果此时没有结果返回的话,会一直阻塞到有结果返回为止。
Oneway模式:客户端调用完继续执行,不管接收端是否成功。
Reliable模式:为保证通信可靠,将借助于消息中心来实现消息的可靠送达,请求将做持久化存储,在接收方在线时做送达,并由消息中心保证异常重试。
五种通信模式的实现方式-同步点对点服务模式
五种通信模式的实现方式-异步点对点消息模式1
五种通信模式的实现方式-异步点对点消息模式2
五种通信模式的实现方式-异步广播消息模式
分布式架构下的服务治理
服务治理是服务框架/服务总线的核心功能。所谓服务治理,是指服务的提供方和消费方达成一致的约定,保证服务的高质量。服务治理功能可以解决将某些特定流量引入某一批机器,以及限制某些非法消费者的恶意访问,并在提供者处理量达到一定程度是,拒绝接受新的访问。
基于服务框架Dubbo的服务治理-服务管理
可以知道你的系统,对外提供了多少服务,可以对服务进行升级、降级、停用、权重调整等 *** 作
可以知道你提供的服务,谁在使用,因业务需求,可以对该消费者实施屏蔽、停用等 *** 作
基于服务框架Dubbo的服务治理-服务监控
可以统计服务的每秒请求数、平均响应时间、调用量、峰值时间等,作为服务集群规划、性能调优的参考指标。
基于服务框架Dubbo的服务治理-服务路由
基于服务框架Dubbo的服务治理-服务保护
基于服务总线OSB的服务治理-功能介绍
基于服务总线OSB的服务治理
Q:Dubbo到底是神马?
A:
淘宝开源的高性能和透明化的RPC远程调用服务框架
SOA服务治理方案
Q:Dubbo原理是?
A:
-结束-随着信息技术的发展,网络阅卷系统在各类考试中逐渐得到应用,减少了人工阅卷方式在试卷处理、试卷评阅及成绩处理等环节的工作量。高考改卷采用网络阅卷系统较早,由于受电脑数量、评卷教师人数等因素限制,高考改卷一般采用分科集中阅卷的方式,每个学科由300人至400人分组单独阅卷,后期通过人工合成各科成绩。由于集中式网络阅卷在人员安排、电脑配置上的局限性,因此,需要研究在教育城域网内如何实现分布式网络阅卷,解决更大规模人数的阅卷问题。下面以我市为例介绍解决方式。
台州市9个县区的学校有高中阶段每个年级各约2万考生,参加10个科目的统考。自2008年实施分布式网络阅卷系统(以下简称本系统)以来,台州市教育系统经过对本系统的多次调整优化,目前可以实现2400人同时评阅高中段6万考生的试卷,在2天内完成所有阅卷工作,并自动生成相应的学生成绩表及分析报表。本系统由网络系统、硬件系统及软件系统三部分组成。
一、网络系统设计
网络系统是实施分布式阅卷的基础,用于各个分布式阅卷点的网络接入。因为各个学校网络接入形式不一致,既有通过县区教育城域网统一出口的学校,也有直接接入互联网的学校。另外,各类考试的保密要求不同,如中考阅卷具有保密性要求,而高中期末考试则无相应要求。因此,本系统应考虑多种网络接入方式,无保密性要求的网络阅卷可通过互联网接入,具有保密要求的网络阅卷则可以通过专网接入,可采用MPLS 或SDH等方式通过光纤组网,确保系统运行时与其他网络物理隔离。
首先,需要考虑本系统网络的稳定性问题。由于SDH方式组网后对广播风暴抑制能力较弱,台州市中考阅卷采用MPLS 网络接入,每个县区设置一个接入点,用于当地阅卷客户端的接入及扫描数据上传。高中期末联考则采用MPLS 网络与互联网接入混合的方式。
其次,需要考虑本系统互联网出口带宽及MPLS 汇聚带宽的问题。经多次网络阅卷运行测试,每个评卷客户端在阅卷时主要传送试卷切分,所需平均带宽为40Kbps至50Kbps。台州市高中段一个年级2万考生所有学科评阅卷所需带宽约为72Mbps至80Mbps,按这样的带宽考虑本系统扩充问题,以及后期教育资源共享等应用业务的开展,互联网出口采用100Mbps专线,MPLS 网络采用1000Mbps专线。
二、硬件系统设计
1服务器系统
服务器系统包括数据库服务器、评卷服务器、图像服务器,是分布式阅卷软件运行的基础平台。数据库服务器为数据库系统的稳定运行提供保障,对CPU资源要求较高。本系统采用ORACLE 9i作为后台数据库。经实际测试,在2×2CPU+4G内存配置的单台服务器平台上同时进行高中段10个科目,每个科目单个年级段有2万条记录的网络评卷,系统运行稳定。评卷服务器实现网络阅卷界面的登录,主要负责>
分布式系统架构中,分布式事务问题是一个绕不过去的挑战。而微服务架构的流行,让分布式事问题日益突出!
下面我们以电商购物支付流程中,在各大参与者系统中可能会遇到分布式事务问题的场景进行详细的分析!
如上图所示,假设三大参与平台(电商平台、支付平台、银行)的系统都做了分布式系统架构拆分,按上数中的流程步骤进行分析:
1、电商平台中创建订单:预留库存、预扣减积分、锁定优惠券,此时电商平台内各服务间会有分布式事务问题,因为此时已经要跨多个内部服务修改数据;
2、支付平台中创建支付订单(选yhk支付):查询账户、查询限制规则,符合条件的就创建支付订单并跳转银行,此时不会有分布式事务问题,因为还不会跨服务改数据;
3、银行平台中创建交易订单:查找账户、创建交易记录、判断账户余额并扣款、增加积分、通知支付平台,此时也会有分布式事务问题(如果是服务化架构的话);
4、支付平台收到银行扣款结果:更改订单状态、给账户加款、给积分帐户增加积分、生成会计分录、通知电商平台等,此时也会有分布式事务问题;
5、电商平台收到支付平台的支付结果:更改订单状态、扣减库存、扣减积分、使用优惠券、增加消费积分等,系统内部各服务间调用也会遇到分布式事问题;
如上图,支付平台收到银行扣款结果后的内部处理流程:
1、支付平台的支付网关对银行通知结果进行校验,然后调用支付订单服务执行支付订单处理;
2、支付订单服务根据银行扣款结果更改支付订单状态;
3、调用资金账户服务给电商平台的商户账户加款(实际过程中可能还会有各种的成本计费;如果是余额支付,还可能是同时从用户账户扣款,给商户账户加款);
4、调用积分服务给用户积分账户增加积分;
5、调用会计服务向会计(财务)系统写进交易原始凭证生成会计分录;
6、调用通知服务将支付处理结果通知电商平台;
如上图,把支付系统中的银行扣款成功回调处理流程提取出来,对应的分布式事务问题的代码场景:
/ 支付订单处理 /
@Transactional(rollbackFor = Exceptionclass)
public void completeOrder() {
orderDaoupdate(); // 订单服务本地更新订单状态
accountServiceupdate(); // 调用资金账户服务给资金帐户加款
pointServiceupdate(); // 调用积分服务给积分帐户增加积分
accountingServiceinsert(); // 调用会计服务向会计系统写入会计原始凭证
merchantNotifyServicenotify(); // 调用商户通知服务向商户发送支付结果通知
}
本地事务控制还可行吗?
以上分布式事务问题,需要多种分布式事务解决方案来进行处理。
订单处理:本地事务
资金账户加款、积分账户增加积分:TCC型事务(或两阶段提交型事务),实时性要求比较高,数据必须可靠。
会计记账:异步确保型事务(基于可靠消息的最终一致性,可以异步,但数据绝对不能丢,而且一定要记账成功)
商户通知:最大努力通知型事务(按规律进行通知,不保证数据一定能通知成功,但会提供可查询 *** 作接口进行核对)
阿里云 SLB 是一个很好的调度员,把访问流量均衡的分配给后端的多台 ECS 实例服务器 ,达到加速访问,提高业务稳定性的作用。你可以在负载均衡中添加多台 ECS 云服务器,并且提前设置好运行规则。当阿里云 SLB 启动后,就根据预先设定的规则分发流量。如果遇到某台云服务器故障,就会自动隔离掉故障服务器,保障了整个业务的稳定运行。
是网站中最常用的加速功能。通过分布式服务器布局,把网站业务内容缓存到各地的云服务器中,供访客就近访问。所以使用了 CDN 的网站业务,打开速度特别快。
阿里云CDN官方页面: 点我直达
关于阿里云 CDN 的问题及解答请移步 阿里云 CDN 配置过程及疑问解答 ,老魏强烈建议网站业务都要使用 CDN 加速功能。价格也不贵,普通网站一年几十块钱就搞定了。
局限性在于普通CDN加速只给静态内容加速,比如、文档等。
是有安全防护能力的CDN服务。用官方解释来说,SCDN 能够提前预判外界攻击行为,并将恶意请求切换到高防IP,无需人为 *** 作。目的是通过数据清洗把恶意流量去除。而真实用户的请求则正常打开页面,这样就兼顾了智能加速和安全工作。
官方网址: 点我直达
因为传统的CDN加速服务,只具备最基本的抗攻击功能,不过无法抵挡大规模的DDoS、CC攻击。单独使用高防IP保护源站的方式又无法兼顾加速。而在游戏、金融、政企安防、电商、医疗领域等易受攻击又必须兼顾加速的业务场景,需要同时有高防能力和稳定高效的安全CDN加速服务。阿里云SCDN 就是基于阿里云CDN 的优质加速能力,深度集成阿里云盾的专业攻防策略,可一站式提供安全和加速的整体解决方案。
全站加速(DCDN)
)是在CDN加速的基础上技术升级的云产品。智能区分访问的动态内容还是静态内容。如果是静态内容就直接用阿里云CDN加速,动态内容通过路由决策优化、协议优化等快速回源拉取内容数据。
和普通CDN加速只给静态内容加速,比如、文档相比,阿里云全站加速(DCDN)可以智能的对动态、静态内容都进行加速。请看表格的功能对比。如何搭建分布式网站服务器,比如我有3台服务器ABC,需要搭建分布式服务。也就需要建立IIS 还由DNS WIN 服务器的 还有更改主机名 很麻烦的,这个需要专业的IT人员来 *** 作的。 以下资料作为参考: DNS轮循 首先介绍一
分布式存储系统,是将数据分散存储在多台独立的设备上。传统的网络存储系统采用集中的存储服务器存放所有数据,存储服务器成为系统性能的瓶颈,也是可靠性和安全性的焦点,不能满足大规模存储应用的需要。分布式网络存储系统采用可扩展的系统结构,利用多台存储服务器分担存储负荷,利用位置服务器定位存储信息,它不但提高了系统的可靠性、可用性和存取效率,还易于扩展。
扩展资料:
分布式存储,集中管理,在这个方案中,共有三级:
1、上级监控中心:上级监控中心通常只有一个,主要由数字矩阵、认证服务器和VSTARClerk软件等。
2、本地监控中心:本地监控中心可以有多个,可依据地理位置设置,或者依据行政隶属关系设立,主要由数字矩阵、流媒体网关、iSCSI存储设备、软件等组成;音视频的数据均主要保存在本地监控中心,这就是分布式存储的概念。
3、监控前端:主要由摄像头、网络视频服务器组成,其中VE4000系列的网络视频服务器可以带硬盘,该硬盘主要是用于网络不畅时,暂时对音视频数据进行保存,或者需要在前端保存一些重要数据的情况。
-分布式存储系统
-分散存储
我们的服务器从单机发展到拥有多台机器的分布式系统,各个系统之前需要借助于网络进行通信,原有单机中相对可靠的方法调用以及进程间通信方式已经没有办法使用,同时网络环境也是不稳定的,造成了我们多个机器之间的数据同步问题,这就是典型的分布式事务问题。
在分布式事务中事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。分布式事务就是要保证不同节点之间的数据一致性。
1、2PC(二阶段提交)方案 - 强一致性
2、3PC(三阶段提交)方案
3、TCC (Try-Confirm-Cancel)事务 - 最终一致性
4、Saga事务 - 最终一致性
5、本地消息表 - 最终一致性
6、MQ事务 - 最终一致性
消息的生产方,除了维护自己的业务逻辑之外,同时需要维护一个消息表。这个消息表里面记录的就是需要同步到别的服务的信息,当然这个消息表,每个消息都有一个状态值,来标识这个消息有没有被成功处理。
发送放的业务逻辑以及消息表中数据的插入将在一个事务中完成,这样避免了业务处理成功 + 事务消息发送失败,或业务处理失败 + 事务消息发送成功,这个问题。
举个栗子:
我们假定目前有两个服务,订单服务,购物车服务,用户在购物车中对几个商品进行合并下单,之后需要情况购物车中刚刚已经下单的商品信息。
1、消息的生产方也就是订单服务,完成了自己的逻辑(对商品进行下单 *** 作)然后把这个消息通过 mq 发送到需要进行数据同步的其他服务中,也就是我们栗子中的购物车服务。
2、其他服务(购物车服务)会监听这个队列;
1、如果收到这个消息,并且数据同步执行成功了,当然这也是一个本地事务,就通过 mq 回复消息的生产方(订单服务)消息已经处理了,然后生产方就能标识本次事务已经结束。如果是一个业务上的错误,就回复消息的生产方,需要进行数据回滚了。
2、很久没收到这个消息,这种情况是不会发生的,消息的发送方会有一个定时的任务,会定时重试发送消息表中还没有处理的消息;
3、消息的生产方(订单服务)如果收到消息回执;
1、成功的话就修改本次消息已经处理完,也就是本次分布式事务的同步已经完成;
2、如果消息的结果是执行失败,同时在本地回滚本次事务,标识消息已经处理完成;
3、如果消息丢失,也就是回执消息没有收到,这种情况也不太会发生,消息的发送方(订单服务)会有一个定时的任务,定时重试发送消息表中还没有处理的消息,下游的服务需要做幂等,可能会收到多次重复的消息,如果一个回复消息生产方中的某个回执信息丢失了,后面持续收到生产方的 mq 消息,然后再次回复消息的生产方回执信息,这样总能保证发送者能成功收到回执,消息的生产方在接收回执消息的时候也要做到幂等性。
这里有两个很重要的 *** 作:
1、服务器处理消息需要是幂等的,消息的生产方和接收方都需要做到幂等性;
2、发送放需要添加一个定时器来遍历重推未处理的消息,避免消息丢失,造成的事务执行断裂。
该方案的优缺点
优点:
1、在设计层面上实现了消息数据的可靠性,不依赖消息中间件,弱化了对 mq 特性的依赖。
2、简单,易于实现。
缺点:
主要是需要和业务数据绑定到一起,耦合性比较高,使用相同的数据库,会占用业务数据库的一些资源。
下面分析下几种消息队列对事务的支持
RocketMQ 中的事务,它解决的问题是,确保执行本地事务和发消息这两个 *** 作,要么都成功,要么都失败。并且,RocketMQ 增加了一个事务反查的机制,来尽量提高事务执行的成功率和数据一致性。
主要是两个方面,正常的事务提交和事务消息补偿
正常的事务提交
1、发送消息(half消息),这个 half 消息和普通消息的区别,在事务提交 之前,对于消费者来说,这个消息是不可见的。
2、MQ SERVER写入信息,并且返回响应的结果;
3、根据MQ SERVER响应的结果,决定是否执行本地事务,如果MQ SERVER写入信息成功执行本地事务,否则不执行;
如果MQ SERVER没有收到 Commit 或者 Rollback 的消息,这种情况就需要进行补偿流程了
补偿流程
1、MQ SERVER如果没有收到来自消息发送方的 Commit 或者 Rollback 消息,就会向消息发送端也就是我们的服务器发起一次查询,查询当前消息的状态;
2、消息发送方收到对应的查询请求,查询事务的状态,然后把状态重新推送给MQ SERVER,MQ SERVER就能之后后续的流程了。
相比于本地消息表来处理分布式事务,MQ 事务是把原本应该在本地消息表中处理的逻辑放到了 MQ 中来完成。
Kafka 中的事务解决问题,确保在一个事务中发送的多条信息,要么都成功,要么都失败。也就是保证对多个分区写入 *** 作的原子性。
通过配合 Kafka 的幂等机制来实现 Kafka 的 Exactly Once,满足了读取-处理-写入这种模式的应用程序。当然 Kafka 中的事务主要也是来处理这种模式的。
什么是读取-处理-写入模式呢?
栗如:在流计算中,用 Kafka 作为数据源,并且将计算结果保存到 Kafka 这种场景下,数据从 Kafka 的某个主题中消费,在计算集群中计算,再把计算结果保存在 Kafka 的其他主题中。这个过程中,要保证每条消息只被处理一次,这样才能保证最终结果的成功。Kafka 事务的原子性就保证了,读取和写入的原子性,两者要不一起成功,要不就一起失败回滚。
这里来分析下 Kafka 的事务是如何实现的
它的实现原理和 RocketMQ 的事务是差不多的,都是基于两阶段提交来实现的,在实现上可能更麻烦
先来介绍下事务协调者,为了解决分布式事务问题,Kafka 引入了事务协调者这个角色,负责在服务端协调整个事务。这个协调者并不是一个独立的进程,而是 Broker 进程的一部分,协调者和分区一样通过选举来保证自身的可用性。
Kafka 集群中也有一个特殊的用于记录事务日志的主题,里面记录的都是事务的日志。同时会有多个协调者的存在,每个协调者负责管理和使用事务日志中的几个分区。这样能够并行的执行事务,提高性能。
下面看下具体的流程
事务的提交
1、协调者设置事务的状态为PrepareCommit,写入到事务日志中;
2、协调者在每个分区中写入事务结束的标识,然后客户端就能把之前过滤的未提交的事务消息放行给消费端进行消费了;
事务的回滚
1、协调者设置事务的状态为PrepareAbort,写入到事务日志中;
2、协调者在每个分区中写入事务回滚的标识,然后之前未提交的事务消息就能被丢弃了;
这里引用一下消息队列高手课中的
RabbitMQ 中事务解决的问题是确保生产者的消息到达MQ SERVER,这和其他 MQ 事务还是有点差别的,这里也不展开讨论了。
先来分析下一条消息在 MQ 中流转所经历的阶段。
生产阶段 :生产者产生消息,通过网络发送到 Broker 端。
存储阶段 :Broker 拿到消息,需要进行落盘,如果是集群版的 MQ 还需要同步数据到其他节点。
消费阶段 :消费者在 Broker 端拉数据,通过网络传输到达消费者端。
发生网络丢包、网络故障等这些会导致消息的丢失
在生产者发送消息之前,通过channeltxSelect开启一个事务,接着发送消息, 如果消息投递 server 失败,进行事务回滚channeltxRollback,然后重新发送, 如果 server 收到消息,就提交事务channeltxCommit
不过使用事务性能不好,这是同步 *** 作,一条消息发送之后会使发送端阻塞,以等待RabbitMQ Server的回应,之后才能继续发送下一条消息,生产者生产消息的吞吐量和性能都会大大降低。
使用确认机制,生产者将信道设置成 confirm 确认模式,一旦信道进入 confirm 模式,所有在该信道上面发布的消息都会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,RabbitMQ 就会发送一个确认(BasicAck)给生产者(包含消息的唯一 deliveryTag 和 multiple 参数),这就使得生产者知晓消息已经正确到达了目的地了。
multiple 为 true 表示的是批量的消息确认,为 true 的时候,表示小于等于返回的 deliveryTag 的消息 id 都已经确认了,为 false 表示的是消息 id 为返回的 deliveryTag 的消息,已经确认了。
确认机制有三种类型
1、同步确认
2、批量确认
3、异步确认
同步模式的效率很低,因为每一条消息度都需要等待确认好之后,才能处理下一条;
批量确认模式相比同步模式效率是很高,不过有个致命的缺陷,一旦回复确认失败,当前确认批次的消息会全部重新发送,导致消息重复发送;
异步模式就是个很好的选择了,不会有同步模式的阻塞问题,同时效率也很高,是个不错的选择。
Kafaka 中引入了一个 broker。 broker 会对生产者和消费者进行消息的确认,生产者发送消息到 broker,如果没有收到 broker 的确认就可以选择继续发送。
只要 Producer 收到了 Broker 的确认响应,就可以保证消息在生产阶段不会丢失。有些消息队列在长时间没收到发送确认响应后,会自动重试,如果重试再失败,就会以返回值或者异常的方式告知用户。
只要正确处理 Broker 的确认响应,就可以避免消息的丢失。
RocketMQ 提供了3种发送消息方式,分别是:
同步发送:Producer 向 broker 发送消息,阻塞当前线程等待 broker 响应 发送结果。
异步发送:Producer 首先构建一个向 broker 发送消息的任务,把该任务提交给线程池,等执行完该任务时,回调用户自定义的回调函数,执行处理结果。
Oneway发送:Oneway 方式只负责发送请求,不等待应答,Producer 只负责把请求发出去,而不处理响应结果。
在存储阶段正常情况下,只要 Broker 在正常运行,就不会出现丢失消息的问题,但是如果 Broker 出现了故障,比如进程死掉了或者服务器宕机了,还是可能会丢失消息的。
防止在存储阶段消息额丢失,可以做持久化,防止异常情况(重启,关闭,宕机)。。。
RabbitMQ 持久化中有三部分:
消息的持久化,在投递时指定 delivery_mode=2(1是非持久化),消息的持久化,需要配合队列的持久,只设置消息的持久化,重启之后队列消失,继而消息也会丢失。所以如果只设置消息持久化而不设置队列的持久化意义不大。
对于持久化,如果所有的消息都设置持久化,会影响写入的性能,所以可以选择对可靠性要求比较高的消息进行持久化处理。
不过消息持久化并不能百分之百避免消息的丢失
比如数据在落盘的过程中宕机了,消息还没及时同步到内存中,这也是会丢数据的,这种问题可以通过引入镜像队列来解决。
镜像队列的作用:引入镜像队列,可已将队列镜像到集群中的其他 Broker 节点之上,如果集群中的一个节点失效了,队列能够自动切换到镜像中的另一个节点上来保证服务的可用性。(更细节的这里不展开讨论了)
*** 作系统本身有一层缓存,叫做 Page Cache,当往磁盘文件写入的时候,系统会先将数据流写入缓存中。
Kafka 收到消息后也会先存储在也缓存中(Page Cache)中,之后由 *** 作系统根据自己的策略进行刷盘或者通过 fsync 命令强制刷盘。如果系统挂掉,在 PageCache 中的数据就会丢失。也就是对应的 Broker 中的数据就会丢失了。
处理思路
1、控制竞选分区 leader 的 Broker。如果一个 Broker 落后原先的 Leader 太多,那么它一旦成为新的 Leader,必然会造成消息的丢失。
2、控制消息能够被写入到多个副本中才能提交,这样避免上面的问题1。
1、将刷盘方式改成同步刷盘;
2、对于多个节点的 Broker,需要将 Broker 集群配置成:至少将消息发送到 2 个以上的节点,再给客户端回复发送确认响应。这样当某个 Broker 宕机时,其他的 Broker 可以替代宕机的 Broker,也不会发生消息丢失。
消费阶段就很简单了,如果在网络传输中丢失,这个消息之后还会持续的推送给消费者,在消费阶段我们只需要控制在业务逻辑处理完成之后再去进行消费确认就行了。
总结:对于消息的丢失,也可以借助于本地消息表的思路,消息产生的时候进行消息的落盘,长时间未处理的消息,使用定时重推到队列中。
消息在 MQ 中的传递,大致可以归类为下面三种:
1、At most once: 至多一次。消息在传递时,最多会被送达一次。是不安全的,可能会丢数据。
2、At least once: 至少一次。消息在传递时,至少会被送达一次。也就是说,不允许丢消息,但是允许有少量重复消息出现。
3、Exactly once:恰好一次。消息在传递时,只会被送达一次,不允许丢失也不允许重复,这个是最高的等级。
大部分消息队列满足的都是At least once,也就是可以允许重复的消息出现。
我们消费者需要满足幂等性,通常有下面几种处理方案
1、利用数据库的唯一性
根据业务情况,选定业务中能够判定唯一的值作为数据库的唯一键,新建一个流水表,然后执行业务 *** 作和流水表数据的插入放在同一事务中,如果流水表数据已经存在,那么就执行失败,借此保证幂等性。也可先查询流水表的数据,没有数据然后执行业务,插入流水表数据。不过需要注意,数据库读写延迟的情况。
2、数据库的更新增加前置条件
3、给消息带上唯一ID
每条消息加上唯一ID,利用方法1中通过增加流水表,借助数据库的唯一性来处理重复消息的消费。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)