lua脚本笔记、redis使用lua解锁

文章目录

lua是一门独立的语言。
用lua来解锁redis是非常流行的一种方式。

下载、安装、环境配置

1、官网首页 | 点 download,不要选tag.gz版本,要选预编译版本Pre-compiled后面的LuaBinaries。如图:

2、再点左侧的download,选对应版本下载,例如windows选这个:

3、解压后里面有lua55.exe等程序、将这个文件夹添加到环境变量

4、新打开cmd窗口,输入lua55,出现版本号表示成功。

5、复制lua55.exe,命名为lua.exe,这样用起来方便。

lua解锁redis实践

最佳实践或者通用场景如下:

1、加锁用setIfAbsent

2、解锁用lua

如果使用luaj,那么linux环境连lua都不需要支持,java包里面直接自带了,方便的很。

示例1

代码:

java 复制代码
String lockKey = "myLock";
String requestId = UUID.randomUUID().toString();

try {
    // 1. 加锁 (带过期时间)
    Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, 10, TimeUnit.SECONDS);
    
    if (Boolean.TRUE.equals(locked)) {
        // 2. 执行业务
        doSomething();
    } else {
        // 获取锁失败处理
    }
} finally {
    // 3. 必须主动解锁!
    // 注意:这里最好用 Lua 脚本判断 requestId 再删除,防止误删
    if (isLocked) {
        unlockWithLuaScript(lockKey, requestId); 
    }
}
示例2

代码:

java 复制代码
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;

import java.util.Collections;
import java.util.UUID;

public class RedisLockUtil {

    private final RedisTemplate<String, Object> redisTemplate;

    public RedisLockUtil(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 1. 定义 Lua 脚本
     * 逻辑:如果 key 存在 且 value 等于 myId,则删除 key,返回 1;否则返回 0
     */
    private static final String UNLOCK_LUA_SCRIPT =
            "if redis.call('get', KEYS[1]) == ARGV[1] then " +
            "   return redis.call('del', KEYS[1]) " +
            "else " +
            "   return 0 " +
            "end";

    /**
     * 加锁方法 (为了完整性)
     */
    public boolean lock(String lockKey, String requestId, long expireTime) {
        return Boolean.TRUE.equals(redisTemplate.opsForValue()
                .setIfAbsent(lockKey, requestId, expireTime, java.util.concurrent.TimeUnit.SECONDS));
    }

    /**
     * 2. 解锁方法 (核心部分)
     */
    public void unlock(String lockKey, String requestId) {
        // 封装脚本对象,指定返回类型为 Long
        DefaultRedisScript<Long> script = new DefaultRedisScript<>();
        script.setScriptText(UNLOCK_LUA_SCRIPT);
        script.setResultType(Long.class);

        try {
            // 执行脚本
            // 参数1: 脚本对象
            // 参数2: KEYS 列表 (这里只有一个锁的 key)
            // 参数3: ARGV 列表 (这里是要比对的 requestId)
            Long result = redisTemplate.execute(
                    script, 
                    Collections.singletonList(lockKey), 
                    requestId
            );

            if (result != null && result == 1) {
                System.out.println("解锁成功: " + lockKey);
            } else {
                System.out.println("解锁失败: 锁不存在或不是当前线程持有");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // --- 测试主函数 ---
    public static void main(String[] args) throws InterruptedException {
        // 假设你已经配置好了 RedisTemplate (这里仅作伪代码示意)
        // RedisTemplate<String, Object> template = ... 
        
        // RedisLockUtil lockUtil = new RedisLockUtil(template);
        
        String lockKey = "order_lock_001";
        String myId = UUID.randomUUID().toString(); // 唯一标识

        // 模拟加锁
        // boolean isLock = lockUtil.lock(lockKey, myId, 10);
        
        try {
            // if (isLock) {
                System.out.println("业务执行中...");
                Thread.sleep(1000);
            // }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 模拟解锁
            // lockUtil.unlock(lockKey, myId);
        }
    }
}

pycharm运行lua脚本

vscode就很不错,pycharm也可以。

先安装插件emmylua。

在.lua文件上,点运行配置:

1、新建lua application

2、配置lua.exe的位置

3、选要执行的.lua文件,点运行配置

其他

文档

lua官网(速度快):
https://www.lua.org/

相关推荐
sunoo-22912 分钟前
【Linux 系统编程】学习第七天:线程属性 | 互斥锁 | 死锁 | 信号量 核心知识点 + 踩坑实战
linux·c语言·笔记·vscode·学习
Baron X18 分钟前
Redis 7.0.9 完整部署指南
数据库·redis
LccKyI1 小时前
C#基础编程 面试题汇总(三)
笔记·c#
懿路向前1 小时前
【HarmonyOS学习笔记】2026-08-27 | 端插件踩坑与设计取舍
笔记·学习·harmonyos
ouynagda2 小时前
Linux多线程:互斥锁与信号量学习笔记
linux·笔记·学习
疯狂打码的少年4 小时前
【数据库技术】两级映像与数据独立性(逻辑/物理独立性)
数据库·笔记
翻身的咸鱼ing4 小时前
ArkTS 学习笔记
笔记·学习
程序猿炎义4 小时前
【llm-algo-leetcode学习笔记】训练侧显存优化
人工智能·笔记·学习
动词ing4 小时前
【学习笔记】数据结构(数组滑动窗口+无重复字符的最长字串题目)
数据结构·笔记·学习
CarIise5 小时前
JavaScript进阶与轮播图实现 课堂笔记
开发语言·javascript·笔记