- ①. 建立redis_2022、设置pom文件、写YML、主启动类
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.10.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.xiaozhi.redis</groupId>
<artifactId>redis_20210511</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mapper.version>4.1.5</mapper.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
server.port=5555
spring.application.name=redis0511
# ========================logging 日志相关的配置=====================
#系统默认,全局root配置的日志形式,可以注释掉
logging.level.root=warn
#开发人员自己设置的包结构,对那个package进行什么级别的日志监控
logging.level.com.xiaozhi.redis=info
#开发人员自定义日志路径和日志名称
logging.file.name=D:/mylogs2/logs/redis0511.log
#%d{HH:mm:ss.SSS}――日志输出时间
#%thread――输出日志的进程名字,这在Web应用以及异步任务处理中很有用
#%-5level――日志级别,并且使用5个字符靠左对齐
#%logger- ――日志输出者的名字
#%msg――日志消息
#%n――平台的换行符
#logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
# ========================alibaba.druid相关配置=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.druid.test-while-idle=false
# ========================redis相关配置=====================
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
#spring.redis.host=192.168.111.150
spring.redis.host=192.168.68.143
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1,记得加入单位ms,不然idea报红色
spring.redis.lettuce.pool.max-wait=-1ms
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
# ========================mybatis相关配置===================
mybatis.mapper-locations=classpath:mapper
@SpringBootApplication
@MapperScan("com.xiaozhi.redis.mapper")
public class Redis20210511Application {
public static void main(String[] args) {
SpringApplication.run(Redis20210511Application.class, args);
}
}
- ②. 业务类、controller、service、entity、mapper
@Api(description = "用户User接口")
@RestController
@Slf4j
public class UserController
{
@Resource
private UserService userService;
@ApiOperation("数据库新增5条记录")
@RequestMapping(value = "/user/add",method = RequestMethod.POST)
public void addUser() {
for (int i = 1; i <=5; i++) {
User user = new User();
user.setUsername("TANGZHI"+i);
user.setPassword(IdUtil.simpleUUID().substring(0,6));
user.setSex((byte) new Random().nextInt(2));
user.setDeleted((byte)0);
user.setCreateTime(new Date());
userService.addUser(user);
}
}
@ApiOperation("删除1条记录")
@RequestMapping(value = "/user/delete/{id}",method = RequestMethod.POST)
public void deleteUser(@PathVariable Integer id) {
userService.deleteUser(id);
}
@ApiOperation("修改1条记录")
@RequestMapping(value = "/user/update",method = RequestMethod.POST)
public void updateUser(@RequestBody UserDTO userDTO) {
User user = new User();
BeanUtils.copyProperties(userDTO,user);
userService.updateUser(user);
}
@ApiOperation("查询1条记录")
@RequestMapping(value = "/user/find/{id}",method = RequestMethod.GET)
public User findUserById(@PathVariable Integer id) {
return userService.findUserById2(id);
}
}
@Service
@Slf4j
public class UserService {
public static final String CACHE_KEY_USER = "user:";
@Resource
private UserMapper userMapper;
@Resource
private RedisTemplate redisTemplate;
public void addUser(User user) {
int i = userMapper.insert(user);
if(i > 0) {
user = userMapper.selectById(user.getId());
String key = CACHE_KEY_USER+user.getId();
redisTemplate.opsForValue().set(key,user);
}
}
public void deleteUser(Integer id) {
int i = userMapper.deleteById(id);
if(i > 0) {
String key = CACHE_KEY_USER+id;
redisTemplate.delete(key);
}
}
public void updateUser(User user) {
int i = userMapper.updateById(user);
if(i > 0) {
user = userMapper.selectById(user.getId());
String key = CACHE_KEY_USER+user.getId();
redisTemplate.opsForValue().set(key,user);
}
}
public User findUserById(Integer id) {
User user = null;
String key = CACHE_KEY_USER+id;
user = (User) redisTemplate.opsForValue().get(key);
if(user == null) {
user = userMapper.selectById(id);
if(user == null) {
return user;
}else{
redisTemplate.opsForValue().set(key,user);
}
}
return user;
}
public User findUserById2(Integer id) {
User user = null;
String key = CACHE_KEY_USER+id;
user = (User) redisTemplate.opsForValue().get(key);
if(user == null) {
synchronized (UserService.class){
user = (User) redisTemplate.opsForValue().get(key);
if (user == null) {
user = userMapper.selectById(id);
if (user == null) {
return null;
}else{
redisTemplate.opsForValue().setIfAbsent(key,user,7L,TimeUnit.DAYS);
}
}
}
}
return user;
}
}
@TableName("t_user")
@Data
public class User
{
@TableId
private Integer id;
private String username;
private String password;
private Byte sex;
private Byte deleted;
private Date updateTime;
private Date createTime;
}
@NoArgsConstructor
@AllArgsConstructor
@Data
@ApiModel(value = "用户信息")
public class UserDTO implements Serializable
{
@ApiModelProperty(value = "用户ID")
private Integer id;
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "性别 0=女 1=男 ")
private Byte sex;
@ApiModelProperty(value = "删除标志,默认0不删除,1删除")
private Byte deleted;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
@ApiModelProperty(value = "创建时间")
private Date createTime;
}
- ③. 配置类RedisConfig、SwaggerConfig、UserMapper
@Configuration
@Slf4j
public class RedisConfig {
@Bean
public RedisTemplate<String,Serializable> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
RedisTemplate<String,Serializable> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
@Configuration
@EnableSwagger2
public class SwaggerConfig
{
@Value("${spring.swagger2.enabled}")
private Boolean enabled;
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(enabled)
.select()
.apis(RequestHandlerSelectors.basePackage("com.xiaozhi.redis"))
.paths(PathSelectors.any())
.build();
}
public ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("大厂学院2022年小智重新学习班"+"\t"+new SimpleDateFormat("yyyy-MM-dd").format(new Date()))
.description("小智学Redis")
.version("1.0")
.termsOfServiceUrl("https://tangzhi.blog.csdn.net")
.build();
}
}
public interface UserMapper extends BaseMapper<User> {
}
server.port=5555
spring.application.name=redis0511
# ========================logging 日志相关的配置=====================
#日志级别 trace<debug<info<warn<error<fatal
#默认级别为info,即默认打印info及其以上级别的日志,如下:
#系统默认,全局root配置的日志形式,可以注释掉
logging.level.root=warn
#开发人员自己设置的包结构,对那个package进行什么级别的日志监控
logging.level.com.atguigu.redis=info
#开发人员自定义日志路径和日志名称
logging.file.name=D:/mylogs2/logs/redis0511.log
#%d{HH:mm:ss.SSS}――日志输出时间
#%thread――输出日志的进程名字,这在Web应用以及异步任务处理中很有用
#%-5level――日志级别,并且使用5个字符靠左对齐
#%logger- ――日志输出者的名字
#%msg――日志消息
#%n――平台的换行符
#logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
# ========================alibaba.druid相关配置=====================
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.druid.test-while-idle=false
# ========================redis相关配置=====================
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
#spring.redis.host=192.168.111.150
spring.redis.host=192.168.68.143
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1,记得加入单位ms,不然idea报红色
spring.redis.lettuce.pool.max-wait=-1ms
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
# ========================mybatis相关配置===================
mybatis-plus.mapper-locations=classpath:mapper/*.xml
mybatis-plus.type-aliases-package=com.xiaozhi.redis.entities
# ========================swagger=====================
spring.swagger2.enabled=true
# ========================rabbitmq相关配置===================
#spring.rabbitmq.host=127.0.0.1
#spring.rabbitmq.port=5672
#spring.rabbitmq.username=guest
#spring.rabbitmq.password=guest
#spring.rabbitmq.virtual-host=/
# ========================redis 布隆过滤器相关配置=====================
#redis.bloom.url= 192.168.111.147
#redis.bloom.port= 6379
#redis.bloom.init-capacity= 10000
#redis.bloom.error-rate= 0.01
- ⑤. 启动测试Swagger是否OK http://localhost:5555/swagger-ui.html
![在这里插入图片描述](https://img-blog.csdnimg.cn/7b08f5aceb184445a838ce4338dfffbc.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1RaODQ1MTk1NDg1,size_16,color_FFFFFF,t_70)
- ⑥. 查询代码展示
(这里补充一个在工作中实际遇到过的案例:公司某个卡卷活动,送保养给客户,设置的是一个月,最后当那个key消失的时候,我的邮箱就收到了3条报警邮件,我们分析了一下代码,出现了缓存击穿的现象,最后我们使用周志明老师的双端检索机制,使用重量级进行加锁,进行二次if判断,重新查询数据库,将热点代码进行重新设置进去)
public User findUserById(Integer id) {
User user = null;
String key = CACHE_KEY_USER+id;
user = (User) redisTemplate.opsForValue().get(key);
if(user == null) {
user = userMapper.selectById(id);
if(user == null) {
return user;
}else{
redisTemplate.opsForValue().set(key,user);
}
}
return user;
}
public User findUserById2(Integer id) {
User user = null;
String key = CACHE_KEY_USER+id;
user = (User) redisTemplate.opsForValue().get(key);
if(user == null) {
synchronized (UserService.class){
user = (User) redisTemplate.opsForValue().get(key);
if (user == null) {
user = userMapper.selectById(id);
if (user == null) {
return null;
}else{
redisTemplate.opsForValue().setIfAbsent(key,user,7L,TimeUnit.DAYS);
}
}
}
}
return user;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/1069a2e318f74a94813455a57615aea3.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1RaODQ1MTk1NDg1,size_16,color_FFFFFF,t_70)
- ⑦. 进入到redis的客户端,查看到的数据显示不正常,我们要使用–raw进入redis的客户端
127.0.0.1:6379> keys *
1) "user:1005"
2) "user:1002"
3) "user:1003"
4) "user:1004"
5) "user:1001"
127.0.0.1:6379> get user:1002
"{\"@class\":\"com.xiaozhi.redis.entities.User\",\"id\":1012,\"username\":\"\xe5\x94\x90\xe6\x99\xba\",\"password\":\"320813\",\"sex\":0,\"deleted\":0,\"updateTime\":[\"java.util.Date\",1646726918000],\"createTime\":[\"java.util.Date\",1646709021000]}"
127.0.0.1:6379> exit
root@459c7c8679b1:/data# redis-cli --raw
127.0.0.1:6379> get user:1012
{"@class":"com.xiaozhi.redis.entities.User","id":1012,"username":"唐智","password":"320813","sex":0,"deleted":0,"updateTime":["java.util.Date",1646726918000],"createTime":["java.util.Date",1646709021000]}