【Redis】已解决:redis.clients.jedis.exceptions.JedisNoScriptException


在这里插入图片描述
已解决:redis.clients.jedis.exceptions.JedisNoScriptException

一、分析问题背景

在使用Redis进行缓存或数据处理时,Lua脚本是一种常用的扩展手段,用于保证操作的原子性和高效性。Jedis是Java中使用Redis的一个常用客户端库,但在执行Lua脚本时,开发者可能会遇到redis.clients.jedis.exceptions.JedisNoScriptException报错。这个异常通常发生在尝试执行一个未加载到Redis服务器中的脚本时。以下是一个典型场景:

场景:在一个Spring Boot项目中,开发者使用Jedis来执行Redis Lua脚本进行分布式锁的实现。

示例代码片段:

import redis.clients.jedis.Jedis;

public class RedisLock {

    private static final String LOCK_SCRIPT = "return redis.call('set', KEYS[1], ARGV[1], 'NX', 'PX', ARGV[2])";

    public boolean acquireLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        Object result = jedis.eval(LOCK_SCRIPT, 1, lockKey, requestId, String.valueOf(expireTime));
        return "OK".equals(result);
    }
}

在上述代码中,开发者希望通过Lua脚本在Redis中设置一个分布式锁,但在执行时可能会遇到JedisNoScriptException异常。

二、可能出错的原因

导致redis.clients.jedis.exceptions.JedisNoScriptException报错的原因主要有以下几点:

  1. 脚本未加载:Lua脚本未加载到Redis服务器中,或者由于某种原因被Redis服务器清除。
  2. 脚本缓存失效:Redis服务器重启或清除脚本缓存,导致之前加载的脚本失效。
  3. 脚本SHA不匹配:如果使用了脚本的SHA值进行调用,但SHA值不正确或不匹配,也会导致该异常。

三、错误代码示例

以下是一个可能导致该报错的代码示例,并解释其错误之处:

import redis.clients.jedis.Jedis;

public class RedisLock {

    private static final String LOCK_SCRIPT_SHA = "e0e1f9df1fa3a6dd7c1e3b7f2e9f5e63b71da9f7";

    public boolean acquireLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        // 使用硬编码的SHA值调用脚本
        Object result = jedis.evalsha(LOCK_SCRIPT_SHA, 1, lockKey, requestId, String.valueOf(expireTime));
        return "OK".equals(result);
    }
}

错误分析:

  1. 硬编码SHA值:脚本的SHA值被硬编码,如果Redis服务器重启或脚本缓存失效,该SHA值可能无效,导致JedisNoScriptException异常。

四、正确代码示例

为了解决该报错问题,可以在执行脚本之前先加载脚本并获取其SHA值,然后使用该SHA值进行脚本调用。以下是正确的代码示例:

import redis.clients.jedis.Jedis;

public class RedisLock {

    private static final String LOCK_SCRIPT = "return redis.call('set', KEYS[1], ARGV[1], 'NX', 'PX', ARGV[2])";
    private String lockScriptSha;

    public boolean acquireLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
        // 检查SHA值是否已加载,如果未加载则加载脚本
        if (lockScriptSha == null) {
            lockScriptSha = jedis.scriptLoad(LOCK_SCRIPT);
        }

        try {
            // 使用SHA值调用脚本
            Object result = jedis.evalsha(lockScriptSha, 1, lockKey, requestId, String.valueOf(expireTime));
            return "OK".equals(result);
        } catch (redis.clients.jedis.exceptions.JedisNoScriptException e) {
            // 如果脚本未找到,重新加载并执行
            lockScriptSha = jedis.scriptLoad(LOCK_SCRIPT);
            Object result = jedis.evalsha(lockScriptSha, 1, lockKey, requestId, String.valueOf(expireTime));
            return "OK".equals(result);
        }
    }
}

通过上述代码,我们可以确保脚本在Redis中被正确加载和执行,从而避免JedisNoScriptException异常。

五、注意事项

在编写和使用Jedis执行Redis Lua脚本时,需要注意以下几点:

  1. 脚本加载和缓存:在使用脚本前确保脚本已加载到Redis服务器,并缓存其SHA值。
  2. 异常处理:在捕获JedisNoScriptException时,重新加载脚本并重试执行,以确保脚本正常运行。
  3. 代码风格和规范:遵循良好的代码风格和规范,保持代码清晰和可维护。
  4. 资源管理:确保Jedis连接正确关闭,避免资源泄露。
  5. 脚本管理:集中管理和维护Lua脚本,避免硬编码SHA值,以提升代码的灵活性和可维护性。

通过以上步骤和注意事项,可以有效解决redis.clients.jedis.exceptions.JedisNoScriptException报错问题,确保Redis Lua脚本的正确执行。

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

屿小夏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值