Go语言中怎么通过Lua脚本操作Redis


前言

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

EVAL能够提供的特性:

  • 可以在lua脚本中封装若干操作,如果有多条redis指令,封装好之后只需向redis一次性发送所有参数即可获得结果

  • Redis可以保证Lua脚本运行期间不会有其他命令插入执行,提供像数据库事务一样的原子性

  • Redis会根据脚本的SHA值缓存脚本,已经缓存过的脚本不需要再次传输Lua代码,减少了通信成本,此外在自己代码中改变Lua脚本,执行时Redis必定也会使用最新的代码。

导入常见的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脚本的限制

  • Redis不提供引入额外的包,例如os等,只有redis这一个包可用。

    lua lua

    本文档是lua-5.1中文手册;Lua 是一个扩展式程序设计语言,它被设计成支持通用的过程式编程,并有相关数据描述的设施。 Lua 也能对面向对象编程,函数式编程,数据驱动式编程提供很好的支持。它可以作为一个强大、轻量的脚本语言,供任何需要的程序使用。 Lua 是一个自由软件,它的使用许可决定了对它的使用过程一般没有任何保证。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看

    lua 1 查看详情 lua
  • Lua脚本将会在一个函数中运行,所有变量必须使用local声明

  • return返回多个值时,Redis将会只给你第一个

脚本中的类型限制

  • 脚本返回nil时,Go中得到的是err = redis.Nil(与Get找不到值相同)

  • 脚本返回false时,Go中得到的是nil,脚本返回true时,Go中得到的是int64类型的1

  • 脚本返回{"ok": ...}时,Go中得到的是redis的status类型(true/false)

  • 脚本返回{"err": ...}时,Go中得到的是err值,也可以通过return redis.error_reply("My Error")达成

  • 脚本返回number类型时,Go中得到的是int64类型

  • 在脚本中,如果需要将传入的KEYS/ARGV中的值从字符串类型转换为数字类型,则应使用to_number函数

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

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

以上就是Go语言中怎么通过Lua脚本操作Redis的详细内容,更多请关注其它相关文章!


# 很好  # 免费b2b网站推广嘿嘿  # 自媒体短视频seo  # 大庆短视频推广如何营销  # seo dedecms  # 北京seo 牛商网  # 北海麻辣串团购网站推广  # 石家庄无极网站推广价钱  # 邢台网站建设个人  # 恋爱记网站推广  # 网站建设招聘洁信赖  # 会有  # Go语言  # 文档  # 这一  # 行号  # 不需要  # 也会  # 是一个  # 将会  # 的是  # lua  # redis 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 三角洲行动2025年9月10日摩斯密码分享  《搜书吧》阅读书籍方法  网站体验不好=浪费钱:如何提升-用户体验效果差  顺丰速运官网查询入口 顺丰物流查询官网入口链接  《七读免费小说》开通会员方法  抖音怎么解除第三方绑定_抖音解除第三方平台绑定方法介绍  《鹿路通》退余额方法  如何在CSS中使用伪类选择器_hover实现悬停效果  《洛克王国:世界》国家队搭配攻略  J*a中导出MySQL表为SQL脚本的两种方法  CSS如何控制元素外边距_margin实现布局间隔  sf漫画官网登录入口直达_sf漫画官方正版网址  mysql如何限制远程访问_mysql远程访问限制方法  FotoBalloon图片左右镜像教程  视频转蓝光m2ts格式  qq音乐官方网站入口_qq音乐在线听歌网页版链接  猫眼app抢票快还是小程序快  青橙手机语音助手怎么唤醒_青橙手机语音助手设置与唤醒方法  毒蘑菇VOLUMESHADER_BM官网首页登录入口 毒蘑菇VOLUMESHADER_BM官网首页登录入口说明  跨语言测试实践:使用Python Selenium测试现有J*a Web项目  word邮件合并怎么插入个性化图片_Word邮件合并插入个性化图片方法  支付宝登录刷脸不是本人如何解决  聚水潭ERP后台管理系统登录 聚水潭ERP官方登录通道  消除网页顶部意外空白线:CSS布局常见问题与解决方案  C#解析并修改XML后保存 如何确保格式与编码的正确性  解决异步Python机器人中同步操作的阻塞问题  win11关机几秒又自己开机 Win11关机自动重启问题修复  sublime怎么在文件中显示代码结构大纲_sublime符号列表功能  苹果17 Pro如何启用分屏浏览_iPhone 17 Pro分屏浏览设置步骤  windows10怎么设置电源按钮_windows10按下电源键功能修改  Win10共享文件夹设置方法 Win10局域网文件共享全攻略【教程】  win11怎么启用或禁用休眠 Win11 powercfg命令管理休眠文件【技巧】  steam缓存文件在哪儿_steam缓存文件的路径查找方法与结构说明  CSS过渡如何实现按钮悬停效果_transition属性控制背景颜色变化  cad视图选项卡不见了怎么办_cad视图标签恢复显示方法  Highcharts雷达图轴线交点数值标注指南  传统曲艺莲花落的表演形式是  《随手记》备份数据方法  使用Python和GBGB API高效抓取指定日期范围和赛道比赛结果教程  在PySimpleGUI中实现键盘按键绑定按钮事件  yy漫画登录页面官方入口_yy漫画在线阅读网址入口  《广发易淘金》国债逆回购操作教程  食品生产用水只要符合国家规定的生活饮用水卫生标准就可以吗  msn官方入口2025登录 msn官网2025直达首页入口  快手缓存清理方法  《飞猪旅行》购买汽车票方法  如何高效地基于键列值映射DataFrame中的多个列  魔法祈幻界兑换码礼包大全  windows10怎么关闭自动安装应用_windows10禁止推广应用下载  J*a中为什么强调组合优于继承_组合模式带来的灵活性与可维护性解析 

 2023-05-27

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.