redis--乐观锁--粗粒度锁

一、redis锁的应用

redis锁的引用请参考[redis锁](http://blog.csdn.net/liu20111590/article/details/52840999)

假如使用redis的watch监控一个或者多个key,这些key是集合数据,我们将这种锁称为粗粒度锁(类似于数据库中的表锁的功能)

二、redis粗粒度锁缺点

因为每次的操作,只会涉及到集合key的某一个值。我们对整个key进行监控,导致碰撞几率提高,从而使多数的事务被取消。事实上这些被取消的事务有很多是互相不影响的。

 举个例子
现在有一个市场(SET),里面存放了一些货物(货物1、货物2、货物3),有三个消费者(消费者A、消费者B、消费者C)。
消费者A想购买货物1,消费者B想购买货物2,消费者C想购买货物3。三个人同时拿到货物,同时去付款(这个时候是竞争关系)。
我们假设三个都提交了付款的请求,消费者A首先付款成功。这个时候因为市场(SET)中数据发生了变化,导致后面的事务都被取消掉了。

这种时候其实他们三个人是互不影响,但是因为我们使用了粗粒度锁,导致一些不需要取消的事务被取消。

这个时候我们需要细粒度锁来对数据加锁,减少碰撞的概率。

下面贴一段获取粗粒度锁的代码

/**
     * 对某一个key进行加锁
     * @param lockKey
     * @return
     */
    public String lock(String lockKey){
        AssertLock.isTrue(!StringUtils.isEmpty(lockKey),"lockKey不能为空");

        String uuid = UUID.randomUUID().toString().replace("-","");
        try {
            if(redisTemplate.opsForValue().setIfAbsent(LockUtils.commonLockKey(lockKey),uuid)){
                return uuid;
            }
            return null;
        }catch (Exception e){
            logger.error("获取锁失败",e);
        }
        return null;
    }
 /**
     * 释放锁
     * @param lockKey
     * @param uuid
     * @return
     */
    public boolean unLock(String lockKey,String uuid){
        AssertLock.isTrue(!StringUtils.isEmpty(lockKey),"lockKey不能为空");
        AssertLock.isTrue(!StringUtils.isEmpty(uuid),"uuid不能为空");

        try {
            if(StringUtils.equals(redisTemplate.opsForValue().get(LockUtils.commonLockKey(lockKey)),uuid)){
                return redisTemplate.expire(LockUtils.commonLockKey(lockKey),0L,TimeUnit.MILLISECONDS);
            }
            return false;
        }catch (Exception e){
            logger.error("释放锁失败",e);
        }
        return false;
    }
/**
     * 强制释放某个锁(慎用)
     * @param lockKey
     */
    public void forceUnLock(String lockKey){
        AssertLock.isTrue(!StringUtils.isEmpty(lockKey),"lockKey不能为空");

        redisTemplate.expire(LockUtils.commonLockKey(lockKey),0L,TimeUnit.MILLISECONDS);
    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值