当前位置:网站首页 > Lua脚本开发 > 正文

执行lua脚本的软件_魔兽世界lua能写一键宏吗

在使用redis过程中,我们经常会使用到lua脚本,可能大多数的同学使用场景是这样的:

incrScript := "一大段的lua脚本" redis.Eval(incrScript, keys, args...)

lua脚本可能会很长,这里就会有个问题是需要考虑的,每次执行都有传输一大段文本到redis服务器(脚本文本),很浪费网络io;聪明的同学可能会想到解决方案了。把脚本缓存到服务器上,通过

redis.EvalSha(scHash, keys, args...)

来执行;很好,于是乎这样的思路出现了,先加载脚本到redis服务器,得到一个脚本hash值,通过 EvalSha 来执行脚本,大体的代码是这样的:

scHash, e = redis.ScriptLoad(incrScript) redis.EvalSha(scHash, keys, args...)

但是,这里要解决两个问题:

1)怎么保证ScriptLoad尽量少的执行?

2)集群环境多节点怎么保障?

针对第一个问题,我的思路是这样的,通过一个闭包机制,保障一个进程内,第一次调用执行ScriptLoad得到脚本hash值,具体代码实现:

var incrScriptFn = func() func(cli *redis.Redis, keys []string, args ...interface{}) (val interface{}, err error) { once := &sync.Once{} scHash := "" return func(cli *redis.Redis, keys []string, args ...interface{}) (val interface{}, err error) { once.Do(func() { _ = tools.DoWithRetry(func() error { var e error scHash, e = cli.ScriptLoad(incrScript) return e }, time.Millisecond*15) }) // 通过得到的scHash来调用cli.EvalSha(scHash, keys, args...) ...... ...... ...... } }()

针对第二个问题,我的思路是这样的,因为同样的脚本(注意,脚本里面不能出现随机值和可变值,保障在不同的客户端执行hash的结果是一样的)执行的hash值是一样的,并且redis有个机制,在每次支持eval以后,服务器会缓存该脚本,缓存的脚本hash值跟ScriptLoad得到的hash值是一样的

针对这个机制,我们可以代码这样来实现:

var incrScriptFn = func() func(cli *redis.Redis, keys []string, args ...interface{}) (val interface{}, err error) { once := &sync.Once{} scHash := "" return func(cli *redis.Redis, keys []string, args ...interface{}) (val interface{}, err error) { // 得到scHash ..... ..... ..... // 通过执行脚本hash,可以节约数据的传输 val, err = cli.EvalSha(scHash, keys, args...) if err != nil { // 如果失败,有可能是在集群环境中,打到没有缓存的节点上了,这里通过eval直接执行,执行成功以后,该节点会缓存该脚本,下次 // 执行就直接可以运行EvalSha了 return cli.Eval(incrScript, keys, args...) } return } }()

综上,最后完整的闭包代码实现:

var incrScriptFn = func() func(cli *redis.Redis, keys []string, args ...interface{}) (val interface{}, err error) { once := &sync.Once{} scHash := "" return func(cli *redis.Redis, keys []string, args ...interface{}) (val interface{}, err error) { once.Do(func() { _ = tools.DoWithRetry(func() error { var e error scHash, e = cli.ScriptLoad(incrScript) return e }, time.Millisecond*15) }) if len(scHash) == 0 { // 这里是一个保护设置,保证在incrScriptHash获取不到脚本hash的时候还能正常执行 return cli.Eval(incrScript, keys, args...) } // 通过执行脚本hash,可以节约数据的传输 val, err = cli.EvalSha(scHash, keys, args...) if err != nil { // 如果失败,有可能是在集群环境中,打到没有缓存的节点上了,这里通过eval直接执行,执行成功以后,该节点会缓存该脚本,下次 // 执行就直接可以运行EvalSha了 return cli.Eval(incrScript, keys, args...) } return } }()

调用的地方:

说到最后:

当然,有的同学可能会这样想,我们可以让运维同学先把脚本缓存到服务器呀,代码里面直接使用hash值。但是这里有个问题就是运维成本的问题,加之在redis环境中,节点可能是动态伸缩的。所以从简单角度考虑,还是代码实现更方便。

欢迎大家砸砖讨论,留言转发关注

到此这篇执行lua脚本的软件_魔兽世界lua能写一键宏吗的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 详解事务模式和Lua脚本,带你吃透Redis 事务2024-11-12 23:45:07
  • lua脚本编程器_lua脚本语言2024-11-12 23:45:07
  • redis的lua脚本有什么用_罗技lua脚本2024-11-12 23:45:07
  • redisson lua脚本_如何编写脚本2024-11-12 23:45:07
  • lua脚本语言零基础教程_lua可视化脚本编辑器2024-11-12 23:45:07
  • redis中lua脚本的简单使用_redis lua脚本怎么用2024-11-12 23:45:07
  • nginx lua waf_linux嵌入式软件开发2024-11-12 23:45:07
  • openresty lua教程_如何使用脚本2024-11-12 23:45:07
  • lua脚本开发工具_lua脚本是什么2024-11-12 23:45:07
  • Redis八大附加功能:慢查询分析+Redis Shell+PiPline+事务与Lua脚本+Bitmaps+HyperLogLog+发布订阅+GEO2024-11-12 23:45:07
  • 全屏图片