Mysql实现幂等_MQ如何方式消息重复消费--幂等性

一、何为幂等性?

其任意多次执行所产生的影响均与一次执行的影响相同

从对系统的影响结果来说:At least once + 幂等消费 = Exactly once。

那么如何实现幂等操作呢?最好的方式就是,从业务逻辑设计上入手,将消费的业务逻辑设

计成具备幂等性的操作。但是,不是所有的业务都能设计成天然幂等的,这里就需要一些方

如果一个函数 f(x) 满足:f(f(x)) = f(x),则函数 f(x) 满足幂等性。

法和技巧来实现幂等。

二、常见幂等性实现实现方式

1.利用数据库的唯一约束实现幂等

发起请求前,预先生成id

正常执行业务逻辑,如果已经消费过,报违反唯一性约束。未消费过,正常执行成功。

2.为更新的数据设置前置条件

(1)业务性条件

给数据变更设置一个前置条件,如果满足条件就更新数据,否则拒绝更新数据,在更新数据的时候,同时变更前置条件中需要判断的数据。这样,重复执行这个操作时,由于第一次更新数据的时候已经变更了前置条件中需要判断的数据,不满足前置条件,则不会重复执行更新数据操作。

比如,刚刚我们说过,“将账户 X 的余额增加 100 元”这个操作并不满足幂等性,我们可

以把这个操作加上一个前置条件,变为:“如果账户 X 当前的余额为 500 元,将余额加

100 元”,这个操作就具备了幂等性。对应到消息队列中的使用时,可以在发消息时在消

息体中带上当前的余额,在消费的时候进行判断数据库中,当前余额是否与消息中的余额相

等,只有相等才执行变更操作。

基于这个思路,不光是可以使用关系型数据库,只要是支持类似“INSERT IF NOT

EXIST”语义的存储类系统都可以用于实现幂等,比如,你可以用 Redis 的 SETNX 命令来

替代数据库中的唯一约束,来实现幂等消费。

(2)类似数据库乐观锁--增加一个version字段

借鉴数据库的乐观锁机制,如:

update t_goods set count = count -1 , version = version + 1 where good_id=2 and version = 1

根据version版本,也就是在操作库存前先获取当前商品的version版本号,然后操作的时候带上此version号。我们梳理下,我们第一次操作库存时,得到version为1,调用库存服务version变成了2;但返回给订单服务出现了问题,订单服务又一次发起调用库存服务,当订单服务传如的version还是1,再执行上面的sql语句时,就不会执行;因为version已经变为2了,where条件就不成立。这样就保证了不管调用几次,只会真正的处理一次。

3.记录并检查操作

如果上面提到的两种实现幂等方法都不能适用于你的场景,我们还有一种通用性最强,适用

范围最广的实现幂等性方法:记录并检查操作,也称为“Token 机制或者 GUID(全局唯

一 ID)机制”,实现的思路特别简单:在执行数据更新操作之前,先检查一下是否执行过

这个更新操作。

具体的实现方法是,在发送消息时,给每条消息指定一个全局唯一的 ID,消费时,先根据

这个 ID 检查这条消息是否有被消费过,如果没有消费过,才更新数据,然后将消费状态置

为已消费。

原理和实现是不是很简单?其实一点儿都不简单,在分布式系统中,这个方法其实是非常难

实现的。首先,给每个消息指定一个全局唯一的 ID 就是一件不那么简单的事儿,方法有很

多,但都不太好同时满足简单、高可用和高性能,或多或少都要有些牺牲。更加麻烦的是,

在“检查消费状态,然后更新数据并且设置消费状态”中,三个操作必须作为一组操作保证

原子性,才能真正实现幂等,否则就会出现 Bug。

比如说,对于同一条消息:“全局 ID 为 8,操作为:给 ID 为 666 账户增加 100 元”,有

可能出现这样的情况:

这样就会导致账户被错误地增加了两次 100 元,这是一个在分布式系统中非常容易犯的错

误,一定要引以为戒。

t0 时刻:Consumer A 收到条消息,检查消息执行状态,发现消息未处理过,开始执

行“账户增加 100 元”;

t1 时刻:Consumer B 收到条消息,检查消息执行状态,发现消息未处理过,因为这个

时刻,Consumer A 还未来得及更新消息执行状态。

对于这个问题,当然我们可以用事务来实现,也可以用锁来实现,但是在分布式系统中,无

论是分布式事务还是分布式锁都是比较难解决问题。

参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/487952.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL实践篇(一):使用WebSQL在H5中存储一个本地数据库

文章目录 简介本地存储都有哪些?如何使用WebSQL打开数据库事务操作SQL执行 在浏览器端做一个英雄的查询页面如何删除本地存储参考文献 简介 WebSQL是一种操作本地数据库的网页API接口,通过它,我们可以操作客户端的本地存储。 WebSQL曾经是H…

JavaScript之正方教务系统自动化教评[插件-转载]

【声明】本插件系学院学长原创,非博主所创,发布此处,仅供学习和效仿。 /*** name:正方教务系统自动化教评-插件* * author:chenzhongshu* date:2017-07-04* notice:原生js;无需依赖项**/(function() {var courseCode;var timer;var autoFill …

预计2024年之前载人登月!NASA授予马斯克贝索斯公司大单

来源:小小据外媒报道,当地时间周四,美国宇航局(NASA)宣布选中埃隆马斯克(Elon Musk)旗下美国太空探索技术公司SpaceX、杰夫贝索斯(Jeff Bezos)的蓝色起源公司(Blue Origin)和Dynetics为其设计和建造月球着陆系统&#…

java 遗传算法_[原]遗传算法Java实现源代码

【Title】[原]遗传算法Java实现源代码【Date】2013-04-07【Abstract】以前学习遗传算法时,用Java实现的遗传算法程序,现整理分享出来。【Keywords】wintys、遗传、算法、algorithm、种群、基因、个体、进化、染色体、适应度、Rosenbrock【Environment】W…

防止表单按钮多次提交

1. <form namefm method"POST" action"/"><p>按钮变灰</p>name: <input type"text" name"name"/><input type"button" value"提交" οnclick"javascript:{this.disabledtrue;doc…

理解进化的五座“桥”

来源&#xff1a;原理古往今来&#xff0c;达尔文是不是最具革命性的科学家之一&#xff1f;如果革命指的是把一个已经公认的学说颠倒过来&#xff0c;那挑战者还有很多&#xff0c;至少包括牛顿、爱因斯坦和量子力学的奠基者。这些物理学家超群绝伦的智慧能量&#xff0c;可能…

ACM训练计划建议(转)

ACM训练计划建议 From&#xff1a;freecode# Date&#xff1a;2015/5/20 前言&#xff1a; 老师要我们整理一份训练计划给下一届的学弟学妹们&#xff0c;整理出来了&#xff0c;费了不少笔墨&#xff0c;就也将它放到博客园上供大家参考。 菜鸟之作&#xff0c;大牛勿喷&…

java下载文件夹_java如何通过共享目录下载文件夹(有子文件夹)到本地目录?...

有没有大神会操作的&#xff1f;下面的代码只能下载文件夹下只是文件的&#xff0c;不能下载文件夹下包含子文件夹的文件public static void getShareFile(){System.out.println("开始");NtlmPasswordAuthentication auth new NtlmPasswordAuthentication("192…

【AI】【机器人】AI与机器人的42个终极问题与解答

来源&#xff1a;产业智能官 未来智能实验室的主要工作包括&#xff1a;建立AI智能系统智商评测体系&#xff0c;开展世界人工智能智商评测&#xff1b;开展互联网&#xff08;城市&#xff09;云脑研究计划&#xff0c;构建互联网&#xff08;城市&#xff09;云脑技术和企业图…

With you With me

With you With me 回来了&#xff0c;一起从零开始... 据说每一个敢说从零开始的都特么是个大牛&#xff08;for example hiphop-Man欧阳靖&#xff09;... 这些年的时间多有自己问自己&#xff0c;你特么到底在迷茫什么&#xff0c;想不通就去撞墙啊&#xff01;&#xff01;…

java集合转字符串,Java集合将字符串转换为字符列表

I would like to convert the string containing abc to a list of characters and a hashset of characters. How can I do that in Java ?List charList new ArrayList("abc".toCharArray());解决方案You will have to either use a loop, or create a collectio…

Linux服务器iops性能测试-fio

FIO是测试IOPS的非常好的工具&#xff0c;用来对硬件进行压力测试和验证&#xff0c;支持13种不同的I/O引擎&#xff0c;包括:sync,mmap, libaio, posixaio, SG v3, splice, null, network, syslet,guasi, solarisaio 等等。 fio 官网地址&#xff1a;http://freecode.com/proj…

志澄观察:卫星互联网——太空经济新动力

图1 卫星互联网的组成来源&#xff1a;远望智库 引 言2020年04月20日国家发改委首次明确&#xff0c;将卫星互联网列入我国新型基础设施的范围&#xff0c;这项重大的战略决策&#xff0c;大大鼓舞了我国商业航天行业的信心。另一方面&#xff0c;2020年3月27日,在发展低…

java中位数_java 计算中位数方法

最近工作需要 要求把python的代码写成java版本&#xff0c;python中有一个np.median()求中位数的方法&#xff0c;java决定手写一个先说说什么是中位数&#xff1a;中位数就是中间的那个数&#xff0c;如果一个集合是奇数个&#xff0c;那么中位数就是按大小排列后&#xff0c;…

Unity 找到隐藏的UGUI

问题描述&#xff1a;在项目中需要在一开始将一个UGUI隐藏&#xff0c;之后在特定的时候再显示。 本来想的办法是在需要显示的时候调用GameObject.Find()找到这个UI并设置active&#xff0c; 但发现找出来的为null&#xff0c;经查阅资料发现GameObject.Find()只能find没有被隐…

一文读懂电磁学发展史[图文版]

来源&#xff1a;电子万花筒电磁学或称电动力学或经典电动力学。之所以称为经典&#xff0c;是因为它不包括现代的量子电动力学的内容。电动力学这样一个术语使用并不是非常严格&#xff0c;有时它也用来指电磁学中去除了静电学、静磁学后剩下的部分&#xff0c;是指电磁学与力…

java判断优先级代码_java运算符的优先级

下图是每种运算符的优先级&#xff0c;按照运算先后顺序排序(优先级相同的情况下&#xff0c;按照从左到右的顺序依次运算)优先级描述运算符1括号()、[]2正负号、-3自增自减&#xff0c;非、--、!4乘除&#xff0c;取余*、/、%5加减、-6移位运算<>、>>>7大小关系…

python语言学习笔记整理

什么是程序? 程序等于数据结构加算法&#xff0c;那么数据结构是一个静态的东西&#xff0c;算法是一个动态的东西&#xff0c;我们用一个新的语言编写这个程序&#xff0c;我们要考虑到语言也主要由数据结构和算法相关的东西&#xff0c;或静态或动态的东西来构成&#xff0c…

人机智能既不是人类智能,也不是人工智能

来源&#xff1a;人机与认知实验室从前&#xff0c;一个教授&#xff0c;去一个穷乡僻壤里头坐船过江&#xff0c;就问船上的船工&#xff1a;你学点数学没有&#xff1f;没有。你学点物理没有&#xff1f;没有。那懂不懂计算机啊&#xff1f;不懂。教授感叹这三样都不会&#…

使用HDFS客户端java api读取hadoop集群上的信息

本文介绍使用hdfs java api的配置方法。 1、先解决依赖&#xff0c;pom <dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-client</artifactId><version>2.7.2</version><scope>provided</scope>&l…