springboot整合redis+lua实现getdel操作保证原子性

  1. 原始代码

脚本逻辑先获取redis的值,判断是否等于期望值。 条件成立则删除,不成立则返回0

Lua 复制代码
if redis.call('get', KEYS[1]) == ARGV[1] then
    return redis.call('del', KEYS[1])
end
return 0
  1. 测试代码

根据上面的逻辑加了测试, 在判断成功后等待5秒后执行删除操作。同时开启另外一个线程去修改这个key的值, 发现修改的线程一直阻塞。直到等待的线程5秒结束后且完成删除操作后,修改的线程才会执行。

原因:

redis是单线程执行,

Redis会将整个Lua脚本作为一个原子操作执行,这意味着脚本中的多个命令要么全部执行成功,要么全部失败。这有助于维护数据的原子性和一致性。

Redis执行Lua脚本时,它会自动锁定相关的键,以防止其他客户端对这些键进行并发修改。这确保了在脚本执行期间对键的访问是互斥的。

注意: 如果脚本中涉及多个key的操作并redis部署的是cluster模式时, 需要额外确认多个key都在一个slot中。还好我这就1个key!!!略过.............

java 复制代码
String str_script =
            // 1. 判断key的值是否等于期望值,等于则进行删除,不相等则直接结束
            "if (redis.call('get', KEYS[1]) == ARGV[1]) then\n" +
            "    local start = redis.call('TIME')[1] * 1000 + redis.call('TIME')[2] / 1000\n" +
            "    while (redis.call('TIME')[1] * 1000 + redis.call('TIME')[2] / 1000 - start) < 5000 do\n" +
            "        print('等待5秒结束.....')"+
            "    end\n"+
            // 2. 值判断成功,等待5秒执行删除操作
            "    return redis.call('del', KEYS[1])\n" +
            "end\n" +
            "return 0";
    public String getAndDelete(String key, String expectedValue) {
        log.info("start..................");
        DefaultRedisScript script = new DefaultRedisScript(str_script, Long.class);
        Object res = redisTemplate.execute(script, Collections.singletonList(key), expectedValue);
        log.info("end..................");
        return res.toString();
    }
相关推荐
MrSYJ15 分钟前
学完涨工资的技巧2:Spring Authorization Server如何签发JWTToken
java·spring boot·微服务
阿巴~阿巴~19 分钟前
Redis重大版本演进全解析:从2.6到7.0
服务器·数据库·redis·ubuntu·缓存·centos
摇滚侠1 小时前
Spring Boot 3零基础教程,yml语法细节,笔记16
java·spring boot·笔记
RunningShare1 小时前
高可用架构实战:SpringBoot+MongoDB构建AI原生应用
spring boot·mongodb·架构
ajsbxi2 小时前
【Redis】缓存读/写操作流程
redis·笔记·spring·缓存·bootstrap
艾菜籽3 小时前
SpringMVC练习:加法计算器与登录
java·spring boot·spring·mvc
LawsonJin4 小时前
springboot实现微信小程序支付(服务商和普通商户模式)
spring boot·后端·微信小程序
optimistic_chen4 小时前
【Java EE进阶 --- SpringBoot】Mybatis操作数据库(基础二)
xml·数据库·spring boot·笔记·java-ee·mybatis
泉城老铁4 小时前
tomcat 部署springboot,线程经常断开导致数据库连接池关闭,如何解决
java·spring boot·后端
thginWalker5 小时前
使用Spring Boot构建多维度配置层
spring boot