千家信息网

Java幂等性与分布式锁怎么理解

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,本篇内容主要讲解"Java幂等性与分布式锁怎么理解",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java幂等性与分布式锁怎么理解"吧!1. 什么是幂等性幂
千家信息网最后更新 2026年10月31日Java幂等性与分布式锁怎么理解

本篇内容主要讲解"Java幂等性与分布式锁怎么理解",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Java幂等性与分布式锁怎么理解"吧!

1. 什么是幂等性

幂等性就是指:一个幂等操作任其执行多次所产生的影响均与一次执行的影响相同。用数学的概念表达是这样的: f(f(x)) = f(x).就像 nx1 = n 一样, x1 就是一个幂等操作。无论是乘以多少次结果都一样。

2. 常见的幂等性问题

幂等性问题经常会是由网络问题引起的,还有重复操作引起的。

场景一:比如点赞功能,一个用户只能对同一片文章点赞一次,重复点赞提示已经点过赞了。

示例代码:

public void like(Article article,User user) {    //检查是否点过赞    if (checkIsLike(article,user)) {        //点过赞了        throw new ApiException(CodeEnums.SYSTEM_ERR);    } else {        //保存点赞        saveLike(article,user);    }}

看上去好像没有什么问题,保存点赞之前已经检查过是否点赞了,理论上同一个人不会对同一篇文章重复点赞。但实际不是这样的。因为网络请求不是排队进来的,而是一窝蜂涌进来的。

某些时候,用户网络不好,可能很短的时间内点击了多次,由于网络传输问题,这些请求可能会同时来到我们的服务器。

  • 第一个请求 checkIsLike() 返回 false , 正在执行 saveLike() 操作,还没来的及提交事务

  • 第二个请求过来了 ,checkIsLike() 返回 也是 false , 并去 执行了 saveLike() 操作

这样子,就造成了一个用户同时对一篇文章进行了多次点赞操作。

这就是典型的幂等性问题, 操作了一次和操作了两次结果不一样,因为你多点了一次赞,按照幂等性原则 不管你点击了多少次结果都一样,只点了一次赞。

很多场景都是这样造成的,比如用户重复下单,重复评论,重复提交表单等。

那怎么解决呢?假设网络的请求是排队进来的就不会出现这个问题了。

于是我们可以改成这样:

public synchronized void like(Article article,User user) {    //检查是否点过赞    if (checkIsLike(article,user)) {        //点过赞了        throw new ApiException(CodeEnums.SYSTEM_ERR);    } else {        //保存点赞        saveLike(article,user);    }}

synchronized 同步锁 这样我们的请求就会乖乖的排队进来了。

PS :这样做是效率比较低的做法,不建议这么做,只是举例子,synchronized 也不适合分布式集群场景。

场景二 : 第三方回调

我们系统经常需要和第三方系统打交道,比如微信充值,支付宝充值什么的,微信和支付宝常常会以回调你的接口通知你支付结果。为了保证你能收到回调,往往可能会回调多次。

有时候我们也为了保证数据的准确性会有个定时器去查询支付结果未知的流水,并执行响应的处理。
如果定时器的轮训和回调刚好是在同时进行,这可能又出BUG了,又进行了两次重复操作。

那么问题来了:假设我是一个充值操作, 回调回来的时候 ,会做业务处理,成功了给用户账户加钱。这是后就要保证幂等性了, 假设微信同一笔交易给你回调了两次,如果你给用户充值了两次,这显然不合理(我是老板肯定扣你工资),所以要保证 不管微信回调你多少次 ,同一笔交易你只能给用户充一次钱。这就幂等性。

解决幂等性问题方案

  • synchronized 适合单机应用,不追求性能 ,不追求并发。

  • 分布式锁 但是往往我们的应用是分布式的集群,并且很讲究性能,并发,所以我们需要用到 分布式锁 来解决这个问题。

Redis 分布式锁:

/*** setNx**  @param key*  @param value*  @return*/public Boolean setNx(String key,Object value) {    return redisTemplate.opsForValue().setIfAbsent(key,value);}/***  @param key 锁*  @param waitTime 等待时间  毫秒*  @param expireTime 超时时间  毫秒*  @return*/public Boolean lock(String key,long waitTime,long expireTime) {    String vlaue =  UUIDUtil.mongoObjectId();    Boolean flag = setNx(key,vlaue);    //尝试获取锁  成功返回    if (flag) {        redisTemplate.expire(key,expireTime,TimeUnit.MILLISECONDS);        return flag;    } else {        //失败        //现在时间        long newTime =  System.currentTimeMillis();        //等待过期时间        long loseTime = newTime + waitTime;        //不断尝试获取锁成功返回        while (System.currentTimeMillis()  < loseTime) {            Boolean testFlag = setNx(key,vlaue);            if (testFlag) {                redisTemplate.expire(key,expireTime,TimeUnit.MILLISECONDS);                return testFlag;            }            //休眠100毫秒            try {                Thread.sleep(100);            }            catch (InterruptedException e) {                e.printStackTrace();            }        }    }    return false;}/***  @param key*  @return*/public Boolean lock(String key) {    return lock(key,1000L,60  *  1000L);}/***  @param key*/public void unLock(String key) {    remove(key);}

利用Redis 分布式锁 我们的代码可以改成这样:

public void like(Article article,User user) {    String key =  "key:like"  + article.getId()  +  ":"  + user.getUserId();    //  等待锁的时间  0  ,  过期时间  一分钟防止死锁    Boolean flag = redisService.lock(key,0,60  *  1000L);    if(!flag) {        //获取锁失败  说明前面的请求已经获取了锁        throw new ApiException(CodeEnums.SYSTEM_ERR);    }    //检查是否点过赞    if (checkIsLike(article,user)) {        //点过赞了        throw new ApiException(CodeEnums.SYSTEM_ERR);    } else {        //保存点赞        saveLike(article,user);    }    //删除锁    redisService.unLock(key);}

key 的设计也很讲究:
数据不冲突的两个业务场景,key不能冲突,不同人的key也不一样,不同的文章Key也不一样。
根据场景业务设定。
一个原则: 尽可能的缩小key的范围。 这样才能增强我们的并发。
首先我们先获取锁,获取锁成功 执行完操作,保存数据 ,删除锁。获取不到锁返回失败。设置过期时间是为了防止'死锁',比如机器获取到了 锁,没有设置过期时间,但是他死机了,没有删除释放锁。

到此,相信大家对"Java幂等性与分布式锁怎么理解"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

问题 分布式 时间 用户 场景 结果 网络 成功 保证 支付 检查 业务 就是 数据 不同 代码 内容 原则 同时 定时器 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 科技互联网政务服务 互联网与科技金融数据 互联网科技公司发展 万易互联网科技有限公司 融势互联网科技 掌上梦互联网科技 中化能源互联网科技招聘 互联网科技创新服务 南通创西澳互联网科技有限公司 互联网企业科技类企业如何做账 半导体行业属于互联网高科技类吗 郑州欣桑互联网科技有限公司 宁波跨境商互联网科技有限公司 济南小医互联网科技有限公司招聘 米泉互联网科技专业怎么样 互联网科技品牌 互联网科技创新方面的资料 科技互联网企业在行动 互联网科技创业有什么好项目 六子台科技互联网展会 美国互联网保险保险科技 嘟嘟瓜互联网科技 长亮科技互联网金融 和信科技工业互联网 互联网科技与大数据专业 坤平互联网科技 群盈汇互联网科技有限公司 中科明德北京互联网科技 上海科技产业互联网平台 恒生科技互联网指数十大成分股
0