本地锁 只能锁定自己的服务 SET key value [EX seconds] [PX milliseconds] [NX|XX]http://www.redis.cn/commands/set.html public MapString, ListCatelog2Vo getCatalogJsonWithRedisLock() { //redis 分布原则 加锁保证原子性,解
-
本地锁 只能锁定自己的服务
-
SET key value [EX seconds] [PX milliseconds] [NX|XX] http://www.redis.cn/commands/set.html
导入pom
<!--用redisson作为分布式锁,分布式对象 --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.0</version> </dependency>配置MyRedissonConfig
@Configuration public class MyRedissonConfig { /** * 对于redisson配置是RedissonClient操作的 * * @return * @throws IOException */ @Bean(destroyMethod = "shutdown") RedissonClient redisson() throws IOException { //创建配置 Config config = new Config(); config.useSingleServer().setAddress("redis://192.168.56.10:6379"); //config.useClusterServers() 集群模式 // .addNodeAddress("127.0.0.1:7004", "127.0.0.1:7001"); //依据Config创建RedissonClient RedissonClient redissonClient = Redisson.create(config); return redissonClient; } }测试加锁 解锁
public String hello() { //1.获取一把锁 只要锁 名字一样就是用一把锁 RLock lock = redisson.getLock("my_lock"); //2.加锁 lock.lock(30, TimeUnit.SECONDS); //lock.lock(); //堵塞式等待 try { //打印线程好 如果服务中断 有个看门狗自动续期 System.out.println("加锁成功执行业务"+Thread.currentThread().getId()); Thread.sleep(30000); } catch (InterruptedException e) { } finally { //3.解锁 System.out.println("解锁成功执行业务"+Thread.currentThread().getId()); lock.unlock(); } return "hello"; }//2.加锁 锁的自动续期,如果业务超长,运行期间自动给锁续上行的时间,不用担心业务时间长 锁自动过期被删掉 // 加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认在30s以后自动删除。
- 10秒自动解锁,自动解锁时间-定要大于业务的执行时间。在锁时间到了以后,不会自动续期。
- 如果我们传递了锁的超时时间,就发送给redis执行脚本,进行占锁,默认超时就是我们指定的时间
- 如果我们未指定锁的超时时间,就使用30 * 1000 [LockWatchdogTimeout看门狗的默认时间] ;
- 只要占锁成功,就会启动一个定时任务[重新给锁设置过期时间,新的过期时间就是看[ ]狗的默认时间]
- internallockLeaseTime [看门狗时间] / 3, 10s 规则用 lock.lock(30, TimeUnit.SECONDS); 加锁时间>=解锁时间
读写锁测试
- 保证一 定能读到最新数据,修改期间,写锁是一 个排他锁(互斥锁,独享锁)。读锁是一 一个共享锁
- 与锁役释放读就必须寺待
- 读+读 相当于无锁,并发读,只会在redis中记录好,所有当前的读锁。他们都会同时加锁成功
- 写+读:等待写锁释放
- 写+写:阻塞方式
- 读+写:有读锁。写也需要等待。
- 只要有写的存在,都必须等待
Redisson-信号量测试
车库停车 信号量测试 限流使用
@GetMapping("park") @ResponseBody public String park() throws InterruptedException { //使用信号量命名 RSemaphore park = redisson.getSemaphore("park"); //获取一个信号 获取一个数值 占一个车位 获取失败会一直等待 boolean b = park.tryAcquire(); //尝试获取 能否取到数值 不行就false 走 if (b){ //执行代码 }else { return "error"; } park.acquire(); return "ok停车+1"; } @GetMapping("go") @ResponseBody public String go() throws InterruptedException { //使用信号量命名 RSemaphore park = redisson.getSemaphore("park"); //释放信号 park.release(); return "ok 开走-1"; }Redisson-闭锁测试
分布式闭锁 放假锁门 等到全部走完 才关锁
@GetMapping("/lockDoor") @ResponseBody public String lockDoor() throws InterruptedException { RCountDownLatch doot = redisson.getCountDownLatch("door"); doot.trySetCount(5);//等待5个 doot.await();//等待闭锁都完成 return "放假了"; } @GetMapping("/gogo/{id}")//接收走的id @ResponseBody public String gogo(@PathVariable("id") Long id){ RCountDownLatch doot = redisson.getCountDownLatch("door"); doot.countDown();//等价于计数减一 return id+"走了"; }修正之前方法
public Map<String, List<Catelog2Vo>> getCatalogJsonWithRedissonLock() { //去占锁 RLock lock = redisson.getLock("catalogJson-lock"); //占锁之后 加锁 lock.lock(); Map<String, List<Catelog2Vo>> dataFromDb; try { dataFromDb = getDataFromDb(); } finally { //解锁 lock.unlock(); } return dataFromDb; }缓存-分布式锁-缓存一致性解决