Spring Boot集成Redis + Lua脚本实现原子性操作:小白入门指南

发布于:2025-02-24 ⋅ 阅读:(12) ⋅ 点赞:(0)

Spring Boot集成Redis + Lua脚本实现原子性操作:小白入门指南

一、为什么需要Lua脚本?

在分布式系统中,多个Redis命令的组合操作(如先查询后修改)可能因网络延迟、并发竞争导致数据不一致。Lua脚本可以将多个命令封装为一个原子操作,确保所有命令要么全部成功,要么全部失败,避免中间状态
优势

  • 原子性:Redis单线程执行Lua脚本,执行期间不会被其他操作打断
  • 减少网络开销:多个命令合并为一次请求

2. Lua脚本中 redis.callredis.pcall 的区别

  • redis.call:在执行 Redis 命令时,如果发生错误会抛出异常并终止脚本执行。
  • redis.pcall:在执行 Redis 命令时,即使发生错误也不会抛出异常,而是返回一个包含错误信息的表,脚本会继续执行

3. 在不同数据类型中的应用

1. String 类型
操作 Lua 脚本示例 参数说明 返回值
设置值 redis.call('SET', KEYS[1], ARGV[1]) KEYS[1]: key “OK”
获取值 redis.call('GET', KEYS[1]) KEYS[1]: key String 或 nil(不存在时)
自增 redis.call('INCR', KEYS[1]) KEYS[1]: key 新整数(若 key 不存在则初始化为 1)
带过期时间设置 redis.call('SETEX', KEYS[1], ARGV[1], ARGV[2]) ARGV[1]: 秒,ARGV[2]: 值 “OK”
2. Hash 类型
操作 Lua 脚本示例 参数说明 返回值
设置字段值 redis.call('HSET', KEYS[1], ARGV[1], ARGV[2]) ARGV[1]: 字段名 1(新增)或 0(更新)
获取字段值 redis.call('HGET', KEYS[1], ARGV[1]) ARGV[1]: 字段名 String 或 nil
获取所有字段 redis.call('HGETALL', KEYS[1]) KEYS[1]: key Table(交替字段名和值)
删除字段 redis.call('HDEL', KEYS[1], ARGV[1]) ARGV[1]: 字段名 删除的字段数量
3. List 类型
操作 Lua 脚本示例 参数说明 返回值
左/右插入元素 redis.call('LPUSH', KEYS[1], ARGV[1]) ARGV[1]: 元素值 列表长度
获取范围元素 redis.call('LRANGE', KEYS[1], ARGV[1], ARGV[2]) ARGV[1]: 起始索引(0-based) Table(元素列表)
弹出元素 redis.call('LPOP', KEYS[1]) - 元素值或 nil(空列表时)
4. Set 类型
操作 Lua 脚本示例 参数说明 返回值
添加元素 redis.call('SADD', KEYS[1], ARGV[1]) ARGV[1]: 元素值 新增元素数量
判断元素存在 redis.call('SISMEMBER', KEYS[1], ARGV[1]) ARGV[1]: 元素值 1(存在)或 0(不存在)
获取所有元素 redis.call('SMEMBERS', KEYS[1]) KEYS[1]: key Table(无序元素列表)
5. ZSet(有序集合)
操作 Lua 脚本示例 参数说明 返回值
添加带分数元素 redis.call('ZADD', KEYS[1], ARGV[1], ARGV[2]) ARGV[1]: 分数,ARGV[2]: 元素 新增元素数量
获取分数范围元素 redis.call('ZRANGEBYSCORE', KEYS[1], ARGV[1], ARGV[2]) ARGV[1]: 最小分数,ARGV[2]: 最大分数 Table(元素列表)
获取排名 redis.call('ZRANK', KEYS[1], ARGV[1]) ARGV[1]: 元素值 排名(从 0 开始)或 nil
6. 通用操作
操作 Lua 脚本示例 参数说明 返回值
判断 Key 是否存在 redis.call('EXISTS', KEYS[1]) KEYS[1]: key 1(存在)或 0(不存在)
设置过期时间 redis.call('EXPIRE', KEYS[1], ARGV[1]) ARGV[1]: 秒数 1(成功)或 0(Key 不存在)
删除 Key redis.call('DEL', KEYS[1]) KEYS[1]: key 删除的 Key 数量