任何人都可以使用消息队列。程序的好坏在于如何保证消息的安全。就是如何确保信息使命必须完成。例如,在电子商务系统中,用户下单后,我们通常会使用异步消息通知购物车系统清空相应的购物车商品。如果我们不能保证消息任务一定会送达,则意味着部分用户下单后购物车中还保留着原来的商品,从而造成不好的体验。所以一个可用的消息队列一定是可靠的,那么如何保证消息生产到消费的过程是可靠的。一般来说,消息队列queue中有三个重要的步骤,分别是生产-存储-消费。很多同学都不会注意到这一点,甚至很多人在调用消息队列的时候往往会忘记处理异常。一般情况下,消息的制作是可以成功的。但是在一些极端情况下,比如网络波动或者机器宕机,消息往往会入队失败,这就需要我们处理相应的异常。当消息入队失败时,重试或者直接回滚对应的事务,告诉前端处理失败。其次,是消息的存储阶段。虽然我们的消息队列经历了很多场景的考验,但是在生产环境中,应用的重启也是正常的。为了避免应用重启造成数据丢失,我们最好将数据写入磁盘,即使我们重启应用也不会造成数据丢失。其次,硬件损坏在所难免,服务器也有使用寿命,遇到意外也是有可能的。如果我们的数据只存在于一台机器上,一旦机器损坏,数据就可能丢失。因此,通常的做法是每条消息至少要在两台机器上写入成功后才返回成功。为什么要两台机器?因为从概率上来说,同一个集群的两台机器在不同机房同时遇到故障的概率几乎为零。最后,在消息消费阶段,很多同学有非常不好的编码习惯,就是不处理异常。不管代码执行的结果如何,他们都会告诉消息队列消息消费成功,这是非常糟糕的。我们遇到过这样的例子。用户每次交易,我们都会回调商家,通知商家数据有变化,我们就可以拉取数据了。这只是一个很简单的HTTPGET请求,按道理来说,是很难失败的。但是有些商家开发能力差,服务器经常宕机。正好这个商家今天下了这个订单。因为没有处理HTTP异常,判断消息消费成功,会导致商户数据错误。认为您所要做的就是重试就太天真了。在现代分布式系统中,有一种特殊情况需要程序员特别注意,那就是超时的处理。在程序异常中,我们可以认为下游系统未能处理很多异常。只是超时异常我们很难处理。判断下游系统是否处理成功。这就需要我们在消息队列的设计上,尽量保证我们的系统是幂等的,从而保证消息不会因为重复消费而引发新的问题。
