1、创建springboot项目,添加相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.8</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!-- redis,使用jedis客户端排除lettuce -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.6</version>
</dependency>
2、application.yml配置文件添加配置
spring:
redis:
host: 39.107.46.146
port: 6379
password:
timeout: 5000
database: 0
prefix: redis://
3、管理RedisTemplate,RedissonClient
package com.company.springbootinterviewquestions.sys.config;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
/**
* 缓存的配置
*
* @author zj
* @date 2020/7/9 11:43
*/
@Configuration
public class CacheConfig {
@Autowired
private YmlBean ymlBean;
/**
* redis缓存类
*
* @author zj
* @date 2020/4/19 17:53
*/
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
redisTemplate.setConnectionFactory(connectionFactory);
Jackson2JsonRedisSerializer<?> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
// 字符串key序列化方式
redisTemplate.setKeySerializer(RedisSerializer.string());
// 字符串value序列化方式
redisTemplate.setValueSerializer(RedisSerializer.string());
// Hash key序列化方式
redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
// Hash value序列化方式
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
// 设置序列化方式, 前面只是声明, 该方法才实际注入序列化方式
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public RedissonClient redissonClient(){
Config config = new Config();
config.useSingleServer().setAddress(ymlBean.getRedisPrefix() + ymlBean.getRedisHost() + ":" + ymlBean.getRedisPort());
return Redisson.create(config);
}
}
4、配置文件参数
package com.company.springbootinterviewquestions.sys.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* 配置文件参数
*
* @author 35997
* @date 2022/4/20
*/
@Data
@Configuration
public class YmlBean {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private String redisPort;
@Value("${spring.redis.prefix}")
private String redisPrefix;
}
5、缓存雪崩控制类
package com.company.springbootinterviewquestions.lock.redis;
import cn.hutool.core.util.ObjectUtil;
import com.company.springbootinterviewquestions.core.pojo.response.ResponseData;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 缓存雪崩控制类
*
* @author 35997
* @date 2022/4/15
*/
@RequestMapping("/cache/avalanche")
@Controller
public class CacheAvalancheController {
@Autowired
private RedisTemplate redisTemplate;
/**
* 模拟数据库中的数据
*/
public void data(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
redisTemplate.opsForValue().set("aa", "数据");
}
@Autowired
private RedissonClient redissonClient;
final String LOCK_NAME = "distributed_mutex";
/**
* 互斥锁解决缓存雪崩(分布式锁)
* @return
*/
@RequestMapping("/distributed_mutex")
@ResponseBody
public ResponseData distributedMutex(String key){
Object value = redisTemplate.opsForValue().get(key);
if (ObjectUtil.isEmpty(value)){
RLock lock = redissonClient.getLock(LOCK_NAME);
if (lock.tryLock()) {
try {
value = redisTemplate.opsForValue().get(key);
if(ObjectUtil.isEmpty(value)){
data();
}
} catch (Exception e){
e.printStackTrace();
} finally {
lock.unlock();
}
}else{
value = redisTemplate.opsForValue().get(key);
if(ObjectUtil.isEmpty(value)){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
distributedMutex(key);
}
}
}
return ResponseData.success(value);
}
}
到此,大功告成。