redis_点评(14.优惠券-java调用lua脚本改造分布式锁)
2026/6/12 17:11:54 网站建设 项目流程

这次改造的核心目标是:把「解锁时的非原子操作」改成「原子操作」,彻底解决分布式锁的「判断 + 删除」时序问题

一、先回顾:旧版解锁的致命缺陷

旧版解锁逻辑:

public void unlock() { // 1. 获取当前线程标识 String threadId = ID_PREFIX + Thread.currentThread().getId(); // 2. 从Redis获取锁标识(get操作) String id = stringRedisTemplate.opsForValue().get(KEY_PREFIX + name); // 3. 判断标识是否一致 if (threadId.equals(id)) { // 4. 删除锁(delete操作) stringRedisTemplate.delete(KEY_PREFIX + name); } }

问题出在:getdelete是两次独立的 Redis 命令,中间存在时间窗口

二、用 Lua 脚本实现原子解锁

Lua 脚本的特性:Redis 会将整个脚本作为一个原子操作执行,中间不会被其他命令打断。

  1. 新增 Lua 脚本配置

// 定义解锁脚本 private static final DefaultRedisScript<Long> UNLOCK_SCRIPT; static { UNLOCK_SCRIPT = new DefaultRedisScript<>(); // 加载resources下的unlock.lua文件 UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua")); // 指定脚本返回值类型 UNLOCK_SCRIPT.setResultType(Long.class); }
  • DefaultRedisScript:Spring Data Redis 提供的脚本执行器

  • static静态块:类加载时就加载脚本,避免每次解锁都重新读取文件

  • unlock.lua:存储解锁逻辑的 Lua 脚本文件

  1. 替换 Java 解锁逻辑为 Lua 脚本调用

@Override public void unlock() { // 调用Lua脚本执行解锁 stringRedisTemplate.execute( UNLOCK_SCRIPT, // 脚本对象 Collections.singletonList(KEY_PREFIX + name), // KEYS参数:锁的key ID_PREFIX + Thread.currentThread().getId() // ARGV参数:当前线程标识 ); }
1、stringRedisTemplate.execute(...)
  • 作用:Spring 提供的执行 Redis Lua 脚本的核心方法

  • 特点:Redis 会把整个脚本当作一条原子命令执行,不会被其他命令打断

2、UNLOCK_SCRIPT
  • 提前加载好的Lua 解锁脚本

3.Collections.singletonList(KEY_PREFIX + name)
  • 传给 Lua 的KEYS 数组参数

  • 内容:lock:order:userId(锁的 Redis Key)

  • 必须用 List 集合,是 Redis 脚本的参数规范

4.ID_PREFIX + Thread.currentThread().getId()
  • 传给 Lua 的ARGV 参数

  • 内容:当前线程的唯一标识(UUID + 线程 ID)

  • 用于 Lua 脚本判断:这把锁是不是当前线程加的

三、unlock.lua脚本内容

-- 比较线程标示与锁中的标示是否一致 if (redis.call('get', KEYS[1]) == ARGV[1]) then -- 释放锁:标识一致,删除锁 return redis.call('del', KEYS[1]) end -- 标识不一致,直接返回 return 0
  • redis.call('get', KEYS[1]):获取锁的标识(原子操作)

  • == ARGV[1]:和当前线程的标识对比(原子操作)

  • redis.call('del', KEYS[1]):如果一致,删除锁(原子操作)

总结:通过 Lua 脚本将「判断锁标识 + 删除锁」合并为 Redis 原子操作,彻底解决旧版 Java 解锁逻辑中「非原子操作导致的锁误删问题」,让分布式锁的解锁过程 100% 安全可靠。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询