前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis 7.0 新功能 Redis Functions 介绍

Redis 7.0 新功能 Redis Functions 介绍

原创
作者头像
HullQin
发布2022-09-28 22:35:21
7.2K4
发布2022-09-28 22:35:21
举报
文章被收录于专栏:教你做小游戏教你做小游戏

背景

2022年4月27日,Redis正式发布了7.0更新(其实早在2022年1月31日,Redis已经预发布了7.0rc-1,经过社区的考验后,确认没重大Bug才会正式发布)。

在众多新特性中,Redis团队把Redis Functions放在了第一位:

image.png
image.png

可见官方对这个特性是相当重视。今天我们来一起学习下Redis Functions

学习前,需了解:Redis旧版本中的lua脚本

Redis为了给开发者更灵活的能力,内置了lua解释器,可以让开发者执行功能强大的「原子操作」。

例如以下场景,只通过Redis本身的数据结构,实现起来是比较低效的:

  • 某个key的string value自乘2。
  • 若keyA=某个数字,则同时设置keyA和keyB。
  • ……

由于Redis本身并没有暴露上述命令,所以我们需要通过transactions或者watch来实现,而watch又不能保证100%成功,可能还需要引入重试。也可以通过分布式锁来实现。但这些都让系统变得更复杂、效率更低。

最高效的方式,其实是Redis内部实现好,暴露相关指令出来(例如incr指令),因为指令是原子的,所以可以放心使用。当然Redis即使暴露再多指令也没用,肯定无法覆盖各种复杂的实际场景,所以最好的方式就是提供编程能力,允许用户自定义「原子操作」,就是通过lua脚本实现。

有个命令是EVAL

代码语言:shell
复制
EVAL script numkeys [key [key ...]] [arg [arg ...]]

就可以执行一段lua脚本。例如可以这样用:

代码语言:txt
复制
> EVAL "return ARGV[1]" 0 hello
"hello"

在lua中,Redis提供了Redis的几乎所有命令API,你可以读取key、设置key等。在执行lua过程中,Redis不会打断,只有执行完毕,才会去执行其它命令。也就是说,这段脚本是「原子操作」。

但是这种方式有些问题:

  1. 每次执行脚本时,需要先编译再执行,效率低(当然Redis也会针对脚本计算哈希,把编译结果存下来,如果后面的脚本跟之前一致,就不再编译了,直接取之前的结果)。但是第一次执行时,依然存在效率问题,尤其是Redis刚启动时,或者脚本初次执行时。
  2. lua脚本复用比较困难,因为每次都要加载一段新的脚本,函数复用成本较高。

所以,我们继续看看Redis Functions是怎么解决这些问题的。

Redis Functions 相关指令介绍

首先我们先看看Redis Functions提供了哪些指令。

了解Redis Functions必须知道的指令

为了了解这个Redis Functions功能,你至少需要知道这2条:

  • Function Load
  • FCALL

Function Load

先看个例子

首先你可以新建一个lua脚本,名字叫hello.lua:

代码语言:lua
复制
#!lua name=mylib

redis.register_function('myfunc', function(keys, args) return args[1] end)

注意上面的redis.register_function方法,是必须的,就是通过该API(Redis给lua提供的API),来注册函数到Redis中,2个参数分别是函数名称、函数引用。

然后可以执行下面这个shell脚本(前提是你已经安装了redis、redis-cli,并启动了redis):

代码语言:shell
复制
cat mylib.lua | redis-cli -x FUNCTION LOAD

这样,就给redis注册了一个名叫mylib的库,这个库里注册了一个叫myfunc的函数。函数作用是直接return参数1。

也可在redis-cli中直接注册

当然,你也可以直接在redis-cli中调用FUNCTION LOAD注册:

代码语言:shell
复制
FUNCTION LOAD "#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
解释 FUNCTION LOAD

语法:

代码语言:shell
复制
FUNCTION LOAD [REPLACE] function-code

你可以使用该语句加载一个lua模块到redis中,一个模块包含一个或多个函数。后续在redis可以调用这些函数。有如下特性:

  • lua代码需要编译,在FUNCTION LOAD后会自动编译,以后每次调用时都不需要编译,调用速度都是快的。(也许你知道Redis有EVAL,它可以直接执行一段lua代码,但它第一次执行时需要编译,所以初次调用速度不如先FUNCTION LOAD再调用)
  • 支持模块级别的重新加载。只要增加个参数REPLACE,就可以用新模块替换同名旧模块(若该模块是第一次加载,也会加载成功的)。
  • Redis重要特性之一是内存数据可持久化保存。当你加载函数后,关闭Redis时,注册的函数也会被持久化到硬盘。重启Redis时自动重新加载之前加载的函数。
  • Redis Function中执行代码是原子操作,执行过程中不会被打断。

注册完毕了,必然要执行,怎么执行呢,就是用FCALL

FCALL

代码语言:shell
复制
FCALL myfunc 0 hahahahaha

指定了函数名,hahahahaha就是参数1。0我们之后再介绍。

这样执行后,不出意外,会输出hahahahaha

image.png
image.png
解释FCALL

语法:

代码语言:shell
复制
FCALL function numkeys [key [key ...]] [arg [arg ...]]

function就是函数名,就是你的lua文件中,redis.register_function的第一个参数。

numkeys是指后面的参数中代表Redis Key的参数有多少个。

后面可以跟一系列参数,参数有2种:代表Redis key的参数、其它参数。

也就是说,如果你要在lua函数中访问Redis的key,必须通过参数传进来,千万不要自己去拼接。 自己拼接key参数在单机Redis没问题,但是分布式Redis中会有大问题。分布式Redis需要知道你在这个「原子操作」中可能读/写哪些key,来做一些并发控制,以免读到脏数据。

其它指令

  • FCALL_RO: 只读模式调用函数(意思是在函数执行时,你无法写入Redis数据,但可以读取)。分布式Redis针对这种模式会有优化。
  • FUNCTION DELETE: 删除加载的lua模块(注意是模块维度删除)。
  • FUNCTION DUMP: 序列化已加载的函数,返回byte串。
  • FUNCTION RESTORE: 通过byte串(恢复)加载函数。有3种模式:FLUSH(清空已加载的再恢复)、APPEND(新增,但是同名的不再加载)、REPLACE(新增,并替代同名)。
  • FUNCTION FLUSH: 清空已加载函数。
  • FUNCTION KILL: 该命令可以终止正在执行的只读的函数。
  • FUNCTION LIST: 返回已加载的模块、函数列表。
  • FUNCTION STATS: 获取正在执行的函数的状态(函数名、参数信息、已经执行了多久)。因为有些函数耗时太久,会导致Redis这个单线程一直卡着,所以通过查询状态,用户可以决策是否通过FUNCTION KILL终止它。

写在最后

推荐阅读官方文档:https://redis.io/docs/manual/programmability/functions-intro/

我是HullQin,公众号线下聚会游戏的作者(欢迎关注我,交个朋友)。转发本文前需获得作者HullQin授权。我独立开发了《联机桌游合集》,是个网页,可以很方便的跟朋友联机玩斗地主、五子棋等游戏,不收费无广告。还开发了《Dice Crush》参加Game Jam 2022。喜欢可以关注我噢~我有空了会分享做游戏的相关技术,会在这个专栏里分享:《教你做小游戏》

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 学习前,需了解:Redis旧版本中的lua脚本
  • Redis Functions 相关指令介绍
    • 了解Redis Functions必须知道的指令
      • Function Load
      • FCALL
    • 其它指令
    • 写在最后
    相关产品与服务
    云数据库 Redis
    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档