有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用RedisTemplate执行Lua脚本永远不会工作

我目前正在为kafka和GC PubSub开发一个基准工具。我想看看关于最小最大和平均传输速度的结果。在之前,我将每个条目都设置为reddis散列。之后,我将reddis散列映射到javamap,并在过程结束时对其进行迭代,以获得最小值和最大值。它看起来很慢,因为如果我调用100000 entry,程序会迭代x3的最小值、最大值和平均值。所以我尝试用Lua脚本来实现这一点。发布消息后,我将开始时间设置为散列映射,当侦听器获取消息时,我从散列中获取该消息的开始时间,并使用System.currentTimeMillis计算差异。在这一步之后,我将尝试执行一个比较当前值和旧值并设置它的Lua脚本。但当我执行脚本时,程序似乎停止了。我尝试从Lua脚本返回true,但没有得到任何响应

 private void calculateSetANDLogAgain(User user){
        long startTime = ((long) redisTemplate.opsForHash().get("times", user.getId()));
        logger.info("Received message -> " + user.toString());
        long duration = 0L;
        duration = System.currentTimeMillis() - startTime;
        Object[] args = new Object[1];
        args[0] = duration;
        System.out.println("BEFORE");
        boolean a = redisTemplate.execute(statisticScript, Collections.singletonList("a"),args);
        System.out.println("AFTER: " + a);
    }

这里我以前看到过,但打印后看不见。下面是关于脚本执行的log输出和配置。这是我的class tree。注意RedisConfig类具有下面的bean

 @Bean
    public DefaultRedisScript<Boolean> redisscript(){
        DefaultRedisScript defaultRedisScript = new DefaultRedisScript<>();
        defaultRedisScript.setLocation(new ClassPathResource("statistics.lua"));
        defaultRedisScript.setResultType(Boolean.class);
        return defaultRedisScript;
    }

我正在拥有calculateSetANDLogAgain方法的类中自动连接DefaultRedisScript实例。脚本文件只有“return true;

编辑;这是我的第一个脚本,如果它有帮助的话

local difference = tonumber(ARGV[1])
local max = tonumber(redis.call("GET","max"))
local min = tonumber(redis.call("GET","min"))
if max == nil then
    redis.call("SET","max",difference)
elseif difference > max then
    redis.call("SET","max",difference)
end
if min == nil then
    redis.call("SET","min",difference)
elseif difference < min then
    redis.call("SET","min",difference)
end

那么,会出现什么问题呢?我想不出来


共 (1) 个答案

  1. # 1 楼答案

    我解决了这个问题。这很奇怪,但似乎失败的根源是错误的类路径。我在代码中做了一些更改,请看一看

    以下是Bean的定义

       @Bean
        public DefaultRedisScript<Boolean> redisscript() {
            DefaultRedisScript defaultRedisScript = new DefaultRedisScript<Boolean>();
            defaultRedisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("statistics.lua")));
            defaultRedisScript.setResultType(Boolean.class);
            return defaultRedisScript;
        }
    

    下面是calculateSetANDLogAgain函数

        private void calculateSetANDLogAgain(User user) {
            long startTime = ((long) redisTemplate.opsForHash().get("times", user.getId()));
            logger.info("Received message -> " + user.toString());
            Long duration = null;
            duration = System.currentTimeMillis() - startTime;
            Object[] args = new Object[1];
            args[0] = duration;
            try {
                redisTemplate.execute(statisticScript, null, args);
            } catch (Exception e) {
                finalLogger.info("Error while executing script -> " + e.getLocalizedMessage());
            }
        }
    

    这是剧本

    local difference = tonumber(ARGV[1])
    local max = tonumber(redis.call("GET","max"))
    local min = tonumber(redis.call("GET","min"))
    if max == nil then
        redis.call("SET","max",tostring(difference));
    elseif difference > max then
        redis.call("SET","max",tostring(difference));
    end
    
    if min == nil then
        redis.call("SET","min",tostring(difference));
    elseif difference < min then
        redis.call("SET","min",tostring(difference));
    end
    return nil;
    

    最后,我将脚本放在resources文件夹中,并将redistemplate注入构造函数中