网站推荐入口,wordpress媒体库创建文件夹,徐州市工程建设交易平台,某企业网站建设论文我的博客大纲 我的后端学习大纲 a.redisson概述#xff1a; 1.Redisson是一个在Redis的基础上实现的Java驻内存数据网格#xff08;In-Memory Data Grid#xff09;2.redisson介绍官方文档地址#xff1a;3.Redisson它不仅提供了一系列的分布式的Java常用对象#xff0c;还… 我的博客大纲 我的后端学习大纲 a.redisson概述 1.Redisson是一个在Redis的基础上实现的Java驻内存数据网格In-Memory Data Grid2.redisson介绍官方文档地址3.Redisson它不仅提供了一系列的分布式的Java常用对象还提供了许多分布式服务 包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service)Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离Separation of Concern从而让使用者能够将精力更集中地放在处理业务逻辑上。
b.各分布式锁介绍
b1.可重入锁Reentrant Lock
b1-1.概述
1.基于Redis的Redisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。2.如果负责储存这个分布式锁的Redisson节点宕机以后而且这个锁正好处于锁住的状态时这个锁会出现锁死的状态。为了避免这种情况的发生Redisson内部提供了一个监控锁的看门狗它的作用是在Redisson实例被关闭前不断的延长锁的有效期。3.默认情况下看门狗检查锁的超时时间是30秒钟也可以通过修改Config.lockWatchdogTimeout来另行指定。4.RLock对象完全符合Java的Lock规范。也就是说只有拥有锁的进程才能解锁其他进程解锁则会抛出IllegalMonitorStateException错误。5.另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
RLock lock redisson.getLock(anyLock);
// 最常见的使用方法
lock.lock();// 加锁以后10秒钟自动解锁
// 无需调用unlock方法手动解锁
lock.lock(10, TimeUnit.SECONDS);// 尝试加锁最多等待100秒上锁以后10秒自动解锁
boolean res lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {try {...} finally {lock.unlock();}
}b1-2.编码实现
1.引入依赖
dependencygroupIdorg.redisson/groupIdartifactIdredisson/artifactIdversion3.11.2/version
/dependency2.添加配置
Configuration
public class RedissonConfig {Beanpublic RedissonClient redissonClient(){Config config new Config();// 可以用rediss://来启用SSL连接config.useSingleServer().setAddress(redis://172.16.116.100:6379);return Redisson.create(config);}
}3.代码中使用
Autowired
private RedissonClient redissonClient;public void checkAndLock() {// 加锁获取锁失败重试RLock lock this.redissonClient.getLock(lock);lock.lock();// 先查询库存是否充足Stock stock this.stockMapper.selectById(1L);// 再减库存if (stock ! null stock.getCount() 0){stock.setCount(stock.getCount() - 1);this.stockMapper.updateById(stock);}// 释放锁lock.unlock();
}4.压力测试性能跟我们手写的区别不大。 5.数据库也没有问题
b2. 公平锁Fair Lock
1.基于Redis的Redisson分布式可重入公平锁也是实现了java.util.concurrent.locks.Lock接口的一种RLock对象。2.同时还提供了异步Async、反射式Reactive和RxJava2标准的接口。3.它保证了当多个Redisson客户端线程同时请求加锁时优先分配给先发出请求的线程。4.所有请求线程会在一个队列中排队当某个线程出现宕机时Redisson会等待5秒后继续下一个线程也就是说如果前面有5个线程都处于等待状态那么后面的线程会等待至少25秒。
RLock fairLock redisson.getFairLock(anyLock);
// 最常见的使用方法
fairLock.lock();// 10秒钟以后自动解锁
// 无需调用unlock方法手动解锁
fairLock.lock(10, TimeUnit.SECONDS);// 尝试加锁最多等待100秒上锁以后10秒自动解锁
boolean res fairLock.tryLock(100, 10, TimeUnit.SECONDS);
fairLock.unlock();b3. 联锁MultiLock
1.基于Redis的Redisson分布式联锁RedissonMultiLock对象可以将多个RLock对象关联为一个联锁每个RLock对象实例可以来自于不同的Redisson实例。
RLock lock1 redissonInstance1.getLock(lock1);
RLock lock2 redissonInstance2.getLock(lock2);
RLock lock3 redissonInstance3.getLock(lock3);RedissonMultiLock lock new RedissonMultiLock(lock1, lock2, lock3);
// 同时加锁lock1 lock2 lock3
// 所有的锁都上锁成功才算成功。
lock.lock();
...
lock.unlock();b4. 红锁RedLock
1.基于Redis的Redisson红锁RedissonRedLock对象实现了Redlock介绍的加锁算法。2.该对象也可以用来将多个RLock对象关联为一个红锁每个RLock对象实例可以来自于不同的Redisson实例。
RLock lock1 redissonInstance1.getLock(lock1);
RLock lock2 redissonInstance2.getLock(lock2);
RLock lock3 redissonInstance3.getLock(lock3);
RedissonRedLock lock new RedissonRedLock(lock1, lock2, lock3);
// 同时加锁lock1 lock2 lock3
// 红锁在大部分节点上加锁成功就算成功。
lock.lock();
...
lock.unlock();b5. 读写锁ReadWriteLock
b5-1.概述
1.基于Redis的Redisson分布式可重入读写锁RReadWriteLock Java对象实现了java.util.concurrent.locks.ReadWriteLock接口。2.其中读锁和写锁都继承了RLock接口。3.分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。
b5-2.编码实现
RReadWriteLock rwlock redisson.getReadWriteLock(anyRWLock);
// 最常见的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();
// 10秒钟以后自动解锁
// 无需调用unlock方法手动解锁
rwlock.readLock().lock(10, TimeUnit.SECONDS);
// 或
rwlock.writeLock().lock(10, TimeUnit.SECONDS);// 尝试加锁最多等待100秒上锁以后10秒自动解锁
boolean res rwlock.readLock().tryLock(100, 10, TimeUnit.SECONDS);
// 或
boolean res rwlock.writeLock().tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();添加StockController方法
GetMapping(test/read)
public String testRead(){String msg stockService.testRead();return 测试读;
}GetMapping(test/write)
public String testWrite(){String msg stockService.testWrite();return 测试写;
}添加StockService方法
public String testRead() {RReadWriteLock rwLock this.redissonClient.getReadWriteLock(rwLock);rwLock.readLock().lock(10, TimeUnit.SECONDS);System.out.println(测试读锁。。。。);// rwLock.readLock().unlock();return null;
}public String testWrite() {RReadWriteLock rwLock this.redissonClient.getReadWriteLock(rwLock);rwLock.writeLock().lock(10, TimeUnit.SECONDS);System.out.println(测试写锁。。。。);// rwLock.writeLock().unlock();return null;
}b5-3.测试
1.打开开两个浏览器窗口测试 同时访问写一个写完之后等待一会儿约10s另一个写开始同时访问读不用等待先写后读读要等待约10s写完成先读后写写要等待约10s读完成 b6. 信号量Semaphore
1.基于Redis的Redisson的分布式信号量SemaphoreJava对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法。2.同时还提供了异步Async、反射式Reactive和RxJava2标准的接口。
RSemaphore semaphore redisson.getSemaphore(semaphore);
semaphore.trySetPermits(3);
semaphore.acquire();
semaphore.release();3.在StockController添加方法
GetMapping(test/semaphore)
public String testSemaphore(){this.stockService.testSemaphore();return 测试信号量;
}4.在StockService添加方法
public void testSemaphore() {RSemaphore semaphore this.redissonClient.getSemaphore(semaphore);semaphore.trySetPermits(3);try {semaphore.acquire();TimeUnit.SECONDS.sleep(5);System.out.println(System.currentTimeMillis());semaphore.release();} catch (InterruptedException e) {e.printStackTrace();}
}5.添加测试用例并发10次循环一次: 6.控制台效果
控制台1
1606960790234
1606960800337
1606960800443
1606960805248控制台2
1606960790328
1606960795332
1606960800245控制台3
1606960790433
1606960795238
16069607954377.由此可知 1606960790秒有3次请求进来每个控制台各1次 1606960795秒有3次请求进来控制台2有1次控制台3有2次 1606960800秒有3次请求进来控制台1有2次控制台2有1次 1606960805秒有1次请求进来控制台1有1次
b7. 闭锁CountDownLatch
1.基于Redisson的Redisson分布式闭锁CountDownLatchJava对象RCountDownLatch采用了与java.util.concurrent.CountDownLatch相似的接口和用法。
RCountDownLatch latch redisson.getCountDownLatch(anyCountDownLatch);
latch.trySetCount(1);
latch.await();// 在其他线程或其他JVM里
RCountDownLatch latch redisson.getCountDownLatch(anyCountDownLatch);
latch.countDown();2.需要两个方法 一个等待一个计数countDown给StockController添加测试方法
GetMapping(test/latch)
public String testLatch(){this.stockService.testLatch();return 班长锁门。。。;
}
GetMapping(test/countdown)
public String testCountDown(){this.stockService.testCountDown();return 出来了一位同学;
}3.给StockService添加测试方法
public void testLatch() {RCountDownLatch latch this.redissonClient.getCountDownLatch(latch);latch.trySetCount(6);try {latch.await();} catch (InterruptedException e) {e.printStackTrace();}
}public void testCountDown() {RCountDownLatch latch this.redissonClient.getCountDownLatch(latch);latch.trySetCount(6);latch.countDown();
}重启测试打开两个页面当第二个请求执行6次之后第一个请求才会执行。