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的其他高级特点
相关推荐
Ai 编码助手5 小时前
MySQL中distinct与group by之间的性能进行比较
数据库·mysql
陈燚_重生之又为程序员5 小时前
基于梧桐数据库的实时数据分析解决方案
数据库·数据挖掘·数据分析
caridle5 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
白云如幻5 小时前
MySQL排序查询
数据库·mysql
萧鼎5 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
^velpro^5 小时前
数据库连接池的创建
java·开发语言·数据库
荒川之神6 小时前
ORACLE _11G_R2_ASM 常用命令
数据库·oracle
IT培训中心-竺老师6 小时前
Oracle 23AI创建示例库
数据库·oracle
小白学大数据6 小时前
JavaScript重定向对网络爬虫的影响及处理
开发语言·javascript·数据库·爬虫
time never ceases6 小时前
使用docker方式进行Oracle数据库的物理迁移(helowin/oracle_11g)
数据库·docker·oracle