RocketMQ
消息队列 RocketMQ 版是阿里云基于 Apache RocketMQ 构建的低延迟、高并发、高可用、高可靠的分布式消息中间件。消息队列 RocketMQ 版既可为分布式应用系统提供异步解耦和削峰填谷的能 力,同时也具备互联网应用所需的海量消息堆积、高吞吐、可靠重试等特性。
建议统一消息格式
统一消息格式,message由两部分组成
-
id:由生产者生成,每次不重复,代表一条消息。消费者可用于做幂等。 -
timestamp:消息的创建时间,消费方可根据业务需求,拒绝某个时间点前的消息。 -
traceId: 链路id,用于追溯业务链路。 -
payload:业务数据。
异步解耦
最常见的一个场景是用户注册后,需要发送注册邮件和短信通知,以告知用户注册成功。
传统实现(串行):
以上三个任务全部完成后,才返回注册结果到客户端,用户才能使用账号登录。
假设每个任务耗时分别为 50 ms,则用户需要在注册页面等待总共需要 150 ms 才能登录。
异步解耦实现:
对于用户来说,注册功能实际只需要注册系统存储用户的账户信息后,该用户便可以登录,后续的注册短信和邮件不是即时需要关注的步骤。
对于注册系统而言,发送注册成功的短信和邮件通知并不一定要绑定在一起同步完成,所以实际当数据写入注册系统后,注册系统就可以把其他的操作放入对应的消息队列 RocketMQ 版中然后马上返回用户结果,由消息队列 RocketMQ 版异步地进行这些操作。
分布式事务的数据一致性方案
1、本地消息表
本地消息表这种实现方式应该是业界使用最多的,其核心思想是将分布式事务拆分成本地事务进行处理,这种思路是来源于ebay。我们可以从下面的流程图中看出其中的一些细节:
基本思路就是:
消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。
消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。
2、事务消息处理
主要用来保证本地事务和消息发送,要么同时成功要么同时失败。
事务消息交互流程如下:
- 生产者将消息发送至MQ服务端,MQ服务端会将消息持久化至文件中;
- MQ服务端向发送方返回 Ack 确认消息已经发送成功,此时发送方开始执行本地事务逻辑;
- 发送方根据本地事务执行结果向服务端提交本地事务结果(Commit 或是 Rollback),服务端收到 Commit 状态则将事务消息标记为可投递,订阅方开始消费该消息;
消息的顺序收发
顺序消息分为两种情况:
全局顺序:对于指定的一个 Topic,所有消息将按照严格的先入先出(FIFO)的顺序,进行顺序发布和顺序消费;
分区顺序:对于指定的一个 Topic,所有消息根据 Sharding Key 进行区块分区,同一个分区内的消息将按照严格的 FIFO 的顺序,进行顺发布和顺序消费,可以保证一个消息被一个进程消费。
削峰填谷
流量削峰也是消息队列 MQ 的常用场景,一般在秒杀或团队抢购活动中使用广泛。
在秒杀或团队抢购活动中,由于用户请求量较大,导致流量暴增,秒杀的应用在处理如此大量的访问流量后,下游的通知系统无法承载海量的调用量,甚至会导致系统崩溃等问题而发生漏通知的情况。为解决这些问题,可在应用和下游通知系统之间加入MQ 。
大规模机器的缓存同步
双十一大促时,各个分会场会有玲琅满目的商品,每件商品的价格都会实时变化。使用缓存技术也无法满足对商品价格的访问需求,缓存服务器网卡满载。访问较多次商品价格查询影响会场页面的打开速度。
此时需要提供一种广播机制,一条消息本来只可以被集群的一台机器消费,如果使用消息队列的广播消费模式,那么这条消息会被所有节点消费一次,相当于把价格信息同步到需要的每台机器上,取代缓存的作用。