1、导入maven坐标
<!-- 用redisson作为所有分布式锁,分布式对象等功能框架--><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.12.5</version></dependency>
2、redisson配置类(如果redis没有密码就不需要private String password)
package com.xuechengpluscommon.config;import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @description Redisson 配置类*/
@Configuration
public class MyRedissonConfig {@Value(value = "${spring.redis.host}")private String host;@Value(value = "${spring.redis.port}")private int port;@Value(value = "${spring.redis.database}")private int database;
// @Value(value = "${spring.redis.password}")
// private String password;/*** 单Redis节点模式配置方法* 其他配置參數,看:* <a href = "https://github.com/redisson/redisson/wiki/2.-%E9%85%8D%E7%BD%AE%E6%96%B9%E6%B3%95#26-%E5%8D%95redis%E8%8A%82%E7%82%B9%E6%A8%A1%E5%BC%8F">* 单Redis节点模式配置方法* </a>** @return {@link RedissonClient}*/@Bean(destroyMethod = "shutdown")RedissonClient redisson() {Config config = new Config();//Redis多节点// config.useClusterServers()// .addNodeAddress("redis://127.0.0.1:6379", "redis://127.0.0.1:7001");//Redis单节点SingleServerConfig singleServerConfig = config.useSingleServer();//可以用"rediss://"来启用SSL连接String address = "redis://" + host + ":" + port;singleServerConfig.setAddress(address);//设置 数据库编号singleServerConfig.setDatabase(database);
// singleServerConfig.setPassword(password);//连接池大小:默认值:64// singleServerConfig.setConnectionPoolSize()return Redisson.create(config);}}
yml中redis的配置
redis:database: 0host: ip地址port: 6379
3、创建redisson的bean
@Autowired
private RedissonClient redisson;
4、测试,入队
@Test
void contextLoads1() {RQueue<String> queue = redisson.getQueue("RedissonQueue");queue.add("hello");System.out.println(queue);
}
redis数据
5、测试,出队
@Test
void contextLoads2() {RQueue<String> queue = redisson.getQueue("RedissonQueue");String remove = queue.remove();System.out.println(remove);
}
出队数据:
6、分布式锁
public R redisTest1() throws InterruptedException {//首先从redis查询数据Orders redisOrder;redisOrder=(Orders) redisTemplate.opsForValue().get("redisTest");//如果存在redis则返回if(ObjectUtils.isNotEmpty(redisOrder)){return R.ok(redisOrder);//如果不存在则从数据库查询}else {//首先获取分布式锁RLock lock = redissonClient.getLock("redisTestDogWatch");//上锁lock.lock();//获取锁之后进行查询try {redisOrder = (Orders) redisTemplate.opsForValue().get("redisTest");if (ObjectUtils.isNotEmpty(redisOrder)) {return R.ok(redisOrder);}//数据库查询redisOrder= ordersService.getById(1577177773194113014L);redisTemplate.opsForValue().set("redisTest", redisOrder );System.out.println("[从数据库中查询]");} catch (Exception e) {e.printStackTrace();} finally {//删除锁lock.unlock();}return R.ok(redisOrder);}}
在这里让线程睡眠35秒
//上锁
lock.lock();
Thread.sleep(35000);
此时三个服务器运行
测试结果
可以首先看到已经上锁的redisTestDogWatch,每个锁30秒,如果线程未完成则会自动续30秒,如果线程完成到finally中的unlock就删除锁
目前可以看到只有一个服务器获取到锁
存储redis的数据
此时进行并发测试
依旧保持35秒的睡眠时间
此时可以看到未拿到锁的线程报错
java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: d904f2b9-e75d-472d-a5a6-d0a8cc603a80 thread-id: 210
尝试解锁锁定,未被当前线程锁定 按节点 ID:C731FAC4-9BF7-4F4A-ACC1-A2CC9B78A02F 线程 ID:232
这是因为锁住了,所以无法获取锁,然后看门狗会不断刷新