小结:前端
一、算法
/1/退订请求入库--->消息队列异步--->调用供应商对接系统数据库
调用后端
成功--->标识数据库安全
失败--->补偿脚本--->从新调用架构
咱们引入RocketMQ将同步改成异步,当前端用户发出退订需求,退订系统接收到请求后就会记录到退订系统的数据库里面,表示这个用户正在退订,同时经过消息引擎把这条退订消息发送到和供应商对接的系统,去调用供应商的接口。异步
若是调用成功,就会把数据库进行标识,表示已经退订成功。同时,加了一个补偿的脚本,去数据库捞那些未退订成功的消息,从新退订,避免消息丢失引发的退订失败的状况。性能
二、
同一Group和同一Topic下,一个是消费Tag1的数据,另外一个是消费Tag2的数据。
正常状况下,启动应该是没问题的,可是有一天咱们发现一个应用起不来了,另一个应用,由于他只消费Tag2的数据,可是由于RocketMQ的机制会把Tag1的数据拿过来,拿过来事后会把Tag1的数据丢弃。spa
三、
对于大量老数据读取的改进方式是
- > 对于新消费组,默认从LAST_OFFSET消费而不是初始默认的0;
- > Broker中单Topic堆积超过1000万时,禁止消费,需联系管理员开启消费;.net
https://mp.weixin.qq.com/s/Uj0lirsq0zyCIb8AlEoNBg
导读:
同程艺龙的机票、火车票、汽车票、酒店相关业务已经接入了RocketMQ,用于流量高峰时候的削峰,以减小后端的压力。同时,对常规的系统进行解耦,将一些同步处理改为异步处理,天天处理的数据达1500亿条。
在近期的Apache RockeMQ Meetup上,同程艺龙机票事业部架构师查江,分享了同程艺龙的消息系统如何应对天天1500亿条的数据处理,经过此文,您将了解到:
-
同程艺龙在消息方面的使用状况;
-
消息在同程艺龙的应用场景;
-
技术上踩过哪些坑;
-
基于RocketMQ,作了哪些改进;
同程艺龙在消息方面的使用状况

虑性能,另外一个考虑安全性。 在纯数据的Broker分红不少组,每一个组里面分为Master和Slave。目前,咱们的机票、火车票、汽车票、酒店相关业务已经接入了RocketMQ,用于流量高峰时候的削峰,以减小后端的压力。同时,对常规的系统进行解耦,将一些同步处理改为异步处理,天天处理的数据达1500亿条。
选择RocketMQ的缘由是:
消息在同程艺龙的应用场景
退订系统
这个是咱们退订系统中的一个应用场景。用户点击前端的退订按钮,系统调用退订接口,再去调用供应商的退订接口,从而完成一个退订功能。

若是供应商的系统接口不可靠,就会致使用户退订失败,若是系统设置为同步操做,会致使用户须要再去点一次。因此,咱们引入RocketMQ将同步改成异步,当前端用户发出退订需求,退订系统接收到请求后就会记录到退订系统的数据库里面,表示这个用户正在退订,同时经过消息引擎把这条退订消息发送到和供应商对接的系统,去调用供应商的接口。
若是调用成功,就会把数据库进行标识,表示已经退订成功。同时,加了一个补偿的脚本,去数据库捞那些未退订成功的消息,从新退订,避免消息丢失引发的退订失败的状况。
房仓系统
第二个应用场景是咱们的房仓系统。这是一个比较常规的消息使用场景,咱们从供应商处采集一些酒店的基本信息数据和详情数据,而后接入到消息系统,由后端的分销系统、最小价系统和库存系统来进行计算。同时当供应商有变价的时候,变价事件也会经过消息系统传递给咱们的后端业务系统,来保证数据的实时性和准确性。

供应库的订阅系统
数据库的订阅系统也用到了消息的应用。通常状况下作数据库同步,都是经过binlog去读里面的数据,而后搬运到数据库。搬运过程当中咱们最关注的是数据的顺序性,所以在数据库row模式的基础上,新增了一个功能,以确保每个Queue里面的顺序是惟一的。

咱们踩过哪些坑
供应商系统的场景

上图中,一个MQ对应有两个消费者,他们是在同一个Group1中,起初你们都只有Topic1,这时候是正常消费的。但若是在第一个消费者里面加入一个Topic2,这时候是没法消费或消费不正常了。这是RocketMQ自己的机制引发的问题,须要在第二个消费者里面加入Topic2才能正常消费。
支付交易系统的场景

另一个是支付交易系统,这个场景下也是有两个应用,他们都是在同一Group和同一Topic下,一个是消费Tag1的数据,另外一个是消费Tag2的数据。正常状况下,启动应该是没问题的,可是有一天咱们发现一个应用起不来了,另一个应用,由于他只消费Tag2的数据,可是由于RocketMQ的机制会把Tag1的数据拿过来,拿过来事后会把Tag1的数据丢弃。这会致使用户在支付过程当中出现支付失败的状况。
对此,咱们把Tag2放到Group2里面,两个Group就不会消费相同的消息了。我的建议RocketMQ可以实现一个机制,即只接受本身的Tag消息,非相关的Tag不去接收。
大量老数据读取的场景

在火车票消费的场景中,咱们发现有200亿条老数据没有被消费。当咱们消费启动的时候,RocketMQ会默认从第0个数据开始读,这时候磁盘IO飙升到100%,从而影响到其余消费端数据的读取,但这些老数据被加载后后,并无实际做用。所以,对于大量老数据读取的改进方式是:
- > 对于新消费组,默认从LAST_OFFSET消费;
- > Broker中单Topic堆积超过1000万时,禁止消费,需联系管理员开启消费;
- > 监控要到位,磁盘IO飙升时,能马上联系到消费方处理。
服务端的场景
CentOS 6.6中 Futex Kernel bug, 致使Name Server, Broker进程常常挂起,没法正常工做;
- > 升级到6.7
服务端2个线程会建立相同CommitLog放入List,致使计算消息offset错误,解析消息失败,没法消费,重启无法解决问题。
- > 线程安全问题,改成单线程
Pull模式下重置消费进度,致使服务端填充大量数据到Map中,broker cpu使用率飙升100%。
- > Map局部变量场景用不到,删除
Master建议客户端到Slave消费时,若数据还没同步到Slave, 会重置pullOffset, 致使大量重复消费。
- > 不重置offset
同步没有MagicCode,安全组扫描同步端口时,Master解析错误,致使一些问题。
- > 同步时添加magicCode校验
基于RocketMQ,咱们作了哪些改进
新增客户端
新增.net客户端,基于Java源代码原生开发;
新增HTTP客户端,实现部分功能,并经过Netty Server链接RocketMQ;

新增消息限流功能
若是客户端代码写错产生死循环,就会产生大量的重复数据,这时候会把生产线程打满,致使队列溢出,严重影响咱们MQ集群的稳定性,从而影响其余业务。

上图是限流的模型图,咱们把限流功能加在Topic以前。经过限流功能能够设置rate limit和size limit等。其中rate limit是经过令牌桶算法来实现的,即每秒往桶里放多少个令牌,每秒就消费多少速度,或者是往Topic里写多少数据。以上的两个配置是支持动态修改的。
后台监控
咱们还作了一个监控后台,用于监控消息的全链路过程,包括:
其余功能
以上即是同程艺龙在消息系统建设方面的实践。