zoukankan      html  css  js  c++  java
  • (九)redis使用lua脚本

    Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。
    时间复杂度:取决于执行的脚本。

    使用Lua脚本的好处:

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

    语法

    redis 127.0.0.1:6379> EVAL script numkeys key [key ...] arg [arg ...]
    
    • script: 参数是一段 Lua 5.1 脚本程序。脚本不必(也不应该)定义为一个 Lua 函数。
    • numkeys: 用于指定键名参数的个数。
    • key [key ...]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
    • arg [arg ...]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。

    示例:

    127.0.0.1:6379> eval "return ARGV[1]" 0 100 
    "100"
    127.0.0.1:6379> eval "return {ARGV[1],ARGV[2]}" 0 100 101
    1) "100"
    2) "101"
    
    127.0.0.1:6379> eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
    1) "key1"
    2) "key2"
    3) "first"
    4) "second"
    
    127.0.0.1:6379> eval "redis.call('SET', KEYS[1], ARGV[1]);redis.call('EXPIRE', KEYS[1], ARGV[2]); return 1;" 1 test 10 60
    (integer) 1
    127.0.0.1:6379> ttl test
    (integer) 59
    127.0.0.1:6379> get test
    "10"
    
    • {}在lua里是指数据类型table,类似数组。
    • redis.call()可以调用redis命令。

    命令行里使用

    如果直接使用redis-cli命令,格式会有点不一样:

    redis-cli --eval lua_file.lua key1 key2 , arg1 arg2 arg3
    
    • eval 后面参数是lua脚本文件,.lua后缀。
    • 不用写numkeys,而是使用,隔开。注意,前后有空格。

    示例:
    incrbymul.lua

    local num = redis.call('GET', KEYS[1]);  
    
    if not num then
    	return 0;
    else
    	local res = num * ARGV[1]; 
    	redis.call('SET',KEYS[1], res); 
    	return res;
    end
    

    命令行运行:

    $ redis-cli --eval incrbymul.lua lua:incrbymul , 8
    (integer) 0
    $ redis-cli incr lua:incrbymul 
    (integer) 1
    $ redis-cli --eval incrbymul.lua lua:incrbymul , 8
    (integer) 8
    $ redis-cli --eval incrbymul.lua lua:incrbymul , 8
    (integer) 64
    $ redis-cli --eval incrbymul.lua lua:incrbymul , 2
    (integer) 128
    

    由于redis没有提供命令可以实现将一个数原子性的乘以N倍,这里我们就用Lua脚本实现了,运行过程中确保不会被其它客户端打断。

    使用jedis执行lua脚本

        String script = "return { KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3] }";  
    
        List<String> keys = new ArrayList<String>();  
        keys.add("key1");  
        keys.add("key2");
    
        List<String> args = new ArrayList<String>();  
        args.add("first");  
        args.add("second");  
        args.add("third"); 
    
        List<String> response = (List<String>) jedis.eval(script, keys, args); 
    
    
  • 相关阅读:
    《魏坤琳的科学育儿宝典》笔记
    大千世界中,万物皆有时节
    心里健康基本要素
    不带评论的观察是人类智力的最高形式
    《七律·人民解放军占领南京》
    《最好的防御就是进攻》-- 向任总汇报无线业务会议纪要 2013年9月5日
    《深淘滩,低作堰》-- 任正非在运作与交付体系奋斗表彰大会上的讲话 2009年4月24日
    《市场经济是最好的竞争方式,经济全球化是不可阻挡的潮流》-- 任正非在财经系统表彰大会上的讲话 2009年3月24日
    《开放、妥协与灰度》-- 任正非在2009年全球市场工作会议上的讲话 2009年1月15日
    《让青春的火花,点燃无愧无悔的人生》-- 任正非在无线产品线奋斗大会上的讲话纪要 2008年5月31日
  • 原文地址:https://www.cnblogs.com/everyingo/p/13062182.html
Copyright © 2011-2022 走看看