Redis Functions 介绍(一)

Redis提供了编程接口(programming interface)可以让你在Redis服务器端执行客户的脚本。

一个重大的变化就是从Redis 7开始,你可以选择使用Redis Functions去管理和运行你的脚本,而在此之前你只能使用EVAL命令执行Lua脚本。

通过EVAL命令执行的脚本是有缺陷的。如果在Redis服务器端执行了命令SCRIPT FLUSH, 或者服务器重启,或者主节点执行了一个主备切换,那么存在于服务器端的脚本将会丢失,于是客户端的应用程序需要重新将整个的脚本再次发送到服务器。这个缺陷实际上说明,客户要执行的脚本需要客户端的应用程序去维护而不是Redis服务器端维护。所以,为了解决脚本的一系列问题,Redis在最新发布的7.0版本中提出了Functions这个概念。

Redis Functions最重要的2点是可以持久化的,并且也是可以复制的。Redis Functions提供了和脚本一样的核心功能,但是Redis认为Functions是数据库的一部分,因此,客户端的应用程序在运行时候不需要再load它们,也不用担心在执行事务的操作时候会有中断的危险。在使用Functions之前仅需要先声明它们(declare before use),这样,客户端应用程序仅仅需要调用Functions的API即可,而不需要再关注那些在脚本中的程序逻辑了。Functions提供的这些丰富的API可以包括很多Redis的核心命令,这一点非常 类似于Redis的Modules, 并且,Redis的Functions可以达到开发一次,使用多次的目的,同一个Functions可以在多个客户端应用程序中重复使用。

每个Function都有一个唯一的名字,并且每个Function都属于一个唯一的库(library),在一个库中可以包含多个Function. 要注意一点的是,这个库的内容是不可以改变的,不可以选择性地改变或者更新它所包含的Function,而是必须将整个库作为一个操作将所有的库一起更新。这个特性使得可以在一个库中的多个Function可以互相调用,或者共享代码。

另外要注意的一点,Function的执行是原子化的。当一个Function在执行它的代码时候,它会阻塞Redis Server执行其他命令,因此,Functions的代码应执行的非常快,尽量避免在Functions中出现运行时间比较长的代码段。

下面我们以实例说明如何使用Redis Functions

我们前面已经说过,每一个Function都属于一个唯一的库(library)。加载(Loading)一个库进Redis数据库需要通过FUNCTION LOAD命令。这个命令将库的payload作为输入,这个输入的格式如下:

#!<engine name> name=<library name>

让我们看一个例子:

下面的例子是创建了一个library名字是mylib, 并且这个库有一个函数名字为myfunc, 这个函数的目的是返回它的第一个参数

例子1:

redis> FUNCTION LOAD "#!lua name=mylib

复制代码
                       redis.register_function('myfunc', function(keys, args) `                                               `return args[1] end)"mylib ---- 命令返回值
复制代码
这个命令的返回值是加载的库的名字,这里就是mylib
复制代码
我们可以通过FCALL命令调用在库mylib中注册的函数myfunc
复制代码
redis> FCALL myfunc 0 hello
复制代码
"hello"
复制代码
你们可以看到,返回值就是hello
复制代码
例子2:此外还有2个与FUNCTION LOAD相关的命令,FUNCTION LIST 与 FUNCTION DELETE
复制代码
redis> function list
复制代码
1) 1) "library_name"
复制代码
   2) "mylib"
复制代码
   3) "engine"
复制代码
   4) "LUA"
复制代码
   5) "functions"
复制代码
   6) 1) 1) "name"
复制代码
         2) "myfunc"
复制代码
         3) "description"
复制代码
         4) (nil)
复制代码
         5) "flags"
复制代码
         6) (empty array)
复制代码
例子3: 
复制代码
redis> FUNCTION DELETE mylib
复制代码
OK
复制代码
redis> FCALL myfunc 0
复制代码
(error) ERR Function not found
复制代码
以上3个命令的详细信息与如何具体的使用可以查看下面的连接:
复制代码
[FUNCTION LOAD \| Redis](https://redis.io/commands/function-load/ "FUNCTION LOAD | Redis")
复制代码
[FUNCTION LIST \| Redis](https://redis.io/commands/function-list/ "FUNCTION LIST | Redis")
复制代码
[FUNCTION DELETE \| Redis](https://redis.io/commands/function-delete/ "FUNCTION DELETE | Redis")
复制代码
你们可能已经注意到了,上面调用库中函数的命令是:
复制代码
redis> FCALL myfunc 0 hello
复制代码
"hello"
复制代码
在其中包括myfunc函数名和一个数字0. 这个数字表示后面的键的数目(the number of key names that follow it),在这个例子中,不包括任何的key,所以这里写做了0我们下面要讲解一个关于在Redis Functions中关于将key的名字作为参数和非key名字作为参数的区别为了让Redis Functions能够正确的执行,在function中所有的要访问的key的名字都必须明确地(explicitly)将这些key的名字作为输入参数;任何不是key名字的参数都将被视为普通的输入参数下面我们将会举一个例子进行说明:一个HSET的数据类型,我们想为每个这种数据类型的key存贮如下信息:HGETALL myhashkey1) "_last_modified_"2) "1654705366"3) "orange"4) "good"5) "apple"6) "perfect"7) "banada"8) "very good"除了3---8的货品信息,还包括一个1-2的最新的修改信息。我们可以先在一个Lua脚本文件mylib.lua中定义如下的库和函数
复制代码
#!lua name=mylib
复制代码
local function my_hset(keys, args)
复制代码
  local hash = keys\[1\]
复制代码
  local time = redis.call('TIME')\[1\]
复制代码
  return redis.call('HSET', hash, '_last_modified_', time, unpack(args))
复制代码
end
复制代码
redis.register_function('my_hset', my_hset)
复制代码
然后我们在命令行中运行如下命令:
复制代码
$ cat mylib.lua \| redis-cli -x FUNCTION LOAD REPLACE
复制代码
"mylib"
复制代码
然后当我们再运行如下FCALL命令时候,我们会得到如下的结果:
复制代码
redis> FCALL my_hset 1 myhash orange "good" apple "perfect" banada "very good"
复制代码
(integer) 3
复制代码
上面命令的my_hset是函数名,1代表第一个参数myhash是key名,后面的orange "good" apple "perfect" banada "very good" 都是这个key:myhash的field:value对
复制代码
好了,这篇文章就先介绍到这里,下次我们将接续介绍Redis Functions的其他高级特点
相关推荐
用户3169353811831 小时前
Java连接Redis
redis
倔强的石头_3 小时前
《Kingbase护城河》——数据库存储空间全景探测与精细化瘦身实战
数据库
冬奇Lab16 小时前
每日一个开源项目(第134篇):Zvec - 阿里开源的嵌入式向量数据库,向量搜索界的 SQLite
数据库·人工智能·llm
ClouGence1 天前
Oracle CDC 架构优化:从主库直连到 DataGuard 备库同步
数据库·后端·oracle
无响应de神1 天前
三、用户与权限管理
数据库·mysql
小小工匠2 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
麦聪聊数据2 天前
数据服务化时代:企业数据能力输出的核心路径
数据库
shushangyun_2 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
DARLING Zero two♡2 天前
【MySQL数据库】数据类型与表约束
数据库·mysql
曹牧2 天前
Oracle EXPLAIN PLAN
数据库·oracle