上一期我们谈到了消息队列的顺序消费,很多同学反馈没听懂,各种意见都有,有说例子不对的,有说我强行解释的,还有让我看源码、画图的,等等。为了回应大家,本期就给大家列举一些在日常开发中常见的消息队列顺序消费的例子,来补充上一期的内容。
先说说用户商城下单的场景。用户下单还没付款,然后不想要了,点了取消订单。在持久化到数据库的过程中,会产生两条消息,一条是下单消息,一条是取消订单消息。必须先下单然后取消订单,这是很典型的消息顺序消费场景。在分布式场景下,通常由多个消费者组成,很可能在数据同步过程中,出现先取消订单然后再下单的情况,这与我们的初衷不符。解决方案很简单,拆分多个队列,按照订单号取模或者哈希的方式分成多个队列。同一个订单号的下单和取消订单消息进入同一个队列,也就是多了一些队列。然后一个队列对应一个消费者,队列中的消息是顺序的,消费者就会先取下单消息,再取订单取消消息,这样就能保证消息的顺序消费。
再比如发送短信验证码,不管是登录模块还是重要信息的交易模块,都会用到发送验证码的功能。点一下就会在接口生成验证码,然后发送一条消息给通知中心让其发送验证码。如果通知中心因为压力过大发生消息积压,长时间没有响应,短信发送不过来,这时就会尝试再次发送,在消息队列中就会出现多条短信验证码的发送请求。为了保证校验的准确性,必须保证同一个用户、同一个场景下短信验证码的顺序性。解决方案跟订单场景类似,按照用户 ID 取模或者哈希的方式分成多个队列,同一个用户、同一个场景发送验证码进入同一个队列。然后一个队列对应一个消费者,这样也能保证消费的顺序性。
总结一下,保障消息顺序消费有两个步骤:一是需要顺序消费的相关消息进入同一个队列,为了分压可以拆分成多个队列,其实就是多了一些队列而已;二是要保证一个队列对应一个消费者。可能有同学会问,这难道不会造成吞吐量下降吗?压力怎么分摊呢?可以通过多线程加内存队列组合的方式来处理。
好了,本期的内容就是这些。如果您对本期内容有任何疑问,欢迎大家在评论区给我留言。谢谢大家!