• 【愚公系列】2022年11月 Redis数据库-Lua脚本的使用



    前言

    Lua 由标准 C 编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以编译,运行。

    Lua脚本是一个很轻量级的脚本,也是号称性能最高的脚本,用在很多需要性能的地方,比如:游戏脚本,nginx,wireshark的脚本。

    Redis实例支持Lua相关命令,通过Lua脚本可高效地处理CAS(check-and-set)命令,进一步提升Redis的性能,同时可以轻松实现以前较难实现或者不能高效实现的模式。Lua语言编写脚本传到Redis中执行,在Lua脚本中也可以调用大部分的Redis命令。使用脚本有以下三个好处:

    • 减少网络开销:有些时候需要多次请求Redis获取处理数据,而使用脚本功能就可以只使用一次请求完成相同操作,减少了网络往返时延。
    • 原子操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。也就是说在编写脚本的过程中无须担心会出现竞态条件,也就是无须使用事务。事务可以完成的所有功能,都可以用脚本来完成。
    • 复用:客户端发送的脚本会永久存储在Redis中,这就意味着其他客户端(可以是其他语言开发的项目)可以复用这一脚本而不需要使用代码完成同样的逻辑。

    一、Lua脚本的使用

    Redis调用Lua的方式主要又如下几种

    1.EVAL命令

    EVAL的命令格式如下:

    EVAL script numkeys key [key ...] arg [arg ...]
    
    • 1

    字段说明:

    • script:脚本内容。
    • numkeys:key参数的数量。
    • key和arg:这两个参数向脚本传递数据,它们的值可以在脚本中分别使用KEYS[index]和ARGV[index]两个表类型的全局变量访问,numkeys为key的数量和其索引的最大值,argv的索引为key和argv数量总和减去numkeys,它们的索引都是从1开始,超出则返回nil。
    PS C:\Users\Happy\devTools\Redis-x64-3.2.100> redis-cli
    127.0.0.1:6379> EVAL "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
    1) "key1"
    2) "key2"
    3) "first"
    4) "second"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    2.Evalsha命令

    EVAL的命令格式如下:

    EVALSHA sha1 numkeys key [key ...] arg [arg ...] 
    
    • 1

    字段说明:

    • sha1 : 通过 SCRIPT LOAD 生成的 sha1 校验码。
    • numkeys: 用于指定键名参数的个数。
    • key [key …]: 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key),这些键名参数可以在 Lua 中通过全局变量 KEYS 数组,用 1 为基址的形式访问( KEYS[1] , KEYS[2] ,以此类推)。
    • arg [arg …]: 附加参数,在 Lua 中通过全局变量 ARGV 数组访问,访问的形式和 KEYS 变量类似( ARGV[1] 、 ARGV[2] ,诸如此类)。
    127.0.0.1:6379> SCRIPT LOAD "return 'hello moto'"
    "232fd51614574cf0867b83d384a5e898cfd24e5a"
    127.0.0.1:6379> EVALSHA "232fd51614574cf0867b83d384a5e898cfd24e5a" 0
    "hello moto"
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    3.SCRIPT命令

    • SCRIPT LOAD script:将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。
    • SCRIPT EXISTS script [script …]:查看指定的脚本是否已经被保存在缓存当中。
    • SCRIPT FLUSH:从脚本缓存中移除所有脚本。
    • SCRIPT KILL:杀死当前正在运行的 Lua 脚本。如果当前执行的脚本对Redis的数据进行了修改,则SCRIPT KILL不会终止脚本的运行,因为这样违背了原子性。
    • SHUTDOWN NOSAVE:强制终止Redis将原先脚本的修改操作返回,不进行持久化操作,这意味着所有发送在上一次的快照后的数据库修改都会丢失。

    二、Lua脚本的返回值

    很多情况下,都需要脚本通过return返回值,如果没有执行return则默认返回nil。因为我们可以像调用其他Redis内置命令一样调用我们自己写的脚本,所以同样Redis会自动将脚本返回值的Lua数据类型转化成Redis的返回值类型。具体的转换规则如下:

    1、Lua的数字类型,Redis为整数类型。

    127.0.0.1:6379> eval 'return 1.1' 0
    (integer) 1
    
    • 1
    • 2

    2、Lua的字符串类型,Redis也是字符串类型

    3、 Lua的表类型(数组形式),Redis会返回多行字符串

    127.0.0.1:6379> eval 'return {0,1}' 0
    1) (integer) 0
    2) (integer) 1
    
    • 1
    • 2
    • 3

    4、 Lua表类型(只有一个ok字段存储状态信息),Redis为成功状态回复

    127.0.0.1:6379> eval 'return {ok="this is ok"}' 0
    this is ok
    
    • 1
    • 2

    5、Lua表类型(只有一个err字段存储状态信息),Redis为错误状态回复

    127.0.0.1:6379> eval 'return {err="so bad"}' 0
    (error) so bad
    
    • 1
    • 2

    6、Lua的bool类型中true为Redis的1,false为nil

    127.0.0.1:6379> eval 'return true' 0
    (integer) 1
    127.0.0.1:6379> eval 'return false' 0
    (nil)
    
    • 1
    • 2
    • 3
    • 4

    注意

    Redis脚本禁止使用Lua标准库中与文件或系统调用相关的函数,在脚本中只允许对Redis的数据进行处理。并且Redis还通过禁用脚本的全局变量的方式保证每个脚本都是相对隔离的,不会互相干扰。

  • 相关阅读:
    滚雪球学Java(26):Java进制转换
    我和谷歌共成长——前端必备插件Vue.js devtools
    【设计模式】Java设计模式 - 桥接模式
    linux排查java进程占用CPU过高原因方法
    Windows11搭建kafka-python环境
    基于Java Web的云端学习系统的设计与实现
    【集群迁移】使用Shell脚本获取老集群整个Hive库的建库、建表DDL
    leetcode309最佳买卖股票时机含冷冻期刷题打卡
    查看静态库.a编译时支持的CPU架构
    华为“天才少年” DIY 生日礼物:四个月打造能缝葡萄的机械臂!
  • 原文地址:https://blog.csdn.net/aa2528877987/article/details/127818462