转载:http://segmentfault.com/a/1190000003059871算法
这是一篇老帖子了,我是来学习的。原文在这里:http://jm-blog.aliapp.com/?p=3483。问题是图片都没有了。我费了很大功夫才把原文的图片给找回来。排版以后从新发布一遍。
淘宝的notify是一个很是有特点的消息中间件。它用创新地方式解决了分布式事务的问题,用相对较低的成本,实现了跨micro service的最终一致性。这种把最终一致性用application queue而不是database replication queue的方式来实现,把IT技术层面的跨业务的事务变成一个业务层面的单据传递的概念,很是值得推广。sql
综述
消息中间件是一种由消息传送机制或消息队列模式组成的最典型的中间件技术。经过消息中间件,应用程序或组件之间能够进行可靠的异步通信来下降系统之间的耦合度,从而提升整个系统的可扩展性和可用性。数据库
Notify是淘宝自主研发的一套消息服务引擎,是支撑双11最为核心的系统之一,在淘宝和支付宝的核心交易场景中都有大量使用。消息系统的核心做用就是三点:解耦,异步和并行。下面让我以一个实际的例子来讲明一下解耦异步和并行分别所表明的具体意义吧:编程
假设咱们有这么一个应用场景,为了完成一个用户注册淘宝的操做,可能须要将用户信息写入到用户库中,而后通知给红包中心给用户发新手红包,而后还须要通知支付宝给用户准备对应的支付宝帐号,进行合法性验证,告知sns系统给用户导入新的用户等10步操做。
那么针对这个场景,一个最简单的设计方法就是串行的执行整个流程,如图3-1所示:segmentfault
这种方式的最大问题是,随着后端流程愈来愈多,每步流程都须要额外的耗费不少时间,从而会致使用户更长的等待延迟。天然的,咱们能够采用并行的方式来完成业务,可以极大的减小延迟,如图3-2所示。后端
但并行之后又会有一个新的问题出现了,在用户注册这一步,系统并行的发起了4个请求,那么这四个请求中,若是通知SNS这一步须要的时间很长,好比须要10秒钟的话,那么就算是发新手包,准备支付宝帐号,进行合法性验证这几个步骤的速度再快,用户也仍然须要等待10秒之后才能完成用户注册过程。由于只有当全部的后续操做所有完成的时候,用户的注册过程才算真正的“完成”了。用户的信息状态才是完整的。而若是这时候发生了更严重的事故,好比发新手红包的全部服务器由于业务逻辑bug致使down机,那么由于用户的注册过程尚未彻底完成,业务流程也就是失败的了。这样明显是不符合实际的须要的,随着下游步骤的逐渐增多,那么用户等待的时间就会愈来愈长,而且更加严重的是,随着下游系统愈来愈多,整个系统出错的几率也就愈来愈大。缓存
经过业务分析咱们可以得知,用户的实际的核心流程其实只有一个,就是用户注册。然后续的准备支付宝,通知sns等操做虽然必需要完成,但倒是不须要让用户等待的。
这种模式有个专业的名词,就叫最终一致。为了达到最终一致,咱们引入了MQ系统。业务流程以下:安全
主流程如图3-3所示:服务器
图3-3-用户注册流程-引入MQ系统-主流程app
异步流程如图3-4所示:
图3-4-用户注册流程-引入MQ系统-异步流程
核心原理
Notify在设计思路上与传统的MQ有必定的不一样,他的核心设计理念是
为了消息堆积而设计系统
无单点,可自由扩展的设计
下面就请随我一块儿,进入到咱们的消息系统内部来看看他设计的核心原理
为了消息堆积而设计系统在市面上的大部分MQ产品,大部分的核心场景就是点对点的消息传输通道,而后很是激进的使用内存来提高总体的系统性能,这样作虽然标称的tps都能达到很高,但这种设计的思路是很难符合大规模分布式场景的实际须要的。
在实际的分布式场景中,这样的系统会存在着较大的应用场景瓶颈,在后端有大量消费者的前提下,消费者出现问题是个很是常见的状况,而消息系统则必须可以在后端消费不稳定的状况下,仍然可以保证用户写入的正常而且TPS不降,是个很是考验消息系统能力的实际场景。
也由于如此,在Notify的总体设计中,咱们最优先考虑的就是消息堆积问题,在目前的设计中咱们使用了持久化磁盘的方式,在每次用户发消息到Notify的时候都将消息先落盘,而后再异步的进行消息投递,而没有采用激进的使用内存的方案来加快投递速度。
这种方式,虽然系统性能在峰值时比目前市面的MQ效率要差一些,可是做为整个业务逻辑的核心单元,稳定,安全可靠是系统的核心诉求。
无单点,可自由扩展的设计
图3-5展现了组成Notify整个生态体系的有五个核心的部分。
发送消息的集群这主要是业务方的机器,这些APP的机器上是没有任何状态信息的,能够随着用户请求量的增长而随时增长或减小业务发送方的机器数量,从而扩大或缩小集群能力。
配置服务器集群(Config server)这个集群的主要目的是动态的感知应用集群,消息集群机器上线与下线的过程,并及时广播给其余集群。如当业务接受消息的机器下线时,config server会感知到机器下线,从而将该机器从目标用户组内踢出,并通知给notify server,notify server 在获取通知后,就能够将已经下线的机器从本身的投递目标列表中删除,这样就能够实现机器的自动上下线扩容了。
消息服务器(Notify Server)消息服务器,也就是真正承载消息发送与消息接收的服务器,也是一个集群,应用发送消息时能够随机选择一台机器进行消息发送,任意一台server 挂掉,系统均可以正常运行。当须要增长处理能力时,只须要简单地增长notify Server就能够了
存储(Storage)Notify的存储集群有多种不一样的实现方式,以知足不一样应用的实际存储需求。针对消息安全性要求高的应用,咱们会选择使用多份落盘的方式存储消息数据,而对于要求吞吐量而不要求消息安全的场景,咱们则可使用内存存储模型的存储。天然的,全部存储也被设计成了随机无状态写入存储模型以保障能够自由扩展。
消息接收集群业务方用于处理消息的服务器组,上下线机器时候也可以动态的由config server 感知机器上下线的时机,从而能够实现机器自动扩展。
在双11的整个准备过程当中,Notify都承载了很是巨大的压力,由于咱们的核心假定就是后端系统必定会挂,而咱们须要可以承载整个交易高峰内的全部消息都会堆积在数据库内的实际场景。
在屡次压测中,咱们的系统表现仍是很是稳定的,以60w/s的写入量堆积4.5亿消息的时候,整个系统表现很是淡定可靠。在真正的大促到来时,咱们的后端系统响应效率好于预期,因此咱们很轻松的就知足了用户全部消息投递请求,比较好的知足了用户的实际须要。
METAQ是一款彻底的队列模型消息中间件,服务器使用Java语言编写,可在多种软硬件平台上部署。客户端支持Java、C++编程语言,已于2012年3月对外开源,开源地址是:http://metaq.taobao.org/。MetaQ大约经历了下面3个阶段
在2011年1月份发布了MetaQ 1.0版本,从Apache Kafka衍生而来,在内部主要用于日志传输。
在2012年9月份发布了MetaQ 2.0版本,解决了分区数受限问题,在数据库binlog同步方面获得了普遍的应用。
在2013年7月份发布了MetaQ 3.0版本,MetaQ开始普遍应用于订单处理,cache同步、流计算、IM实时消息、binlog同步等领域。MetaQ3.0版本已经开源,参见这里
综上,MetaQ借鉴了Kafka的思想,并结合互联网应用场景对性能的要求,对数据的存储结构进行了全新设计。在功能层面,增长了更适合大型互联网特点的功能点。
MetaQ简介
图3-6-MetaQ总体结构
如图3-6所示,MetaQ对外提供的是一个队列服务,内部实现也是彻底的队列模型,这里的队列是持久化的磁盘队列,具备很是高的可靠性,而且充分利用了操做系统cache来提升性能。
是一个队列模型的消息中间件,具备高性能、高可靠、高实时、分布式特色。
Producer、Consumer、队列均可以分布式。
Producer向一些队列轮流发送消息,队列集合称为Topic,Consumer若是作广播消费,则一个consumer实例消费* * 这个Topic对应的全部队列,若是作集群消费,则多个Consumer实例平均消费这个topic对应的队列集合。
可以保证严格的消息顺序
提供丰富的消息拉取模式
高效的订阅者水平扩展能力
实时的消息订阅机制
亿级消息堆积能力
MetaQ存储结构
MetaQ的存储结构是根据阿里大规模互联网应用需求,彻底从新设计的一套存储结构,使用这套存储结构能够支持上万的队列模型,而且能够支持消息查询、分布式事务、定时队列等功能,如图3-7所示。
图3-7-MetaQ存储体系
MetaQ单机上万队列
MetaQ内部大部分功能都靠队列来驱动,那么必须支持足够多的队列,才能更好的知足业务需求,如图所示,MetaQ能够在单机支持上万队列,这里的队列所有为持久化磁盘方式,从而对IO性能提出了挑战。MetaQ是这样解决的
Message所有写入到一个独立的队列,彻底的顺序写
Message在文件的位置信息写入到另外的文件,串行方式写。
经过以上方式,既作到数据可靠,又能够支持更多的队列,如图3-8所示。
图3-8-MetaQ单机上万队列
MetaQ与Notify区别
Notify侧重于交易消息,分布式事务消息方面。
MetaQ侧重于顺序消息场景,例如binlog同步。以及主动拉消息场景,例如流计算等。
Notify 交易消息转 MetaQ 方案改进
MetaQ 交易集群主要是 Notify 交易消息的一个镜像,旧有的方案是经过 Notify-Client 订阅 Notify 交易消息,而后再转投到 MetaQ 集群,这个方案的缺点:1. 经过消息订阅的方式给 Notify 集群带来比较大的压力 2. 一旦 MetaQ 集群处理不及时会给 Notify 形成消息的堆积,从而带来连锁不良效应。新的方案则是从Notify DB直接拉取binlog到MetaQ,它带来的优点: 1. 解放 NotifyServer 集群的压力;2. 经过 binlog 批量处理能够提高系统的吞吐量。
交易集群低延迟优化
天猫直播间,旨在经过实时获取活动当天的交易数据,经过实时流计算的方式,及时、准确的展现各业务数据。它的特色就是数据全而准确、实时性要求较高。而在全链路压测过程当中发现从 Notify Mysql binlog 获取数据时,出现较大的延迟,最严重的延迟高达4h+,这显然是不合系统需求的。基于这些问题,咱们在 Notify Mysql 端作了不少的优化:
Mysql 数据库实例扩容,从而提升集群的总体吞吐量;
对 binlog 的存放位置进行优化,将数据存储以及 binlog 存储进行分离,从而发挥 DB 的最大写性能;
因为 MySQL 的 binlog 操做存在锁操做,优化了 MySQL 生成 binlog 的配置,保证了拉 binlog 无延时。
针对不一样集群运行参数调优
根据业务的特色,对不一样集群的运行参数调优,如批量拉取大小,刷盘方式,数据有效期等等;同时对io调度、虚拟内存等参数进行调优,以提供更为高效的堆积。
监控与实时告警
任何一个值得信赖的系统,最低限度是须要作到及时发现并处理异常,在第一时间排除故障发生的可能,从而提升产品的可用性。在双十一活动以前,咱们实现了由 MetaQ 系统内部,根据集群状态,各消息的业务数据指标进行监控统计并主动告警,同时还能经过 Diamond 作到动态调整,从而提升监控的及时性以及灵活性。
回顾双十一活动当日,淘宝消息写入总量112亿,消息投递总量220亿,支付宝消息写入总量24亿,消息投递总量24亿。其中实时直播间集群消息写入峰值为13.1w,消息投递峰值为27.8w。
从整体上看,咱们的前期准备仍是比较充分的,MetaQ 各集群在高峰期表现稳定,全天表现很平稳,个别订阅组对消息进行重溯,部分消息有少许的堆积,但都没有对系统形成影响,效果仍是很是好的。75%的交易在聚石塔上完成,实时直播间交易统计延迟在1s左右,加减库存作到零超卖。
目前分布式消息中间件产品已经服务于整个集团,支持了阿里集团各个公司的500多个业务应用系统。每日处理海量消息超350亿次,保证全部交易数据高可靠,高性能,分布式事务处理,是中间件团队最老牌的中间件产品之一。
资料来源:http://club.alibabatech.org/resource_detail.htm?topicId=61
业务操做和消息存储都在本地事务域进行,不存在跨资源的事务。
提交/回滚消息有可能失败,系统会处于短暂的不一致状态
Broker会主动发送Check消息,确认消息是否提交或回滚
最终一致
将分布式事务分解在两个本地事务中
客户端须要付出的代价
实现CheckMessageListener接口
原帖连接:http://jm-blog.aliapp.com/?p=3405&utm_source=tuicool
双十二大促是淘宝集市的年终促销活动,活动当天扫描首页二维码赠送一注×××的活动更是让你们“玩”了一把。面对瞬间的数倍于往常的峰值,如何让用户有一个良好的体验,如何保证系统的稳定运行,让咱们来揭秘这一切。
概括一下系统须要作到以下几点:
RT足够短
压力分布均匀
复杂逻辑分离,异步话
系统结构图
大致分为两个部分:活动系统,×××系统,他们之间经过消息驱动。
活动系统里面只更新一个×××分配的状态,数据更新成功就返回给用户,逻辑足够简单能保证RT很是短。×××系统负责真正的×××出票和更新用户状态等一些耗时操做。
用户在首页扫描二维码发起对活动系统的请求,活动系统更新×××分配状态,产生一条消息,当即返回并。×××系统收到这个消息完成后续出票等一些的业务操做。整个过程是经过MetaQ提供的消息服务驱动完成。活动的时候会有大量的请求涌进活动系统,会产生大量的消息,预估qps达到24w;而且消息不可丢失,确保用户都能领到一注×××;活动系统,×××系统业务复杂度相差较大,处理能力也相差较大,可能会出现大量的堆积;为了让用户有个较好的体验,消息的消费也须要足够的及时。综上对MetaQ有这么一些挑战:
高吞吐量
数据可靠
高效堆积
消息投递足够低延迟
下面介绍一下MetaQ如何作到这些的。
MetaQ简介
METAQ是一款彻底的队列模型消息中间件,服务器使用Java语言编写,可在多种软硬件平台上部署。客户端支持Java、C++编程语言,已于2012年3月对外开源,开源地址。MetaQ的设计目标是高吞吐量,高效堆积。彻底的队列模型还提供了顺序消息,消息回溯等一些特性。
基本概念
Topic 消息主题
Partition 分区,表明一个消费队列 (一个Topic能够划分为多个分区,分区数越多并行度越大,支持的Qps越高)
Group 消费分组,表明一个消费集群
MetaQ对外提供的是一个队列服务,内部实现也是彻底的队列模型,这里的队列是持久化的磁盘队列,具备很是高的可靠性,而且充分利用了操做系统cache来提升性能。这些特性都源于存储层的设计。
MetaQ存储结构
MetaQ的存储结构是根据阿里大规模互联网应用需求,彻底从新设计的一套存储结构,使用这套存储结构能够支持上万的队列模型,而且能够支持消息查询、分布式事务、定时队列等功能,如图3所示。
存储层能够大体分为数据文件(CommitLog)和索引文件两部分。数据文件保存了全部的消息的内容,索引文件保存了消息所在数据文件的偏移量。消息数据不区分Topic,顺序的append到CommitLog,索引文件按照Topic-Partition维度组织,不一样分区的消息append到不一样索引队列里面。
消息写入
客户端发送一条消息,数据首先会写到文件缓存中,同时派发一个写索引请求;异步的构建消息索引。
消息读取
客户端读取消息,根据索引的位置找到须要读取的消息的物理位置和消息长度,从CommitLog中读取数据,经过文件缓存来加速消息的读取。一般热数据都在缓存中,无需IO操做;非热数据,会触发缺页中断,数据从磁盘加载到文件缓存中,直接写到socket缓冲区,避免数据进入Java堆。
数据刷盘
刷盘后数据最终持久化到磁盘。刷盘方式分为两种方式:同步刷盘,数据写入缓存后当即刷盘,确保数据落盘后返回客户端,MetaQ在同步刷盘过程当中也作了必定优化避免过多的性能损失;异步刷盘,数据批量定时的刷到磁盘。
数据清理
消息数据按照文件有效期定时作清理。
数据复制
数据可靠性要求很高的应用,可经过数据复制保证数据的可靠。MetaQ提供两种数据同步的方式:同步双写,数写入到主机后会同时写到备机,主备都写成功才返回客户端成功,主备间数据无延迟,MetaQ有一套本身的主备间高效数据复制方案;异步复制,数据写到主机后返回客户端成功,主备间异步同步,主备间存在必定的延迟。
MetaQ单机上万队列
MetaQ的大部分功能都是靠队列来驱动,以文件的方式存储,经过内存映射对数据进行操做。全部的消息都是顺序的写到数据文件(CommitLog),彻底顺序的写入,避免随机IO;消息索引按照Topic和Partition的维度区分串行的写到索引文件。经过这种这种组织方式能够实现单机上万队列,如图4所示。
数据流图
消息数据首先写入到Java堆,而后在写入到文件缓存,在根据具体的刷盘策略Flush到磁盘;消费消息的时候若是是热数据则直接从系统缓存写到socket发到远端;若是非热数据则由系统产生缺页中断将数据从磁盘加载到系统缓存在写到socket,数据不进应用程序内存空间。内存的管理,页面的换入换出都是由OS来管理的。同时消息的拉取也是批量的,一次处理多条数据,尽可能减小往返的时间。
MetaQ性能依赖于系统内存分配,磁盘IO的有效利用,因此咱们也对操做系统内存分配,脏页会写策略,以及IO调度算法作了一些调优,让资源的分配耗时趋于平稳,堆积的时候保持较高的吞吐量。
负载均衡
发送端负载
默认发送端经过轮询的方式向broker写消息,如图6所示;也能够自行指定消息发到哪里。
消费端负载
默认是消费集群机器均分全部的消费队列。余下的部分由靠前的消费者消费,如图7所示。消费端负载均很也能够定制,如同机房优先等。
另推荐:http://www.infoq.com/cn/news/2014/03/interview-alibaba-wangjingyu?utm_...