Redis之Lua脚本使用

本文探讨Redis使用Lua脚本的三大优势:减少网络开销、确保原子操作及代码复用性。通过示例展示了如何利用Lua脚本进行简单的Redis操作,并深入介绍了访问频率控制的复杂场景应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Redis使用lua脚本的好处:

  • 减少网络开销。可以将多个请求通过脚本的形式一次发送,减少网络时延
  • 原子操作。redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。因此在编写脚本的过程中无需担心会出现竞态条件,无需使用事务。
  • 复用。客户端发送的脚步会永久存在redis中,这样,其他客户端可以复用这一脚本而不需要使用代码完成相同的逻辑

简单使用

简单的set、get、del

代码
    private static String setLua() {
        String lua = "return redis.call('set', 'KEYS[1]',ARGV[1]);";
        return lua;
    }

    private static String getLua() {
        String lua = "return redis.call('get', 'KEYS[1]');";
        return lua;
    }

    private static String delLua() {
        String lua = "return redis.call('del','KEYS[1]');";
        return lua;
    }

 测试:

        SingleSharedRedisClientAgent redisClientAgent = new SingleSharedRedisClientAgent();
        List<String> keyList = Lists.newArrayList("TEST_KEY");
        List<String> valueList = Lists.newArrayList("LUA脚本测试");
        Object obj = redisClientAgent.eval(setLua(),keyList,valueList);
        System.out.println("SET返回结果:"+obj);
        Object obj1 = redisClientAgent.eval(getLua(),keyList,valueList);
        System.out.println("GET返回结果:"+obj1);

说明:不建议写成lua脚本文件,在从文件读写出来。建议lua脚本写成lua脚本字符串。使用redis的evel命令来执行lua脚本

eval(script, keys, args);
eval命令有三个参数,第一个script:lua脚本,第二个keys是redis的中的key,第三个args是key的值或者参数

上面执行的结果:

SET返回结果:OK
GET返回结果:LUA脚本测试
DEL返回结果:1

复杂使用

实现一个访问频率控制,某个ip在短时间内频繁访问页面,需要记录并检测出来,就可以通过Lua脚本高效的实现

lua脚本:

private static String testLua() {
        String lua = "local times = redis.call('incr',KEYS[1])\n"
                + "if times == 1 then\n"
                + "    redis.call('expire',KEYS[1], ARGV[1])\n"
                + "end\n"
                + "if times > tonumber(ARGV[2]) then\n"
                + "    return 0\n"
                + "end\n"
                + "return 1";
        return lua;
    }

脚本的内容的意思是:将访问频率限制为每10秒最多3次,所以在终端中不断的运行此命令会发现当访问频率在10秒内小于或等于3次时返回1,否则返回0

测试:

 

public static void main(String[] args) {
        SingleSharedRedisClientAgent redisClientAgent = new SingleSharedRedisClientAgent();
        List<String> keyList = Lists.newArrayList("10.24.19.118");
        List<String> valueList = Lists.newArrayList("10", "3");
        for (int i = 0; i < 10; i++) {
            if (i == 3) {
                System.out.println("等待10秒再继续执行......");
                run();
            }
            Object xx = redisClientAgent.eval(testLua(), keyList, valueList);
            System.out.println("返回结果:" + xx);
        }
    }

    private static void run() {
        try {
            Thread.sleep(1000 * 10);//10秒
        } catch (InterruptedException e) {
            System.out.print("error" + e);
        }
    }

 

访问10次,在第4次的时候线程等待10秒再继续执行。在等待十秒的后执行返回结果1,在循环第7次返回0,说明已经访问3次了。

返回结果:1
返回结果:1
返回结果:1
等待10秒再继续执行......
返回结果:1
返回结果:1
返回结果:1
返回结果:0
返回结果:0
返回结果:0
返回结果:0

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值