如何保证消息的幂等性
所谓的幂等性其实就是保证同一条消息不会重复或者重复消费了也不会对系统数据造成异常。
出现消息重复消费的情况
拿RabbitMQ来说的话,消费者在消费完成一条消息之后会向MQ回复一个ACK(可以配置自动ACK或者手动ACK) 来告诉MQ这条消息已经消费了。假如当消费者消费完数据后,准备回执ACK时,系统挂掉了,MQ是不知道该条消息已经被消费了。所以重启之后MQ会再次发送该条消息,导致消息被重复消费,如果此时没有做幂等性处理,可能就会导致数据错误等问题。
如何保证消息队列消费的幂等性
这一块应该还是要结合业务来选择合适的方法,有以下几个方案:
- 消费数据为了单纯的写入数据库,可以先根据主键查询数据是否已经存在,如果已经存在了就没必要插入了。或者直接插入也没问题,因为可以利用主键的唯一性来保证数据不会重复插入,重复插入只会报错,但不会出现脏数据。
- 消费数据只是为了缓存到redis当中,这种情况就是直接往redis中set value了,天然的幂等性。
- 针对复杂的业务情况,可以在生产消息的时候给每个消息加一个全局唯一ID,消费者消费消息时根据这个ID去redis当中查询之前是否消费过。如果没有消费过,就进行消费并将这个消息的ID写入到redis当中。如果已经消费过了,就无需再次消费了。
如何保证消息的可靠性
在将消息投入到MQ时,有可能会发生消息投递失败、消息丢失的问题,如果刚好丢失的是一些核心消息,例如money相关的,那就凉凉了…
出现消息丢失的情况
还是拿RabbitMQ来说…
从图中可以看到一共有以下三种可能出现消息丢失的情况:
- 生产者弄丢了消息
生产者在将数据发送到MQ的时候,可能由于网络等原因造成消息投递失败
- MQ自身弄丢了消息
未开启RabbitMQ的持久化,数据存储于内存,服务挂掉后队列数据丢失;
开启了RabbitMQ持久化,消息写入后会持久化到磁盘,但是在落盘的时候挂掉了,不过这种概率很小
- 消费者弄丢了消息
消费者刚接收到消息还没处理完成,结果消费者挂掉了…
保证消息可靠性的方法
针对以上三种情况,每种情况都有对应的处理方法:
- 生产者弄丢消息时的解决方法
方法一: