利用Java代码调用Lua脚本改造分布式锁

4.8 利用Java代码调用Lua脚本改造分布式锁

lua脚本本身并不需要大家花费太多时间去研究,只需要知道如何调用,大致是什么意思即可,所以在笔记中并不会详细的去解释这些lua表达式的含义。

我们的RedisTemplate中,可以利用execute方法去执行lua脚本,参数对应关系就如下图股

Java代码

java 复制代码
private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
    static {
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        UNLOCK_SCRIPT.setResultType(Long.class);
    }

public void unlock() {
    // 调用lua脚本
    stringRedisTemplate.execute(
            UNLOCK_SCRIPT,
            Collections.singletonList(KEY_PREFIX + name),
            ID_PREFIX + Thread.currentThread().getId());
}
经过以上代码改造后,我们就能够实现 拿锁比锁删锁的原子性动作了~

小总结:

基于Redis的分布式锁实现思路:

  • 利用set nx ex获取锁,并设置过期时间,保存线程标示
  • 释放锁时先判断线程标示是否与自己一致,一致则删除锁
    • 特性:
      • 利用set nx满足互斥性
      • 利用set ex保证故障时锁依然能释放,避免死锁,提高安全性
      • 利用Redis集群保证高可用和高并发特性

笔者总结:我们一路走来,利用添加过期时间,防止死锁问题的发生,但是有了过期时间之后,可能出现误删别人锁的问题,这个问题我们开始是利用删之前 通过拿锁,比锁,删锁这个逻辑来解决的,也就是删之前判断一下当前这把锁是否是属于自己的,但是现在还有原子性问题,也就是我们没法保证拿锁比锁删锁是一个原子性的动作,最后通过lua表达式来解决这个问题

但是目前还剩下一个问题锁不住,什么是锁不住呢,你想一想,如果当过期时间到了之后,我们可以给他续期一下,比如续个30s,就好像是网吧上网, 网费到了之后,然后说,来,网管,再给我来10块的,是不是后边的问题都不会发生了,那么续期问题怎么解决呢,可以依赖于我们接下来要学习redission啦

测试逻辑:

第一个线程进来,得到了锁,手动删除锁,模拟锁超时了,其他线程会执行lua来抢锁,当第一天线程利用lua删除锁时,lua能保证他不能删除他的锁,第二个线程删除锁时,利用lua同样可以保证不会删除别人的锁,同时还能保证原子性。

相关推荐
静若繁花_jingjing6 小时前
ZooKeeper & Nacos
分布式·zookeeper·云原生
wanhengidc6 小时前
云手机中分布式存储的功能
运维·服务器·分布式·游戏·智能手机·云计算
u***j3246 小时前
HarmonyOS分布式能力核心技术深度解析
分布式·华为·harmonyos
7***n756 小时前
HarmonyOS分布式数据管理
分布式·华为·harmonyos
TracyCoder1237 小时前
Dubbo+Zookeeper怎么实现的服务注册与发现
分布式·zookeeper·dubbo
C***u17612 小时前
分布式多卡训练(DDP)踩坑
分布式
t***q3312 小时前
分布式监控Skywalking安装及使用教程(保姆级教程)
分布式·skywalking
CNRio12 小时前
人工智能基础架构与算力之2 异构算力合池技术:打破资源壁垒的分布式 AI 部署方案
人工智能·分布式
x***J34819 小时前
VueWebSocket案例
分布式·milvus·appcompat
20岁30年经验的码农1 天前
Kafka 消息中间件实战指南
分布式·kafka·linq