redis执行lua脚本

redis执行lua脚本

文档

  1. redis单机安装
  2. redis常用的五种数据类型
  3. springboot整合redis-RedisTemplate单机模式
  4. 布隆过滤器 -Bloom Filter

官方文档

  1. 官网操作命令指南页面:https://redis.io/docs/latest/commands/?name=get&group=string
  2. Redis cluster specification
  3. Distributed Locks with Redis

说明

  1. redis版本:7.0.0
  2. springboot版本:3.2.0

redis执行lua脚本

安装单机版redis
  1. 安装单机版redis参考文档:redis单机安装
编写lua脚本
  1. 在 Redis 中原子地尝试给 key 设值并设置过期时间,成功返回 1,失败(key 已存在)返回 0,用作分布式加锁。

  2. 编写一个lua脚本,为指定的 key 设置一个值并同时设置毫秒级过期时间,成功则返回 1,失败则返回 0。

  3. 脚本示例

    javascript 复制代码
    -- KEYS[1]  : 锁的 key
    -- ARGV[1]  : 锁的唯一标识
    -- ARGV[2]  : 过期时间(毫秒)
    -- 第一步:只有在 key 不存在时才设置值,相当于 SET key value NX
    
    if redis.call('SETNX', KEYS[1], ARGV[1]) == 1 then
      -- 第二步:设置过期时间,相当于 PX ttl
      redis.call('PEXPIRE', KEYS[1], ARGV[2])
      return 1       -- 加锁成功
    else
      return 0       -- 加锁失败(已有锁)
    end
  4. 简化成一行,保存为脚本文件tryLock.lua

    javascript 复制代码
    if redis.call('SETNX', KEYS[1], ARGV[1]) == 1 then redis.call('PEXPIRE', KEYS[1], ARGV[2]); return 1 else return 0 end
  5. 什么是KEYSARGV

    1. KEYS是一个数组,存放"所有 key 名"
    2. ARGV是一个数组,存放"所有非 key 的参数"
  6. 为什么区分KEYSARGV

    1. 技术上"都用 ARGV"在单机上多数能跑,但违反规范且在集群/路由/工具支持上会出问题
    2. Redis 之所以设计区分 KEYSARGV,就是为了让服务器明确知道哪些参数是 key,用于槽位路由、读写保护和各种内部/客户端工具对 key 的正确识别与处理。
lua脚本常见用法
  1. 常见用法是使用eval命令,传入lua脚本字符及参数,格式如下

    shell 复制代码
    EVAL script numkeys key [key ...] arg [arg ...]
    • script:Lua 脚本内容(字符串)
    • numkeys:后面有多少个 key
    • key [key ...]:传给脚本的 key 列表(用 KEYS[i] 访问)
    • arg [arg ...]:传给脚本的参数列表(用 ARGV[i] 访问)
  2. 示例,执行lua脚本

    shell 复制代码
    127.0.0.1:6379> EVAL "if redis.call('SETNX', KEYS[1], ARGV[1]) == 1 then redis.call('PEXPIRE', KEYS[1], ARGV[2]); return 1 else return 0 end" 1 myLockKey lockValue 30000
    (integer) 1
    • 1:有 1 个 key
    • myLockKeyKEYS[1]
    • lockValueARGV[1]
    • 30000ARGV[2](过期时间,毫秒)
加载lua脚本到内存
  1. 将lua脚本加载到内存中

    shell 复制代码
    127.0.0.1:6379> SCRIPT LOAD "if redis.call('SETNX', KEYS[1], ARGV[1]) == 1 then redis.call('PEXPIRE', KEYS[1], ARGV[2]); return 1 else return 0 end"
    "9aab773b2f1a82e88fcb760f3c42bbd9b9d3b1c3"
    • 返回值是一个 SHA1,使用EVALSHA 命令时会用到
    • 用同一段脚本内容再执行一次SCRIPT LOAD,会得到同一个 SHA
  2. 把 Lua 脚本加载到内存的作用

    核心作用:为了后面可以用 EVALSHA 复用脚本,减少网络传输和解析开销。

    • 性能更好:
      • 第一次用 SCRIPT LOAD 把脚本送到 Redis,服务器记住脚本内容和它的 SHA1。
      • 后面每次只发一个短短的 SHA1(EVALSHA ...),不用再把整段 Lua 文本发过去,也不用每次重新解析脚本。
    • 避免重复发送脚本:
      • 对于固定的业务脚本(比如分布式锁、库存扣减),脚本内容都是不变的,加载一次后就可以被很多次复用。
    • 方便客户端封装:
      • 客户端可以在启动时统一 SCRIPT LOAD 一批脚本,以 SHA1 为 ID 管理它们,调用时只用 EVALSHA 即可。
  3. 在shell中,可以通过读取lua脚本文件内容的方式将lua脚本加载到内存

    shell 复制代码
    cd /opt/module/redis/bin
    ./redis-cli -a 123456 SCRIPT LOAD "$(cat ../lua-data/tryLock.lua)"
    • 这种方式只能在 shell 中用 redis-cli 执行,不能在 redis-cli 里直接执行
检查lua脚本是否已加载
  1. 检查lua脚本是否已加载,实际上是检查lua脚本加载后返回的 SHA1是否存在

  2. 命令示例

    shell 复制代码
    127.0.0.1:6379> SCRIPT EXISTS 9aab773b2f1a82e88fcb760f3c42bbd9b9d3b1c3
    1) (integer) 1
    • 如果返回 1,表示已加载
    • 如果返回 0,表示这个 SHA 对应的脚本当前没在内存中
执行lua脚本
  1. 脚本先加载到内存:SCRIPT LOAD ,得到SHA值,用EVALSHA执行这个SHA值

    shell 复制代码
    127.0.0.1:6379> EVALSHA 9aab773b2f1a82e88fcb760f3c42bbd9b9d3b1c3 1 myLockKey lockValue 30000
    (integer) 1
  2. 直接执行脚本字符串:EVAL,这也是常见的用法

    shell 复制代码
    127.0.0.1:6379> EVAL "if redis.call('SETNX', KEYS[1], ARGV[1]) == 1 then redis.call('PEXPIRE', KEYS[1], ARGV[2]); return 1 else return 0 end" 1 myLockKey lockValue 30000
    (integer) 1
  3. 在shell中,通过脚本文件执行:redis-cli --eval tryLock.lua

    shell 复制代码
    ./redis-cli -a 123456 --eval ../lua-data/tryLock.lua myLockKey , lockValue 30000
    • 逗号前是 KEYS,逗号后是 ARGV

参考资料

  1. https://www.bilibili.com/video/BV13R4y1v7sP

注意事项

  1. 部分内容由AI生成
  2. 如有不对,欢迎指正!!!
相关推荐
入瘾4 小时前
etcd 显示连接失败
数据库·chrome·etcd
会飞的大可4 小时前
Redis Sentinel 高可用方案在WMS仓储管理系统的应用
redis·sentinel
本体智能4 小时前
预制指标、宽表、SQL、本体ABC:真正决定长期成本的,是一次变更会波及多少层
数据库·sql·本体神经网络·uino数据智能引擎
长安11084 小时前
数据库基础知识----数据库大观
数据库·oracle
小羊在睡觉4 小时前
Reids缓存穿透、击穿、雪崩
redis·缓存·go
瀚高PG实验室5 小时前
使用hgdbdeveloper开发工具导出数据后在异机恢复时报错
数据库·瀚高数据库
百结2146 小时前
PostgreSQL 初体验
数据库·postgresql
ward RINL6 小时前
Redis 安装及配置教程(Windows)【安装】
数据库·windows·redis
bingHHB7 小时前
金蝶云星空旗舰版 × 赛狐ERP:亚马逊卖家业财一体化的最后一公里
运维·数据库·集成学习
Nontee8 小时前
Redis高可用架构解析
数据库·redis·架构