Redission简单使用及简单工厂模式、策略模式改造分布式锁

#基于开源项目天机学堂的学习#

Redission

Redission解决的问题:

原子性:多线程下锁标识与锁的获取释放。

超时问题:超时释放易在阻塞发生时出错。
不可重入:一个线程获取锁后再次获取锁不成功。

失败重试:获取锁后是快速结束还是重新获取锁的动态实现。

一致性问题:主从同步时的一致性没有实现,如主节点获取锁宕机了,从节点成为主后没有锁信息。

锁获取使用:

@Autowired
private RedissonClient redissonClient;

@Test
void testRedisson() throws InterruptedException{
//1.获取锁对象,指定锁名称
RLock lock=redissonClient.getLock("lockname");
try{
    //2.尝试获取锁
    boolean isLock=lock.tryLock(1,10,TimeUnit.SECONDS);
    if(!isLock){
    //获取锁失败处理    
    }else{
    //获取锁成功处理
    }

}finally{
    //4.释放锁
    lock.unlock();
    }
}

使用简单工厂来优化获取锁逻辑:

//1.获取锁对象,指定锁名称
RLock lock=redissonClient.getLock("lockname");

自定义工厂为MyLockFactory,然后将bean注入到类中。

工厂中使用了可重入锁、公平锁、读写锁。

@Component
public class MyLockFactory {
    private final Map<MyLockType, Function<String,RLock>> lockHandlers;
    public MyLockFactory(RedissonClient redissonClient){
        // this.lockHandlers=new HashMap<>((MyLockType.values().length);
        //此处用EnumMap代替HashMap,因为枚举map的key是枚举,能大大提高根据枚举取value的效率
        this.lockHandlers=new EnumMap<>(MyLockType.class);
        this.lockHandlers.put(MyLockType.RE_ENTRANT_LOCK,redissonClient::getLock);
        this.lockHandlers.put(MyLockType.FAIR_LOCK,redissonClient::getFairLock);
        this.lockHandlers.put(MyLockType.READ_LOCK,name->redissonClient.getReadWriteLock(name).readLock());
        this.lockHandlers.put(MyLockType.WRITE_LOCK,name->redissonClient.getReadWriteLock(name).writeLock());
    }
    public RLock getLock(MyLockType lockType,String name){
        return lockHandlers.get(lockType).apply(name);
    }
}
public enum MyLockType {
    RE_ENTRANT_LOCK,
    FAIR_LOCK,
    READ_LOCK,
    WRITE_LOCK,
    ;
}

使用策略模式来优化获取锁失败的逻辑:

 //2.尝试获取锁
    boolean isLock=lock.tryLock(1,10,TimeUnit.SECONDS);

此处五种策略应写五个类来实现,由于代码逻辑较简单,就直接写出,类似于匿名内部类的写法

public enum MyLockStrategy {
    SKIP_FAST(){ //快速结束
        @Override
        public  boolean tryLock(RLock lock, MyLock prop) throws InterruptedException {
            return  lock.tryLock(0, prop.leaseTime(), prop.unit());

        }
    },
    FAIL_FAST(){ //快速失败
        @Override
        public  boolean tryLock(RLock lock, MyLock prop) throws InterruptedException {
            boolean islock= lock.tryLock(0, prop.leaseTime(), prop.unit());
            if(!islock){
                throw new BizIllegalException("请求太频繁");
            }
            return true;
        }
    },
    KEEP_TRYING(){ //保持重试
        @Override
        public  boolean tryLock(RLock lock, MyLock prop) {
           lock.lock( prop.leaseTime(), prop.unit());

            return true;
        }
    },
    SKIP_AFTER_RETRY_TIMEOUT(){ //重试超时后结束
        @Override
        public  boolean tryLock(RLock lock, MyLock prop) throws InterruptedException {
            return  lock.tryLock(prop.waitTime(), prop.leaseTime(), prop.unit());
        }
    },
    FAIL_AFTER_RETRY_TIMEOUT(){ //重试超时后抛出异常
        @Override
        public  boolean tryLock(RLock lock, MyLock prop) throws InterruptedException {
            boolean islock= lock.tryLock(prop.waitTime(), prop.leaseTime(), prop.unit());
            if(!islock){
                throw new BizIllegalException("请求太频繁");
            }
            return true;
        }
    },
    ;
  public   abstract boolean tryLock(RLock lock,MyLock prop) throws InterruptedException;

然后我们就可以指出需要的锁及锁获取失败逻辑。

    //自定义的MyLock mylock 中指定了
    //MyLockType lockType() default MyLockType.RE_ENTRANT_LOCK;
    //MyLockStrategy lockStrategy() default  MyLockStrategy.FAIL_AFTER_RETRY_TIMEOUT;         
        //1.创建锁对象 
        RLock lock=lockFactory.getLock(myLock.lockType(),myLock.name());
        //2.尝试获取锁
        boolean isLock=myLock.lockStrategy().tryLock(lock,myLock);

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值