REDIS09_分布式锁的概述、加锁使用sexnu、解锁使用lua脚本保证原子性、引发的问题思考(六)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: REDIS09_分布式锁的概述、加锁使用sexnu、解锁使用lua脚本保证原子性、引发的问题思考(六)

⑥. 单机的Redis案例加锁、解锁


①. 加锁:加锁实际上就是在redis中,给Key键设置一个值,为避免死锁,并给定一个过期时间


②. 解锁:将Key键删除。但也不能乱删,不能说客户端1的请求将客户端2的锁给删除掉,只能自己删除自己的锁


(为了保证解锁操作的原子性,我们用LUA脚本完成这一操作。先判断当前锁的字符串是否与传入的值相等,是的话就删除Key,解锁成功)



if redis.call('get',KEYS[1]) == ARGV[1] then 
   return redis.call('del',KEYS[1]) 
else
   return 0 
end


  • ③. 超时:锁key要注意过期时间,不能长期占用


  • ④. 单机模式中,一般都是用set/setnx+lua脚本搞定,想想它的缺点是什么?
    如果redis发生了宕机,所有的请求压力都指向了数据库


public Map<String, List<Catalog2Vo>> getCatalogJsonDbWithRedisLock() {
    String uuid = UUID.randomUUID().toString();
    ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
    Boolean lock = ops.setIfAbsent("lock", uuid,500, TimeUnit.SECONDS);
    if (lock) {
        Map<String, List<Catalog2Vo>> categoriesDb = getCategoryMap();
        String lockValue = ops.get("lock");
        // get和delete原子操作
        String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
            "    return redis.call(\"del\",KEYS[1])\n" +
            "else\n" +
            "    return 0\n" +
            "end";
        stringRedisTemplate.execute(
            new DefaultRedisScript<Long>(script, Long.class), // 脚本和返回类型
            Arrays.asList("lock"), // 参数
            lockValue); // 参数值,锁的值
        return categoriesDb;
    }else {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 睡眠0.1s后,重新调用 //自旋
        return getCatalogJsonDbWithRedisLock();
    }
}



相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3月前
|
缓存 NoSQL Redis
Redis 脚本
10月更文挑战第18天
44 3
|
3天前
|
SQL Java 关系型数据库
【📕分布式锁通关指南 01】从解决库存超卖开始加锁的初体验
本文通过电商场景中的库存超卖问题,深入探讨了JVM锁、MySQL悲观锁和乐观锁的实现及其局限性。首先介绍了单次访问下库存扣减逻辑的正常运行,但在高并发场景下出现了超卖问题。接着分析了JVM锁在多例模式、事务模式和集群模式下的失效情况,并提出了使用数据库锁机制(如悲观锁和乐观锁)来解决并发问题。 悲观锁通过`update`语句或`select for update`实现,能有效防止超卖,但存在锁范围过大、性能差等问题。乐观锁则通过版本号或时间戳实现,适合读多写少的场景,但也面临高并发写操作性能低和ABA问题。 最终,文章强调没有完美的方案,只有根据具体业务场景选择合适的锁机制。
23 12
|
1月前
|
NoSQL Java Redis
秒杀抢购场景下实战JVM级别锁与分布式锁
在电商系统中,秒杀抢购活动是一种常见的营销手段。它通过设定极低的价格和有限的商品数量,吸引大量用户在特定时间点抢购,从而迅速增加销量、提升品牌曝光度和用户活跃度。然而,这种活动也对系统的性能和稳定性提出了极高的要求。特别是在秒杀开始的瞬间,系统需要处理海量的并发请求,同时确保数据的准确性和一致性。 为了解决这些问题,系统开发者们引入了锁机制。锁机制是一种用于控制对共享资源的并发访问的技术,它能够确保在同一时间只有一个进程或线程能够操作某个资源,从而避免数据不一致或冲突。在秒杀抢购场景下,锁机制显得尤为重要,它能够保证商品库存的扣减操作是原子性的,避免出现超卖或数据不一致的情况。
63 10
|
1月前
|
监控 安全
公司用什么软件监控电脑:Lua 脚本在监控软件扩展功能的应用
在企业环境中,电脑监控软件对保障信息安全、提升效率至关重要。Lua 脚本在此类软件中用于扩展功能,如收集系统信息、监控软件使用时长及文件操作,向指定服务器发送数据,支持企业管理和运营。
45 6
|
2月前
|
存储 运维 NoSQL
分布式读写锁的奥义:上古世代 ZooKeeper 的进击
本文作者将介绍女娲对社区 ZooKeeper 在分布式读写锁实践细节上的思考,希望帮助大家理解分布式读写锁背后的原理。
|
3月前
|
缓存 NoSQL Java
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
85 3
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
|
3月前
|
缓存 分布式计算 NoSQL
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
大数据-43 Redis 功能扩展 Lua 脚本 对Redis扩展 eval redis.call redis.pcall
45 2
|
3月前
|
NoSQL Java 关系型数据库
阿里 P7二面:Redis 执行 Lua,到底能不能保证原子性?
Redis 和 Lua,两个看似风流马不相及的技术点,为何能产生“爱”的火花,成为工作开发中的黄金搭档?技术面试中更是高频出现,Redis 执行 Lua 到底能不能保证原子性?今天就来聊一聊。 
130 1
|
4月前
|
存储 JSON Ubuntu
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
如何使用 Lua 脚本进行更复杂的网络请求,比如 POST 请求?
|
4月前
|
SQL 存储 网络协议
分布式的概述
分布式的概述