本文为不熟悉MQ技术的同学介绍一个在生产环境中可能遇到的问题。至此,你的RabbitMQ部署是在线服务器上吧?然后订单服务和存储服务都可以基于RabbitMQ发送和接收消息。同时存储服务宕机,消息不会丢失。好了,让我们看看到目前为止的架构图。那么这个时候如果出现问题,就是订单服务把订单消息投递给了RabbitMQ,RabbitMQ暂时放在了自己的内存中,还没来得及投递到下游的存储服务,RabbitMQ突然宕机了这次。会发生什么答案其实很简单。默认情况下,根据我们当前的代码和配置,此数据将丢失。那么在这里,就牵扯到RabbitMQ的一个比较重要的概念:消息的持久化,英文就是durablemechanism。那么这里还有一个扩展的概念。如果按照我们之前的代码和配置,默认情况下,一旦RabbitMQ宕机并再次重启,我们之前创建的队列就会丢失。所以首先让队列持久化。使用以下代码,我们可以将我们的“warehouse_schedule_delivery”队列(即用于仓库调度和交付的队列)设置为持久队列。这样即使宕机后重启RabbitMQ,之前创建的队列也会恢复。您看到上面定义和创建队列的代码行了吗?核心在于第二个参数,为true。他的意思是创建的队列是持久化的,即支持持久化。RabbitMQ会将队列的相关信息持久化存储到磁盘中,这样在RabbitMQ重启后,可以恢复持久化队列。OK,现在你的队列信息可以持久化了,RabbitMQ宕机重启后会自动恢复队列。但是队列中的消息数据呢?队列中充满了过去订单服务发送的订单消息数据。如果RabbitMQ还没来得及将队列中的订单消息传递给存储服务,RabbitMQ就会因此宕机。这时候RabbitMQ重启后,他可以恢复队列的信息,但是无法恢复队列的消息数据。所以这时候还有一个很重要的点,就是当你的订单服务向RabbitMQ发送消息的时候,你需要定义这个消息也是持久的,也就是持久化。通过上述方式发送消息,可以使发送的消息持久化。一旦消息被标记为持久化,RabbitMQ将被要求将持久化消息写入磁盘。这时候如果RabbitMQ还没有把数据投递到存储服务,结果会突然崩溃。然后再次重启时,将加载磁盘上的持久消息。整个过程如下图所示:但这里需要注意的是,RabbitMQ的消息持久化并不能保证100%的消息不会丢失。因为有可能RabbitMQ已经收到了消息,但是还没来得及持久化到磁盘,它自己就宕机了,这时候消息还是会丢失。如果要100%保证写入RabbitMQ的数据一定落地到磁盘上,不会丢失,就需要依赖其他机制。
