redis 调用Lua脚本 EVAL命令 SCRIPT命令
redis+lua 实现评分排行榜实时更新 lua 脚本 Golang调用redis+lua示例 byte切片与string的转换优化 github链接
参考文献
redis调用Lua脚本需要使用EVAL命令。 redis EVAL命令格式:
最简单的例子:
使用redis-cli调用lua脚本示例(若在windows系统下,则需要在git bash中执行,在powershell中无法读取value):
test.lua如下(redis log打印在server的日志中):
redis提供了以下几个script命令,用于对于脚本子系统进行控制:
script flush:清除所有的脚本缓存
script load:将脚本装入脚本缓存,不立即运行并返回其校验和
script exists:根据指定脚本校验和,检查脚本是否存在于缓存
script kill:杀死当前正在运行的脚本(防止脚本运行缓存,占用内存)
主要优势: 减少网络开销:多个请求通过脚本一次发送,减少网络延迟
原子操作:将脚本作为一个整体执行,中间不会插入其他命令,无需使用事务
复用:客户端发送的脚本永久存在redis中,其他客户端可以复用脚本
可嵌入性:可嵌入JAVA,C#等多种编程语言,支持不同操作系统跨平台交互
通过script命令加载及执行lua脚本示例:
#redis+lua 实现评分排行榜实时更新 使用redis的zset保存排行数据,使用lua脚本实现评分排行更新的原子操作。
相关redis命令: ZCARD key 获取有序集合的成员数 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 通过分数返回有序集合指定区间内的成员(从小到大的顺序) ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员 ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数 主要思路是维护一个zset,将评分前N位保存到redis中,当成员的评分发生变化时,动态更新zset的成员信息。 lua脚本如下,其中 KEYS[1]表示zset的key, ARGV[1]表示期望的zset最大存储成员数量, ARGV[2]表示评分上限,默认评分下限是0, ARGV[3]表示待添加的评分, ARGV[4]表示待添加的成员名称。
init函数中读取Lua脚本并通过redisgo包的NewScript函数加载这个脚本,在使用时通过返回的指针调用lua.Do()即可。
redisgo包对Do方法做了优化,会检查这个脚本的SHA是否存在,若不存在,会通过EVAL命令执行即会加载脚本,下次执行就可以通过 EVALSHA来执行了。
在Go读取了脚本内容存在byte切片中,需要转化为string来调用redis.NewScript来创建对象。 通过unsafe包转化可以避免内存拷贝从而提高效率。 unsafe 包提供了 2 点重要的能力: 任何类型的指针和 unsafe.Pointer 可以相互转换。 uintptr 类型和 unsafe.Pointer 可以相互转换。

通过unsafe包将byte切片转换为string示例:
string与slice底层结构如下:
详见https://github.com/GrassInWind2019/bookms