1. 什么是幂等性
- 1.用户对于
同一操作
发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。 - 2.举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额发现多扣钱了,
流水记录也变成了两条
。在以前的单应用系统
中,我们只需要把数据操作放入事务中即可,发生错误立即回滚
,但是再响应客户端的时候也有可能出现网络中断或者异常等等;
2. 消息重复消费问题:
2.1.什么是消息的重复消费:
- 消费者在消费 MQ 中的消息时,M
Q 已把消息发送给消费者
,消费者在给 MQ返回 ack 时网络中断
,故 MQ 未收到确认信息,该条消息会重新发给其他的消费者,或者在网络重连后再次发送给该消费者,但实际上该消费者已成功消费了该条消息,造成消费者消费了重复的消息
。
2.2. 解决思路
MQ 消费者的幂等性
的解决一般使用全局 ID 或者写个唯一标识比如时间戳 或者 UUID 或者订单消费者消费 MQ 中的消息也可利用 MQ 的该 id 来判断
,或者可按自己的规则生成一个全局唯一 id
,每次消费消息时用该 id 先判断该消息是否已消费过
a. 消费端的幂等性保障
- 1.在海量订单生成的
业务高峰期
,生产端有可能就会重复发生了消息
,这时候消费端就要实现幂等性,这就意味着我们的消息永远不会被消费多次,即使我们收到了一样的消息 - 2.业界主流的幂等性有两种操作:
唯一ID+指纹码机制
,利用数据库主键去重,利用 redis 的原子性去实现
b. 唯一 ID+指纹码机制
- 指纹码:我们的
一些规则或者时间戳加别的服务给到的唯一信息码
,它并不一定是我们系统生成的,基本都是由我们的业务规则拼接而来
,但是一定要保证唯一性
,然后就利用查询语句进行判断这个 id 是否存在数据库中,- 优势就是实现简单就一个拼接,然后查询判断是否重复;
- 劣势就是在高并发时,如果是单个数据库就会有写入性能瓶颈,
当然也可以采用分库分表提升性能,但也不是我们最推荐的方式
。
c. Redis 原子性
- 1.利用 redis 执行
setnx 命令
,天然具有幂等性。从而实现不重复消费