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/

相关推荐
bst@微胖子8 小时前
Linux环境做LVM快照
lua
1314lay_10079 小时前
SAP 接口调用 500 Native SSL Error ,导入证书
经验分享·笔记
晚安日记wanna9 小时前
Redis 持久化RDB 和 AOF 到底该怎么选
redis·面试·架构
百里香酚兰9 小时前
【Unity学习笔记】如何把粉色Prefab还原
笔记·学习·unity
小叶肥辉10 小时前
LangChain链和LangGraph图的学习笔记【六】——提示语模板(3)——Few-Shot Prompting(少样本提示) 模板类
笔记·python·学习·langchain·prompt·aigc
志尊宝11 小时前
Vue3 零基础每日笔记(032):Suspense 与异步组件——懒加载与顶层 await 终极方案
前端·javascript·vue.js·笔记·html5
今儿敲了吗12 小时前
04英文文本关键词提取(TF-IDF)
笔记·python
志尊宝12 小时前
Vue3 零基础每日笔记(035):什么是 Composables——mixin 之死与逻辑复用新方案
笔记·vue·html·前端开发·软件开发
晴空蓝天12 小时前
Spring Boot 3.5 脚手架里的 JWT + Redis 双轨会话,双端 token 隔离我是这么设计的
java·spring boot·redis
动词ing12 小时前
【学习笔记】数据结构 二分查找(二分查找模板+边界处理+查找区间+旋转数组)
笔记·学习