Skip to main content

幂等性

David LiuAbout 3 min

幂等性

概念

用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了侧作用。举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣歌,返回结果成功,用户查询余额发现多扣钱了,流水记录也变成了两条。在以前的单应用系统中,我们只需要把数据操作放入事务中即可,发生错误立即回滚,但是再响应客户端的时候也有可能出现网络中断或者异常等等

防止消息重复消费

消费者在消费MQ中的消息时,MQ已把消息发送给消费者,消费者在给MQ返回ack时网络中断,故MQ未收到确认信息,该条消息会重新发给其他的消费者,或者在网络重连后再次发送给该消费者,但实际上该消费者已成诚功消费了该条消息,造成消费者消费了重复的消息,

MQ消费者的幂等性的解决一般使用全局ID或者写个唯一标识比如时间戳或者UUID或者订单消费者消费MQ中的消息也可利用MQ的该id来判断,或者可按自己的规则生成一个全局唯一id,每次消费消息时用该d先判断该消息是否已消费过,

消费端的幂等性保障

在海量订单生成的业务高峰期,生产端有可能就会重复发生了消息,这时候消费端就要实现幂等性,这就意味着我们的消息永远不会被消费多次,即使我们收到了一样的消息,业界主流的幂等性有两种操作:

  • 唯一ID+指纹码机制,利用数据库主键去重,
  • 利用redis的原子性去实现

解决方案

  • 唯一ID+指纹码机制

    性能瓶颈

  • Redis原子性

    最佳方法

在RabbitMQ中,幂等性是指在消息传递过程中,无论消息被传递多少次,最终的结果都是一致的。为了保证消息的幂等性,可以采用以下两种方式:

  1. 消费者端实现幂等性

在消费者端,可以通过记录已经处理过的消息ID或者其他唯一标识符,来避免重复处理同一条消息。当消费者接收到一条消息时,先检查该消息是否已经被处理过,如果已经处理过,则直接忽略该消息,否则执行相应的业务逻辑,并将该消息标记为已处理。

  1. 生产者端实现幂等性

在生产者端,可以通过为每条消息生成一个唯一的ID,并将该ID作为消息的一部分发送到RabbitMQ中。当消费者接收到一条消息时,先检查该消息的ID是否已经被处理过,如果已经处理过,则直接忽略该消息,否则执行相应的业务逻辑,并将该消息的ID标记为已处理。

需要注意的是,以上两种方式都需要保证消息的ID或者其他唯一标识符的唯一性,否则会导致消息的幂等性无法保证。此外,在实现幂等性的过程中,还需要考虑到消息重试、消息丢失等异常情况的处理,以保证系统的稳定性和可靠性。