如何用Redlock完成分布式锁ITeye - AG环亚娱乐集团

如何用Redlock完成分布式锁ITeye

2019年04月04日11时08分26秒 | 作者: 耘志 | 标签: 分布式,完成,获取 | 浏览: 1802

转载自:

http://blog.csdn.net/forezp/article/details/70305336 
本文出自方志朋的博客

 

之前写过一篇文章《如安在springcloud分布式体系中完成分布式锁?》,由于自己仅仅是阅读了相关的书本,和查阅了相关的材料,就以为那样的是可行的。那篇文章完成的大约思路是用setNx指令和setEx合作运用。 setNx是一个耗时操作,由于它需求查询这个键是否存在,就算Redis的百万的qps,在高并发的场景下,这种操作也是有问题的。关于redis完成分布式锁,redis官方引荐运用redlock。

一、redlock简介

在不同进程需求互斥地拜访共享资源时,分布式锁是一种十分有用的技术手段。完成高效的分布式锁有三个特点需求考虑:

安全特点:互斥,不论什么时候,只需一个客户端持有锁 功率特点A:不会死锁 功率特点B:容错,只需大多数redis节点能够正常作业,客户端端都能获取和开释锁。

Redlock是redis官方提出的完成分布式锁管理器的算法。这个算法会比一般的一般办法愈加安全可靠。关于这个算法的评论能够看下官方文档。

二、怎样用java运用 redlock

在pom文件引进redis和redisson依靠:

 

 ! redis 
 dependency 
 groupId org.springframework.boot /groupId 
 artifactId spring-boot-starter-data-redis /artifactId 
 /dependency 
 ! redisson 
 dependency 
 groupId org.redisson /groupId 
 artifactId redisson /artifactId 
 version 3.3.2 /version 
 /dependency 

 AquiredLockWorker接口类,,主要是用于获取锁后需求处理的逻辑:

 

 

/**
 * Created by fangzhipeng on 2017/4/5.
 * 获取锁后需求处理的逻辑
public interface AquiredLockWorker T {
 T invokeAfterLockAquire() throws Exception;
}

 DistributedLocker 获取锁管理类:

 

 

/**
 * Created by fangzhipeng on 2017/4/5.
 * 获取锁管理类
public interface DistributedLocker {
 * 获取锁
 * @param resourceName 锁的称号
 * @param worker 获取锁后的处理类
 * @param T 
 * @return 处理完详细的事务逻辑要回来的数据
 * @throws UnableToAquireLockException
 * @throws Exception
 T T lock(String resourceName, AquiredLockWorker T worker) throws UnableToAquireLockException, Exception;
 T T lock(String resourceName, AquiredLockWorker T worker, int lockTime) throws UnableToAquireLockException, Exception;
}

 UnableToAquireLockException ,不能获取锁的反常类:

 

 

/**
 * Created by fangzhipeng on 2017/4/5.
 * 反常类
public class UnableToAquireLockException extends RuntimeException {
 public UnableToAquireLockException() {
 public UnableToAquireLockException(String message) {
 super(message);
 public UnableToAquireLockException(String message, Throwable cause) {
 super(message, cause);
}

 RedissonConnector 衔接类:

 

 

/**
 * Created by fangzhipeng on 2017/4/5.
 * 获取RedissonClient衔接类
@Component
public class RedissonConnector {
 RedissonClient redisson;
 @PostConstruct
 public void init(){
 redisson = Redisson.create();
 public RedissonClient getClient(){
 return redisson;
}

 RedisLocker 类,完成了DistributedLocker:

 

 

import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
 * Created by fangzhipeng on 2017/4/5.
@Component
public class RedisLocker implements DistributedLocker{
 private final static String LOCKER_PREFIX = "lock:";
 @Autowired
 RedissonConnector redissonConnector;
 @Override
 public T T lock(String resourceName, AquiredLockWorker T worker) throws InterruptedException, UnableToAquireLockException, Exception {
 return lock(resourceName, worker, 100);
 @Override
 public T T lock(String resourceName, AquiredLockWorker T worker, int lockTime) throws UnableToAquireLockException, Exception {
 RedissonClient redisson= redissonConnector.getClient();
 RLock lock = redisson.getLock(LOCKER_PREFIX + resourceName);
 // Wait for 100 seconds seconds and automatically unlock it after lockTime seconds
 boolean success = lock.tryLock(100, lockTime, TimeUnit.SECONDS);
 if (success) {
 try {
 return worker.invokeAfterLockAquire();
 } finally {
 lock.unlock();
 throw new UnableToAquireLockException();
}

 测验类:

 

 

@Autowired
 RedisLocker distributedLocker;
 @RequestMapping(value = "/redlock")
 public String testRedlock() throws Exception{
 CountDownLatch startSignal = new CountDownLatch(1);
 CountDownLatch doneSignal = new CountDownLatch(5);
 for (int i = 0; i ++i) { // create and start threads
 new Thread(new Worker(startSignal, doneSignal)).start();
 startSignal.countDown(); // let all threads proceed
 doneSignal.await();
 System.out.println("All processors done. Shutdown connection");
 return "redlock";
 class Worker implements Runnable {
 private final CountDownLatch startSignal;
 private final CountDownLatch doneSignal;
 Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
 this.startSignal = startSignal;
 this.doneSignal = doneSignal;
 public void run() {
 try {
 startSignal.await();
 distributedLocker.lock("test",new AquiredLockWorker Object () {
 @Override
 public Object invokeAfterLockAquire() {
 doTask();
 return null;
 }catch (Exception e){
 void doTask() {
 System.out.println(Thread.currentThread().getName() + " start");
 Random random = new Random();
 int _int = random.nextInt(200);
 System.out.println(Thread.currentThread().getName() + " sleep " + _int + "millis");
 try {
 Thread.sleep(_int);
 } catch (InterruptedException e) {
 e.printStackTrace();
 System.out.println(Thread.currentThread().getName() + " end");
 doneSignal.countDown();
 }

 运转测验类:

Thread-48 start 
Thread-48 sleep 99millis 
Thread-48 end 
Thread-49 start 
Thread-49 sleep 118millis 
Thread-49 end 
Thread-52 start 
Thread-52 sleep 141millis 
Thread-52 end 
Thread-50 start 
Thread-50 sleep 28millis 
Thread-50 end 
Thread-51 start 
Thread-51 sleep 145millis 
Thread-51 end

 

从运转成果上看,在异步使命的情况下,确实是获取锁之后才干运转线程。不论怎样样,这是redis官方引荐的一种计划,可靠性比较高。有什么问题欢迎留言。

三、参考材料

https://github.com/redisson/redisson

《Redis官方文档》用Redis构建分布式锁

A Look at the Java Distributed In-Memory Data Model (Powered by Redis)

优异文章引荐: 史上最简略的 SpringCloud 教程 | 终章 史上最简略的 SpringCloud 教程 | 第一篇: 效劳的注册与发现(Eureka) 史上最简略的SpringCloud教程 | 第七篇: 高可用的分布式装备中心(Spring Cloud Config)
版权声明
本文来源于网络,版权归原作者所有,其内容与观点不代表AG环亚娱乐集团立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,请与我们联系,我们核实后立即修改或删除。

猜您喜欢的文章

阅读排行

  • 1

    简历打分排序ITeye

    排序,简历,体系
  • 2

    如何用Redlock完成分布式锁ITeye

    分布式,完成,获取
  • 3
  • 4

    java 批量推送 iosITeye

    推送,测验,内容
  • 5
  • 6
  • 7
  • 8

    递归算法和文件行列算法ITeye

    文件,行列,文件夹
  • 9

    链表结构ITeye

    结点,保存,删去
  • 10