基础篇相当不错,只用 8 篇文章就把消息队列的特性勾勒了出来,让人具备了基本的选择和决策能力。进阶篇侧重讲解消息系统的实现,感兴趣的可以深入阅读。
试读链接:任意四章试读入口
新人优惠:极客时间新注册38元代金券
方案1: 网关接收到请求后,生成消息,后端异步处理完成后响应。这种方案会导致响应延迟,异步处理链条被拉长(从网关后就开始异步):
方案2:网关收到请求后,先去获取令牌,获取到令牌后在进行业务处理,未获取到令牌返回秒杀失败。这种方案更好,更早拦截了不需要处理的请求,异步流程缩短,系统实现难度降低:
RabbitMQ 使用队列模型:
RocketMQ 使用使用发布-订阅模型 :
Kafka 和 RocketMQ 类似,只是把主题中的队列称为分区(Partition)。
事务消息用于解决「消息队列与其它系统间的数据一致性问题」,譬如生成新订单时有两步操作:1. 写入订单数据库 2. 写入消息队列。理想情况是这两步操作同时成功/失败。 可以出现不一致的情况是:
RocketMQ 和 Kafka 提供了事务消息功能:
rocketmq 的事务反查机制:
只看消息队列的状态,事务消息是一个完成事务,消息要么发出,要么未发出。但是如果和数据库和消息队列放到一起看待,这不是一个真正意义的事务,譬如消息未发出时,数据库中的记录已经可见,如果还有其它失败导致消息不能发出,数据库中的记录不会自动删除。
跨多个系统的事务很难实现。
MQTT 给出了三种消息传递质量标准;
RocketMQ、Kafka、RabbitMQ 实现的都是 At Least Once,消费者需要自己处理消息重复的问题。
对于重复消息,最好的处理方式是实现操作幂等,即同一个消息处理重复处理多次结果不变。为消息分配全局唯一ID,然后通过记录消息ID的方式去重,这种方式不可取,因为至少需要引入两个新的系统,多个系统之间的需要协调处理的情况很多,譬如什么时候记录已经消费的消息的ID。
消息保序:消息的消费顺序和生成顺序严格一致。
RocketMQ 和 Kafka 主题 topic 中的消息是不包序的,除非 topic 中只有一个队列。
在生成消息的时候,可以按照一定策略,把符合条件的消息写入同一个队列,实现局部保序。譬如按照用户ID哈希,把同一个用户的消息发送到一个队列上,队列的上的消费是保序的,所以这个用户的消息处理实现了保序。