当前位置: 首页 > news >正文

Redis Functions 介绍(二)

首先,让我们先回顾一下上一篇讲的在Redis Functions中关于将key的名字作为参数和非key名字作为参数的区别,先看下面的例子

首先,我们先在一个Lua脚本文件mylib.lua中定义如下的库和函数

//--------------------mylib.lua 文件开始 ----------- //

#!lua name= mylib

local function my_hset(keys, args)

    local hash = keys[1]

    local time = redis.call('TIME')[1]     //这一行的目的是执行TIME命令得到当前的服务器时间

    return redis.call('HSET', hash, '_last_modified_', time, unpack(args))

end

redis.register_function('my_hset', my_hset)

//--------------------mylib.lua 文件结束 ----------- //

然后我们在命令行中运行如下命令:

$ cat mylib.lua | redis-cli -x FUNCTION LOAD

"mylib"

当我们再运行如下FCALL命令时候,我们会得到如下的结果:

redis> FCALL my_hset 1 myhash_key first_field "first value" second_field "second value"

(integer) 3

上面命令的my_hset是函数名,1代表第一个参数myhash_key是key名,后面的first_field "first value" second_field "second value" 都是这个key: myhash_key的field:value对

我们通过在Redis客户端运行 HGETALL myhash_key可以查看到相对应的结果:

redis> HGETALL myhash_key

1) "_last_modified_"

2) "1659536487"

3) "first_field"

4) "first value"

5) "second_field"

6) "second value"

好了,在复习完了上一篇Redis Functions的内容之后,我们可以看到上面的例子中mylib库中只包含了一个函数my_hset, 事实上在一个库中可以包括多个函数,在下面的例子中我们要添加另外2个function: my_hgetall  与 my_hlastmodified.

其中,函数my_hgetall相当于在redis 客户端执行hgetall命令,而my_hlastmodified函数返回的是传入的key中_last_modified这一个field的值

首先,让我们在mylib.lua中添加这两个function

local function my_hgetall(keys, args)

    local hash = keys[1]

    local res = redis.call('HGETALL', hash)

    return res

end

local function my_hlastmodified(keys, args)

    local hash = keys[1]

    return redis.call('HGET', keys[1], '_last_modified_')

end

然后,在mylib中注册这两个函数

redis.register_function('my_hgetall', my_hgetall)

redis.register_function('my_hlastmodified', my_hlastmodified)

因为我们要在mylib库中新增两个函数,所以我们需要运行如下的命令

$ cat mylib.lua | redis-cli -x FUNCTION LOAD REPLACE

"mylib"

接下来我们运行my_hgetall函数与my_hlastmodified

redis> FCALL my_hgetall 1 myhash_key

1) "_last_modified_"

2) "1659536487"

3) "first_field"

4) "first value"

5) "second_field"

6) "second value"

redis> FCALL my_hlastmodified 1 myhash_key

"1659536487"

最后我们可以通过FUNCTION LIST命令来查看当前所有的Redis Function的库及其包含的函数信息。下面我们来查看一下当前库mylib中包括的3个function的信息

127.0.0.1:6381> FUNCTION list

1) 1) "library_name"

   2) "mylib"

   3) "engine"

   4) "LUA"

   5) "functions"

   6) 1) 1) "name"

         2) "my_hset"

         3) "description"

         4) (nil)

         5) "flags"

         6) (empty array)

      2) 1) "name"

         2) "my_hlastmodified"

         3) "description"

         4) (nil)

         5) "flags"

         6) (empty array)

      3) 1) "name"

         2) "my_hgetall"

         3) "description"

         4) (nil)

         5) "flags"

         6) (empty array)

在Redis的官方文档中,我们发现我们可以在库中定义一个function供库中的其他函数使用,在官方的使用说明,它给出了一个例子用于错误检测。我们下面来看看这个例子

定义一个check_keys的函数,用来检测客户端调用的redis function的函数输入的key是否存在并且只有一个

local function check_keys(keys)

    local error = nil

    local nkeys = table.getn(keys)

    if nkeys == 0 then

        error = 'Hash key name not provided'

    elseif nkeys > 1 then

        error = 'Only one key name is allowed'

    end

    if error ~= nil then

        redis.log(redis.LOG_WARNING, error);

        return redis.error_reply(error)

     end

     return nil

end

相应的,我们也需要修改已经有的3个函数,让他们去调用新增的check_keys函数

local function my_hset(keys, args)

    local error = check_keys(keys)

    if error ~= nil then

        return error

    end

    local hash = keys[1]

    local time = redis.call('TIME')[1]

    return redis.call('HSET', hash, '_last_modified_', time, unpack(args))

end

local function my_hgetall(keys, args)

    local error = check_keys(keys)

    if error ~= nil then

        return error

    end

    local hash = keys[1]

    local res = redis.call('HGETALL', hash)

    return res

end

local function my_hlastmodified(keys, args)

     local error = check_keys(keys)

     if error ~= nil then

         return error

     end

     local hash = keys[1]

     return redis.call('HGET', keys[1], '_last_modified_')

end

这里要注意一点,在上面地例子中,如果我们运行FCALL:

redis> FCALL my_hgetall 1 myhash_key

1) "_last_modified_"

2) "1659536487"

3) "first_field"

4) "first value"

5) "second_field"

6) "second value"

我们可以看到运行是正常地,但是如果我们运行FCALL_RO:

redis> FCALL_RO my_hgetall 1 myhash_key

(error) ERR Can not execute a script with write flag using *_ro command.

我们会收到一个错误。这是为什么呢?

事实上,函数my_hgetall的目的只是从数据中读取数据,并没有写操作。但是当我们定义它的时候,并没有标注它是只读属性

local function my_hgetall(keys, args)

    local hash = keys[1]

    local res = redis.call('HGETALL', hash)

    return res

end

所以这个时候,当我们用命令FCALL_RO就会返回一个错误:Can not execute a script with write flag using *_ro command

所以为了可以让FCALL_RO执行一个只读属性的函数,我们需要对my_hgetall的注册方式进行一下修改:

redis.register_function{

    function_name='my_hgetall',

    callback=my_hgetall,

    flags={ 'no-writes' }

}

这个时候,我们再运行FCALL_RO命令时候,我们就会得到正确的结果了

redis> FCALL_RO my_hgetall 1 myhash_key

1) "_last_modified_"

2) "1659536487"

3) "first_field"

4) "first value"

5) "second_field"

6) "second value"

下面我们来看看Redis functions是如何在集群中运行的

在非集群状态时候,如果有主从节点,那么主节点上的function会自动地被复制到从节点,这与function创建地初衷也是一致地:Redis认为Functions是数据库的一部分,是可以持久化的,并且也是可以复制的。

但是,如果function是存在于集群的几点中,那么就有一些不一样的特性了。Redis function无法被自动地加载到集群中地所有节点,而需要被管理员手动地将function加载到集群中地每个节点中。要加载Redis function在集群中地节点,可以运行如下地命令:

redis-cli --cluster-only-masters --cluster call host:port FUNCTION LOAD [REPLACE] function-code

如果运行命令:

redis-cli --cluster add-node

那么这个时候集群中已经存在的节点会将已经加载地function自动地传播到新加入集训地节点

使用Redis Function的其他的注意事项

如果一个已经加载Redis Function的节点需要重启,那么在重启之前建议先运行命令:

redis-cli --functions-rdb

这样会将已经存在于节点上的Redis function存到一个RDB文件中,当这个节点重启之后可以直接加载这个rdb文件,就不需要再手工加载每一个function了,大大地节省了时间和减少错误机率

本篇文章引用了部分Redis官方文档的例子, 大家可以从链接去查看和运行一下。

https://redis.io/docs/interact/programmability/functions-intro/

下一篇博客我们开始分析Redis function的源码,让我们深入探讨一下这个Redis新特性内部是如何执行,欢迎继续关注Redis Functions系列博客

最后,感谢Redis社区的所有贡献者的努力工作,及所有对Redis感兴趣的开发者的支持

相关文章:

Redis Functions 介绍(二)

首先,让我们先回顾一下上一篇讲的在Redis Functions中关于将key的名字作为参数和非key名字作为参数的区别,先看下面的例子 首先,我们先在一个Lua脚本文件mylib.lua中定义如下的库和函数 //--------------------mylib.lua 文件开始 --------…...

R语言环境下使用curl库做的爬虫代码示例

curl库是一个用于传输数据的工具和库,它支持多种协议,包括HTTP、FTP、SMTP等。在爬虫中,curl库可以用来获取网页内容,从而实现爬取网页的功能。通过设置curl的选项,可以实现对网页的请求、响应、重定向等操作。在使用c…...

【论文阅读】Equivariant Contrastive Learning for Sequential Recommendation

【论文阅读】Equivariant Contrastive Learning for Sequential Recommendation 文章目录 【论文阅读】Equivariant Contrastive Learning for Sequential Recommendation1. 来源2. 介绍3. 前置工作3.1 序列推荐的目标3.2 数据增强策略3.3 序列推荐的不变对比学习 4. 方法介绍4…...

智行破晓,驭未来航程!——经纬恒润智能驾驶数据闭环云平台OrienLink重磅来袭

2023是被AI技术标记的⼀年。年初,OpenAI的GPT崭露头角;6月,Tesla在CVPR2023上对World Model进行深度解读;8月,SIGGRAPH见证GH200、L40S显卡和ChatUSD的登场,FSD V12彰显端到端智能驾驶的实力;9月…...

深入理解WPF中的依赖注入和控制反转

在WPF开发中,依赖注入(Dependency Injection)和控制反转(Inversion of Control)是程序解耦的关键,在当今软件工程中占有举足轻重的地位,两者之间有着密不可分的联系。今天就以一个简单的小例子&…...

【CIO人物展】国家能源集团信息技术主管王爱军:中国企业数智化转型升级的内在驱动力...

王爱军 本文由国家能源集团信息技术主管王爱军投递并参与《2023中国数智化转型升级优秀CIO》榜单/奖项评选。丨推荐企业—锐捷网络 大数据产业创新服务媒体 ——聚焦数据 改变商业 随着全球信息化和网络化的进程日益加速,数字化转型已经成为当下各大企业追求的核心…...

(后续补充)vue+express、gitee pm2部署轻量服务器

首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 首先 防火墙全部关闭算了 关闭防火墙 systemctl stop firewalld 重新载入防火墙使设置生效 firewall-cmd --reload 后端的 pm2.config.cjs …...

第G7周:Semi-Supervised GAN 理论与实战

🍨 本文为🔗365天深度学习训练营 中的学习记录博客 🍦 参考文章:365天深度学习训练营-第G7周:Semi-Supervised GAN 理论与实战(训练营内部成员可读) 🍖 原作者:K同学啊|接…...

美国Embarcadero产品经理Marco Cantù谈Delphi/C++ Builder目前开发应用领域

美国Embarcadero产品经理Marco Cant 日前在欧洲的一次信息技术会议上谈到了Delphi/C Builder目前开发应用领域:RAD Studio Delphi/C Builder目前应用于哪些开发领域?使用 Delphi 和 CBuilder 进行开发为当今众多企业提供了动力。 航空航天 大型数据采集 …...

【iOS】——知乎日报第三周总结

文章目录 一、获取新闻额外信息二、工具栏按钮的布局三、评论区文字高度四、评论区长评论和短评论的数目显示五、评论区的cell布局问题和评论消息的判断 一、获取新闻额外信息 新闻额外信息的URL需要通过当前新闻的id来获取,所以我将所有的新闻放到一个数组中&…...

leetcode每日一题-周复盘

前言 该系列文章用于我对一周中leetcode每日一题or其他不会的题的复盘总结。 一方面用于自己加深印象,另一方面也希望能对读者的算法能力有所帮助。 该复盘对我来说比较容易的题我会复盘的比较粗糙,反之较为细致 解答语言:Golang 周一&a…...

[NLP] LlaMa2模型运行在Mac机器

本文将介绍如何使用llama.cpp在MacBook Pro本地部署运行量化版本的Llama2模型推理,并基于LangChain在本地构建一个简单的文档Q&A应用。本文实验环境为Apple M1 芯片 8GB内存。 Llama2和llama.cpp Llama2是Meta AI开发的Llama大语言模型的迭代版本,…...

基于若依的ruoyi-nbcio流程管理系统增加仿钉钉流程设计(六)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 这节主要讲条件节点与并发节点的有效性检查,主要是增加这两个节点的子节点检查,因为…...

听GPT 讲Rust源代码--library/std(15)

题图来自 An In-Depth Comparison of Rust and C[1] File: rust/library/std/src/os/wasi/io/fd.rs 文件路径:rust/library/std/src/os/wasi/io/fd.rs 该文件的作用是实现与文件描述符(File Descriptor)相关的操作,具体包括打开文…...

腾讯云CVM服务器操作系统镜像大全

腾讯云CVM服务器的公共镜像是由腾讯云官方提供的镜像,公共镜像包含基础操作系统和腾讯云提供的初始化组件,公共镜像分为Windows和Linux两大类操作系统,如TencentOS Server、Windows Server、OpenCloudOS、CentOS Stream、CentOS、Ubuntu、Deb…...

Mxnet框架使用

目录 1.mxnet推理API 2.MXNET模型转ONNX 3.运行示例 1.mxnet推理API # 导入 MXNet 深度学习框架 import mxnet as mx if __name__ __main__:# 指定预训练模型的 JSON 文件json_file resnext50_32x4d # 指定模型的参数文件params_file resnext50_32x4d-0000.params # 使…...

每个程序员都应该自己写一个的:socket包装类

每个程序员都应该有自己的网络类。 下面是我自己用的socket类,支持所有我自己常用的功能,支持windows和unix/linux。 目录 客户端 服务端 非阻塞 获取socket信息 完整代码 客户端 作为socket客户端,只需要如下几个功能: //…...

JMeter:断言之响应断言

一、断言的定义 断言用于验证取样器请求或对应的响应数据是否返回了期望的结果。可以是看成验证测试是否预期的方法。 对于接口测试来说,就是测试Request/Response,断言即可以针对Request进行,也可以针对Response进行。但大部分是对Respons…...

RLHF的替代算法之DPO原理解析:从Zephyr的DPO到Claude的RAILF

前言 本文的成就是一个点顺着一个点而来的,成文过程颇有意思 首先,如上文所说,我司正在做三大LLM项目,其中一个是论文审稿GPT第二版,在模型选型的时候,关注到了Mistral 7B(其背后的公司Mistral AI号称欧洲…...

U盘显示无媒体怎么办?方法很简单

当出现U盘无媒体情况时,您可以在磁盘管理工具中看到一个空白的磁盘框,并且在文件资源管理器中不会显示出来。那么,导致这种问题的原因是什么呢?我们又该怎么解决呢? 导致U盘无媒体的原因是什么? 当您遇到上…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

基于服务器使用 apt 安装、配置 Nginx

🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...