您现在的位置: 首页 > 网站导航收录 > 百科知识百科知识
JAVA面试如何保证消息不被重复消费?如何保证消息消费的幂等性?
消息,你的,问题JAVA面试如何保证消息不被重复消费?如何保证消息消费的幂等性?
发布时间:2019-02-08加入收藏来源:互联网点击:
JAVA面试如何保证消息不被重复消费?如何保证消息消费的幂等性?
回答于 2019-09-11 08:43:50
回答于 2019-09-11 08:43:50
这要从提安全性,同步设置,标注同步,注销同步设置,这是软件没置问题。如果做到标记与消费信息实现同步,就不会出现重复的问题了。
回答于 2019-09-11 08:43:50
这个问题提的好,我感觉都快崩溃了。原因很简单,我不懂,从中实在找不出乐趣来。
回答于 2019-09-11 08:43:50
如何保证不重复消费?
不同的消息系统会有不同的方案。比如Kafka。Kafka的每条消息都有一个offset。如果你消费Kafka的消息之后保存一下自己消费成功的offset,那么下次消费的时候从上次消费的offset开始就可以避免重复。我有个动画视频讲解了这个原理,欢迎观看。
如何保证幂等?
当重复消费同一条消息的时候,如果不做幂等处理,就会产生重复的结果。可以这么处理:
存在性检查,可以检查这条消息是否被消费过;可以通过记录消费过的offset,来去重。
也可以检查这条消息产生的结果是否已经存在了;如果消费的结果的key是由消息里面的一些信息生成出来的唯一值,那么可以利用这个key来去重。
回答于 2019-09-11 08:43:50
今天,让我们一起看看保证 MQ 的幂等性有哪些方案。
01. 幂等性的概念
先说说什么是幂等性。
当用户对同一操作请求了一次或者多次(消息发送或接收了多次),最终的结果是一致的,并不会因为多次请求产生副作用;比如同一个订单支付了两次,最后应该只扣客户一次钱。
查询和删除:查询具有天然的幂等性,在数据不变的前提下,相同查询条件查询一次和查询多次的结果都是一样的;删除也一样,相同的条件删除一次和删除多次,可能删除的数据量不一样,但是数据库中的数据不会因为执行了多次删除而不同。
新增和修改:如果不做幂等性处理,可能就会产生问题;执行多次新增操作,可能会导致一模一样的数据产生了多条(主键自动生成);修改操作,如果只是把某些字段更新成固定的值,不会有幂等性问题,但是如果新值要在旧值上做处理做计算,如增加多少、减少多少,那么多次执行的结果就会有差异。
02. MQ 消息出现非幂等的情况
1. 生产者发送消息给 MQ,为了保证消息可达,通常会使用超时重传机制,但是如果生产者的消息已经发出去,但是由于网络原因未收到确认信息,那么可能会进行重发,最终造成了消息的重复发送。
2. 消费者消费的过程也类似,消费者接受到 MQ 的消息,但是 MQ 未收到确认信息,那么该条消息可能会重新发送给其他消费者,或者网络恢复再次发送给消费者,最终造成重复消费。
03. 解决方法
1. 唯一索引
使用唯一索引,可以有效的防止新增脏数据:当表中存在唯一索引的时候,并发新增相同数据的时候就会报错,不过这在单库单表的时候才有效,如果项目数据量很大,采用了分库分表的策略,就不能再通过数据库的唯一性索引来解决幂等性的问题了。
2. 全局唯一 ID
每条消息,都携带一个全局的唯一 ID,消费者接收到消息,在执行前判断这个 ID 是否已经在本地存在,如果不存在,则执行交易后记录 ID(存到数据库或Redis中,表示该交易已经执行);如果已经存在,表示消息已经消费掉了,不能再次执行。
许多分布式架构中,生成全局唯一 ID 都会被作为一个基础的微服务,当然这个服务的可靠性要求极高,或者可以使用全局唯一 ID 算法,由每个应用自己生成。不过总的来说,引入全局唯一 ID 这个方案,实现起来还是非常繁琐的。
3. 业务状态
保证消息的幂等性,也可以结合业务流程考虑,比如很多业务流程每一步都是有状态的,比如网上购物可能会有:订单创建、付款、发货,那么付款之前保单状态为“待付款”,付款之后可以将保单的状态修改为“待发货”;那么如果发起重复扣款的话,第二次扣款的时候保单状态已经变化了,就会扣款失败。
4. 去重表
如果业务中有唯一性的标识时,可以使用去重表,把这个唯一性的表示保存到去重表中,如果重复插入,那么会被校验住。
比如上面的场景,一个订单只会付款一次,那么在付款的时候,把订单号作为唯一性的标识,保存到去重表中,可以保证付款操作只会发生一次;这个方法也用到了唯一 ID,不过和全局唯一 ID 不同,这个唯一 ID 是针对具体业务的。
我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注。
回答于 2019-09-11 08:43:50
下一篇:返回列表
相关链接 |
||
网友回复(共有 0 条回复) |