分布式锁。

分布式锁一般有三种实现方式

  1. 数据库乐观锁。
  2. 基于Redis的分布式锁。
  3. 基于ZooKeeper的分布式锁。

一、Redis实现分布式锁

  1. 通过setnx,不存在key则插入成功,存在key则不插入
  2. 且加上过期时间,防止释放锁失败一直死锁
  3. 插入和设置过期时间是原子性操作
  4. 释放锁,只有当前持有改锁的客户端能够释放锁。通过Lua脚本执行,如果redis value相同才删除key。如果不是原子性操作,A客户端的value=redisValue,刚好过期,B客户端过来访问获取到锁,此时A客户端执行删除key释放锁。可能误释放B的锁
	/**
     * 获取分布式锁, 且锁加上过期时间
     * 单个redis服务器, 已有key存在, 则函数不会调用成功。只有一个客户端能持有key, 通过setNx + 过期时间实现锁
     * @param key
     * @param value
     * @param expireTime 秒
     * @return
     */
    public static boolean getDistributedLock(RedisService redisService, String key, String value, int expireTime) {
        boolean res = redisService.setNxExpire(key, value, expireTime);
        logger.info(String.format("key:%s, 获取锁结果:%s", key, res));

        return res;
    }
	public boolean setNxExpire(String key, String value, int seconds) {
        Jedis jedis = null;
        try {
            jedis = getJedis(jedisPool);
            String result = jedis.set(key, value, "NX", "EX", seconds);
            if ("OK".equals(result)) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }
        return false;
    }
	/**
     * 释放分布式锁, 只有value相同时才能释放
     * @param key
     * @param value
     * @return
     */
    public static boolean releaseDistributedLock(RedisService redisService, String key, String value) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = redisService.eval(script, key, value);
        if (null == result) {
            return false;
        }
        if (Long.valueOf(1).equals(result)) {
            return true;
        } else {
            return false;
        }
    }
	@Override
    public Object eval(String script, String key, String value) {
        Jedis jedis = null;
        try {
            jedis = getJedis(jedisPool);
            return jedis.eval(script, Collections.singletonList(key), Collections.singletonList(value));
        } catch (Exception e) {
            returnBrokenResource(jedis);
        } finally {
            returnResource(jedis);
        }
        return null;
    }

使用示例
在这里插入图片描述

二、乐观锁和悲观锁

  1. 乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,CAS算法实现。
  2. 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。
  3. CAS存在ABA问题

参考内容

  1. https://www.jb51.net/article/169108.htm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值