RabbitMQ消息中间件技术精讲10 高级篇三 幂等性保障不重复消费

利用幂等性保障消息不被重复消费

本文主要内容:

一:幂等性概念

什么是幂等性?

在网络超时等问题除外下,要求一次或多次请求同一个资源,对资源本身产生的影响和第一次执行的影响相同。

关于幂等性更详细的介绍,可以参见《拓展知识一:幂等性》这篇文章。

幂等性我们可以借鉴数据库的乐观锁机制来理解:

比如,我们执行一条更新库存的sql语句:

update table set count = count -1 where id = 1

流程说明:

    在高并发的情况下,比如秒杀系统,现在商品就剩下一个了。如果我们执行:update table set count = count -1 where id = 1这个sql语句的时候,高并发情况会导致库存成为负数,这种操作是有问题的。所以我们可以就是用乐观锁:

添加版本字段,通过版本号字段来处理。

在查询的时候,假设查询的版本号是1,在更新的时候拿着版本号作为更新条件即where version=1来更新。高并发时候,第一个执行完成后,version+1了。当第二条更新时候,发现已经不是1了就更新不了。关于mysql数据库乐观锁和悲观锁的详细介绍,可以参见《拓展知识二:mysql数据库中乐观锁和悲观锁》

二:消费端如何保障幂等性消费

问题:

    在海量订单产生的业务高峰期,如何避免消息被重复的消费呢?

答案:在消费端实现幂等性即可。

消息端实现幂等性,就意味着,我们的消息永远不会消费多次,即使我们发送多条一样的消息

三:业界主流的幂等性操作

唯一ID+指纹码机制

名称解释:

唯一ID:如数据库的主键id

指纹码:业务规则标识唯一的。如时间戳+银行返回的唯一码。需要注意的是,这个指纹码不一定就是我们系统生产的,可能是我们自己业务规则或者是外部返回的一些规则经过拼接后的东西。其目的:就是为了保障此次操作达到绝对唯一的。

唯一ID+指纹码机制,利用数据库主键去重。如:

    Select count(id) from table where id = 唯一ID+指纹码

好处:实现简单

坏处:高并发下有数据库希尔的性能瓶颈

解决方案:对唯一ID进行分库分表进行算法路由

利用redis原子特性实现

使用redis进行幂等需要考虑的问题

第一:我们是否需要进行数据入?如果需要入库的话,关键解决的问题是数据库和缓存如何做到原子性?

第二:如果步进行入库?那么都存储在缓存中,如何设置定时同步的策略?

这两个问题欢迎大家发表自己的见解。

在下节中,我们将学习Confirm消息确认机制。


本文来源:http://kaigejava.com/article/detail/514

凯哥个人博客:www.kaigejava.com

凯哥公众号:凯哥Java(kaigejava)

你可能感兴趣的:(RabbitMQ消息中间件技术精讲10 高级篇三 幂等性保障不重复消费)