• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Go语言中通过Lua脚本操作Redis的方法

    前言

    为了在我的一个基本库中降低与Redis的通讯成本,我将一系列操作封装到LUA脚本中,借助Redis提供的EVAL命令来简化操作。

    EVAL能够提供的特性:

    导入常见的Go库如 "github.com/go-redis/redis",就可以实现以下代码。

    生成一段Lua脚本

    // KEYS: key for record
    // ARGV: fieldName, currentUnixTimestamp, recordTTL
    // Update expire field of record key to current timestamp, and renew key expiration
    var updateRecordExpireScript = redis.NewScript(`
    redis.call("EXPIRE", KEYS[1], ARGV[3])
    redis.call("HSET", KEYS[1], ARGV[1], ARGV[2])
    return 1
    `)

    该变量创建时,Lua代码不会被执行,也不需要有已存的Redis连接。

    Redis提供的Lua脚本支持,默认有KEYS、ARGV两个数组,KEYS代表脚本运行时传入的若干键值,ARGV代表传入的若干参数。由于Lua代码需要保持简洁,难免难以读懂,最好为这些参数写一些注释

    注意:上面一段代码使用``跨行,`所在的行虽然空白回车,也会被认为是一行,报错时不要看错代码行号。

    运行一段Lua脚本

     updateRecordExpireScript.Run(c.Client, []string{recordKey(key)}, 
             expireField,
             time.Now().UTC().UnixNano(), int64(c.opt.RecordTTL/time.Second)).Err()

    运行时,Run将会先通过EVALSHA尝试通过缓存运行脚本。如果没有缓存,则使用EVAL运行,这时Lua脚本才会被整个传入Redis。

    Lua脚本的限制

    脚本中的类型限制

    如果脚本运行了很久会发生什么?

    Lua脚本运行期间,为了避免被其他操作污染数据,这期间将不能执行其它命令,一直等到执行完毕才可以继续执行其它请求。当Lua脚本执行时间超过了lua-time-limit时,其他请求将会收到Busy错误,除非这些请求是SCRIPT KILL(杀掉脚本)或者SHUTDOWN NOSAVE(不保存结果直接关闭Redis)

    更多内容参考以下地址,我这里主要是根据使用Go的经验提供一些总结。https://redis.io/commands/eval

    一段更“复杂”的脚本,它要求在获取一个key值时,如果该值访问较多,就延长生存周期。此外还要比较更新时间,如果不需要更新,则直接返回取到的值,否则返回redis.Nil

    // KEYS: rec:key, key
    // ARGV: currentUnixTimestamp, hotHit, recordTTL, ttl
    // When there's a hit,
    var fetchRecordScript = redis.NewScript(local value = redis.call("GET", KEYS[2]) if(value == nil) then return nil end local hit = redis.call("HINCRBY", KEYS[1], "hit", 1) redis.call("EXPIRE", KEYS[1], ARGV[3]) local minHotHit = tonumber(ARGV[2]) local keyTTL = tonumber(ARGV[4]) if(hit > minHotHit)then keyTTL = keyTTL * 2 end redis.call("EXPIRE", KEYS[2], keyTTL) local expire = tonumber(redis.call("HGET", KEYS[1], "expire")) local unixTime = tonumber(ARGV[1]) if(expire == nil or expire  unixTime) then return nil else return value end)
    // KEYS: key for record
    // ARGV: fieldName, currentUnixTimestamp, recordTTL
    // Update expire field of record key to current timestamp, and renew key expiration
    var updateRecordExpireScript = redis.NewScript(redis.call("EXPIRE", KEYS[1], ARGV[3]) redis.call("HSET", KEYS[1], ARGV[1], ARGV[2]) return 1)

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

    您可能感兴趣的文章:
    • SpringBoot通过RedisTemplate执行Lua脚本的方法步骤
    • Redis执行Lua脚本的好处与示例代码
    • redis中如何使用lua脚本让你的灵活性提高5个逼格详解
    • Redis分布式锁的实现方式(redis面试题)
    • SpringBoot使用Redisson实现分布式锁(秒杀系统)
    • SpringBoot集成Redisson实现分布式锁的方法示例
    • Java Redis分布式锁的正确实现方式详解
    • 基于Redis实现分布式锁的方法(lua脚本版)
    上一篇:vim配置go语言语法高亮问题的解决方法
    下一篇:Go语言中切片使用的注意事项小结
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Go语言中通过Lua脚本操作Redis的方法 语,言中,通过,Lua,脚本,操作,