redis简单的分布式锁

分布式锁的演进:

在这里插入图片描述

分布式锁演进——阶段1

在这里插入图片描述

分布式锁演进——阶段2

在这里插入图片描述

分布式锁演进——阶段3

在这里插入图片描述

分布式锁演进——阶段4

在这里插入图片描述

分布式锁演进——最终形态

在这里插入图片描述
java源代码:

private Map<Long,List<Category2Level>> getCategorysJsonFromDBWithRedisLock() {
        final String LOCK_KEY = "lock";
        // 生成每个线程各自的的唯一表示,区分lock值
        String uuid = UUID.randomUUID().toString();
        // 取redis中占坑,其他的线程就只能等待、(set lock 123 EX 300 NX),这边的过期时间和加锁一起设置,保证原子性
        Boolean lock = redisTemplate.opsForValue().setIfAbsent(LOCK_KEY, uuid, 300, TimeUnit.SECONDS);
        // 当前一个成功占坑
        if(lock) {
            System.out.println("获取分布式锁成功");
            Map<Long, List<Category2Level>> datasFromDB = null;
            try {
                // 查询缓存
                String s = redisTemplate.opsForValue().get(CATEGORY_JSON_KEY);
                // 缓存中没有
                if (StringUtils.isEmpty(s)){
                    // System.out.println("查询数据库");
                    // getDatasFromDB();查询数据库的逻辑
                    datasFromDB = getDatasFromDB();
                    // 在redis缓存中存数据 在锁结束时保存到缓存中
                    redisTemplate.opsForValue().set(CATEGORY_JSON_KEY,JSON.toJSONString(datasFromDB),1, TimeUnit.DAYS);
                }
                datasFromDB = JSON.parseObject(s, new TypeReference<Map<Long, List<Category2Level>>>() {
                });
                return datasFromDB;
            }catch (Exception e){
                System.out.println("业务逻辑出现异常");
            }finally {
                // 通过lua脚本删除锁
                String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
                redisTemplate.execute(new DefaultRedisScript<Long>(script,Long.class), Arrays.asList(LOCK_KEY), uuid);
            }
            return datasFromDB;
        } else {
            System.out.println("获取分布式锁失败,等待重试");
            // 加锁失败。。。重试
            // 休眠100ms重试
            try {
                Thread.sleep(200);
            }catch (Exception e){}
            return getCategorysJsonFromDBWithRedisLock();// 自旋的方式重试
        }
    }

主要是用了redis当中set命令:

SET key value [EX seconds] [PX milliseconds] [NX|XX]

PX milliseconds – 设置键key的过期时间,单位时毫秒
NX – 只有键key不存在的时候才会设置key的值

这时可以引入Redission

参考:redis中文网(set命令)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值