千家信息网

Redis Template实现分布式锁

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,今天就跟大家聊聊有关Redis Template实现分布式锁,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。可靠性首先,为了确保分布式锁可用,我
千家信息网最后更新 2026年11月01日Redis Template实现分布式锁

今天就跟大家聊聊有关Redis Template实现分布式锁,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

可靠性

首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件:
1.互斥性。在任意时刻,只有一个客户端能持有锁。
2.不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。
3.具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。
4.解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。

使用Redis的SETNX命令获取分布式锁的步骤:

•C1和C2线程同时检查时间戳获取锁,执行SETNX命令并都返回0,此时锁仍被C3持有,并且C3已经崩溃
•C1 DEL锁
•C1 使用SETNX命令获取锁,并且成功
•C2 DEL锁
•C2 使用SETNX命令获取锁,并且成功
•ERROR : 由于竞态条件,C1和C2都获取到了锁

幸运的是,以下面的步骤完全可以避免这种情况发生,看看C4线程如何操作

•C4使用SETNX命令获取锁
•C3已经崩溃但是仍然持有锁,所以Redis返回0给C4
•C4使用GET命令获取锁并检查锁是否已经过期,如果没有过期,则继续等待一段时间并重新重试
•如果锁已经过期,C4尝试 GETSET lock.foo
•利用GETSET语法,C4可以检查旧时间是否仍然是过期时间,如果是,则获取锁
•如果另一个客户端C5率先获取到锁,C4执行GETSET命令后将返回非过期时间,然后C4继续从头开始重新尝试获取锁。此操作C4将延长一点C5获取到的锁的过期时间,不过这不是什么大问题。

接下来我们用代码的形式展现:

package com.shuige.components.cache.redis;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.ValueOperations;import org.springframework.stereotype.Component;import java.util.Objects;import java.util.concurrent.TimeUnit;/** * Description: 通用Redis帮助类 * User: zhouzhou * Date: 2018-09-05 * Time: 15:39 */@Componentpublic class CommonRedisHelper {  public static final String LOCK_PREFIX = "redis_lock";  public static final int LOCK_EXPIRE = 300; // ms  @Autowired  RedisTemplate redisTemplate;  /**   * 最终加强分布式锁   *   * @param key key值   * @return 是否获取到   */  public boolean lock(String key){    String lock = LOCK_PREFIX + key;    // 利用lambda表达式    return (Boolean) redisTemplate.execute((RedisCallback) connection -> {      long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1;      Boolean acquire = connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes());      if (acquire) {        return true;      } else {        byte[] value = connection.get(lock.getBytes());        if (Objects.nonNull(value) && value.length > 0) {          long expireTime = Long.parseLong(new String(value));          if (expireTime < System.currentTimeMillis()) {            // 如果锁已经过期            byte[] oldValue = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());            // 防止死锁            return Long.parseLong(new String(oldValue)) < System.currentTimeMillis();          }        }      }      return false;    });  }  /**   * 删除锁   *   * @param key   */  public void delete(String key) {    redisTemplate.delete(key);  }}

如何使用呢,导入工具类后:

boolean lock = redisHelper.lock(key);    if (lock) {      // 执行逻辑操作      redisHelper.delete(key);    } else {      // 设置失败次数计数器, 当到达5次时, 返回失败      int failCount = 1;      while(failCount <= 5){        // 等待100ms重试        try {          Thread.sleep(100l);        } catch (InterruptedException e) {          e.printStackTrace();        }        if (redisHelper.lock(key)){          // 执行逻辑操作          redisHelper.delete(key);        }else{          failCount ++;        }      }      throw new RuntimeException("现在创建的人太多了, 请稍等再试");    }

看完上述内容,你们对Redis Template实现分布式锁有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。

命令 客户 客户端 时间 分布式 内容 检查 成功 同时 条件 步骤 线程 逻辑 死锁 和解 尝试 主动 幸运 解铃还须系铃人 接下来 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 耶加雪菲 华服互联网科技靠谱吗 广东猪兼强互联网科技有限公司 互联网的科技 互联网科技财经 易互联网科技有限公司 奇酷互联网络科技 世界互联网领先科技成果 互联网和高科技公司 云创客互联网科技公司 西藏七维空间互联网科技有限公司 互联网科技博主是什么意思 互联网科技革命什么开始 移动互联网科技公司 洛阳昕诺飞互联网科技有限公司 高科技互联网发展前景如何 江苏互联网智能科技产品出厂价 西安左小互联网科技有限公司 平安好医生打造互联网科技医疗 现代科技的标志之一的互联网 互联网科技有限公司 互联网巨头科技公司 互联网科技网站 互联网科技公司招聘 互联网科技中介 互联网时代科技改变生活 青岛科技大学互联网大赛研究生 互联网科技大奖都有哪些公司 容联科技互联网电商 知域互联网科技有限公司官网
0