Rdis使用lua脚本的作用、使用案例、保证原子性的原理、存在的问题和解决方法

借鉴:https://blog.csdn.net/qq_38787653/article/details/118619734

一:Rdis使用lua脚本的作用

  1. 减少网络开销,在Lua脚本中可以把多个命令放在同一个脚本中运行
  2. 原子操作,redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。换句话说,编写脚本的过程中无需担心会出现竞态条件
  3. 复用性,客户端发送的脚本会永远存储在redis中,这意味着其他客户端可以复用这一脚本来完成同样的逻辑

二:使用的案例

1.根据业务编写lua脚本 XX.lua

local current = redis.call('GET', KEYS[1])
if (current == ARGV[1]) then
    redis.call('SET', KEYS[1], ARGV[2])
    redis.call('EXPIRE', KEYS[1], ARGV[3])
    return true
end
return false

Lua可以使用redis.call和redis.pcall函数实现对Redis的调用,redis.call和 redis.pcall的不同在于:
如果redis.call执行失败,那么脚本执行结束会直接返 回错误
而redis.pcall会忽略错误继续执行脚本

2.实例化

@Configuration
public class RedisLuaScriptConfig {
 
    /**
     * 实例化lua 脚本  cas 操作
     */
    @Bean
    public RedisScript<Boolean> compereAndSetAndExpire() {
        return RedisScript.of(new ClassPathResource("redis/compereAndSetAndExpire.lua"), Boolean.class);
    }
}

3.调用

public class XX{    
    @Resource(name = "compereAndSetAndExpire")
    RedisScript<Boolean> compereAndSetAndExpire;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    public void XX {
         // 1脚本,2, key  3, 期望值, 4, 要设置值 5过期时长 单位秒
         Boolean red = Optional.ofNullable(redisTemplate.execute(compereAndSetAndExpire, Lists.newArrayList(key), "8", "10",60000)).orElse(false);
     }
}

三:保证原子性的原理

  1. 一个lua 脚本会锁住整个 redis-server ,其他所有 redis-client (包括命令行 jedis lettuce redission) 此时都无法的对 redis-server 发送命令 (证明方法:lua脚本写一个死循环,其他各种各样的redis客户端就连不上了,因为redis是单线程处理客户端请求) :缺点就是影响性能

四:存在的问题和解决方法

问题:脚本随便是一次性给redis执行,但是还是一条一条命令执行的,某个命令还是可能执行失败

解决方法:可以执行脚本之前,先获取到redis中key对应的值。如果执行脚本报错了就把key的值设置回原来的

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值