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的其他高级特点
相关推荐
AndyHeee6 分钟前
【瑞芯微rk3576刷ubuntu根文件系统容量不足问题解决】
linux·数据库·ubuntu
李昊哲小课7 分钟前
Ubuntu 24.04 在线安装 Redis 8.x 完整教程
linux·redis·ubuntu
李宥小哥15 分钟前
SQLite03-数据库管理
数据库
『六哥』28 分钟前
MySQL 版本安装教程
数据库·mysql
AC赳赳老秦38 分钟前
工业互联网赋能智造:DeepSeek解析产线传感器数据驱动质量管控新范式
前端·数据库·人工智能·zookeeper·json·flume·deepseek
小北方城市网1 小时前
第 10 课:Python 全体系实战整合与职业进阶指南(完结篇)
大数据·开发语言·数据库·python
韩立学长1 小时前
基于Springboot建筑物保护可视化系统rk6tni53(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
量化风云1 小时前
2026量化新基建(二) - sqlite 与 sqlite-utils
数据库·python·sqlite·量化交易·量化交易课程
Element_南笙1 小时前
BUG:ModuleNotFoundError: No module named ‘milvus_lite‘
java·服务器·数据库
code tsunami2 小时前
如何将 Helium 与 CapSolver 集成,实现无缝 CAPTCHA 自动化解决
运维·数据库·人工智能·爬虫·python·自动化