整合redis缓存

整合redis缓存

分布式锁的实现和解析

(12条消息) 分布式锁之Redis实现_kuan_sun的博客-CSDN博客_redis锁的实现

整合步骤:

  1. 下载redis,解压,修改配置文件(redis.windows.conf)
  2. 导入redis启动依赖
  3. 创建redis配置类 (主要是对于kv的序列化和反序列化)
  4. 启动redis-server.exe (redis服务)(同时也可以通过指定配置文件进行启动—集群)
  5. 启动redis-cli.exe (操作客户端)

注意:

  • HashMap不能设置过期时间!!!
  • 使用device:No_001:Name 的方式来存放K
  • 在存放value(对象)时 需要导入FastJson来进行操作
  • redis操作都在redisTemplate中,有很多操作,需要熟悉

引入缓存可能导致的问题(目前能想到的)

  1. 在修改后,需要对缓存进行操作,不然缓存中的数据有误
    1. 在修改时判断是否有缓存 ?
      1. 有:改缓存,利用缓存来修改持久层的(可以慢慢操作,在缓存失效之前操作完)
      2. 没有:修改持久层的,存缓存(有修改,一定马上会用到)
  2. 删除两边都得删
  3. 新增时添加缓存(新增也一定马上会用到)
  4. 查找时:如果缓存有,是否需要更新过期时间?
  5. 分页需要做缓存吗,怎么做?

可以改进的方向:

  1. redis集群
    1. 利用redis中String来做
      1. setnx device:NO_001_Lock 1 ex time

        Untitled

      2. 0则再用,重试请求;1进行业务操作

      3. 设置过期时间,避免设置锁后宕机死锁 时间需合适

        1. 太短:还没操作完就释放了
        2. 太长:已经操作完了 还锁着
      4. 解决:线程守护

        1. 设置一定时长
        2. 例设置10s 8s时判断是否还在执行? 延长 : 不延长
1
2
3
4
5
<!-- redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.jcDemo.config;

import com.alibaba.fastjson2.support.spring.data.redis.FastJsonRedisSerializer;
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.*;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
*@author:gao_quansui
*@user:ASUS
*@date:2022/9/28- 13:41
*@projectName:jc_demo
*/
@Configuration
public class RedisConfig {

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
FastJsonRedisSerializer<Object> objectFastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// 自定义的RedisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置key的序列化方法
redisTemplate.setKeySerializer(new StringRedisSerializer());
// 核心的设置 1.2.36版本自动提供
redisTemplate.setValueSerializer(objectFastJsonRedisSerializer);
// 对hash的序列化操作设置
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(objectFastJsonRedisSerializer);
// 注册到工程类
redisTemplate.setConnectionFactory(factory);
return redisTemplate;
}

@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}

@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}

@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}

@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}

@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package com.jcDemo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jcDemo.commom.CommonException;
import com.jcDemo.entity.entities.Device;
import com.jcDemo.entity.res.PageResult;
import com.jcDemo.entity.res.Result;
import com.jcDemo.entity.res.ResultCode;
import com.jcDemo.service.device.DeviceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
*@author:gao_quansui
*@user:ASUS
*@date:2022/9/23- 10:51
*@projectName:jc_demo
*/
@Slf4j
@Api(tags = "设备管理")
@RestController
@RequestMapping("/api/device")
public class DeviceController {

@Autowired
DeviceService deviceService;

@Resource
RedisTemplate redisTemplate;

@ApiOperation("查找所有设备")
@GetMapping("/getDevices")
public Result getDevices(@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize) {
PageResult pr = null;
try {
Page page = PageHelper.startPage(pageNum, pageSize);
List<Device> devices = deviceService.getDevices();

pr = new PageResult(page.getTotal(), devices);
log.info("pageNum:{},pageSize:{}", pageNum, pageSize);
} catch (CommonException e) {
e.printStackTrace();
return new Result(ResultCode.EMPTY);
}
return new Result(ResultCode.SUCCESS, pr);
}

//设备编号查询
@ApiOperation("查找设备ByNo")
@GetMapping("/getDeviceByNo/{no}")
public Result getDeviceByNo(@PathVariable("no") String no) throws CommonException {
Device device = null;
try {
if (redisTemplate.hasKey("devices:" + no)) {
log.info("重置时间->devices:{}", no);
redisTemplate.expire("devices:" + no, 300, TimeUnit.SECONDS);
log.info("从redis取出来的devices:{}", no);
device = JSON.parseObject(String.valueOf(redisTemplate.opsForValue().get("devices:" + no)), Device.class);
} else {
log.info("从mysql取出来的{}", no);
//mysql没有抛异常 下面捕获返回空
device = deviceService.getDeviceByNo(no);
//取出来存入缓存
redisTemplate.opsForValue().set("devices:" + no, JSON.toJSONString(device), 300, TimeUnit.SECONDS);
}
return new Result(ResultCode.SUCCESS, device);
} catch (CommonException e) {
e.printStackTrace();
return new Result(ResultCode.EMPTY);
}
}

//查询
@ApiOperation("头部查找")
@GetMapping("/searchDevice")
public Result searchDevice(@RequestBody Device device) {
List<Device> devices;
try {
devices = deviceService.searchDevice(device);
return new Result(ResultCode.SUCCESS, devices);
} catch (CommonException e) {
e.printStackTrace();
return new Result(ResultCode.EMPTY);
}
}

@ApiOperation("更新设备")
@PostMapping("/updateDevice")
public Result updateDevice(@RequestBody Device device) throws ParseException {
if (deviceService.updateDevice(device) == 1) {
//更新成功后判断是否有缓存 有就换
if (redisTemplate.hasKey("devices:" + device.getDeviceNo())) {
Boolean delete = redisTemplate.delete("devices:" + device.getDeviceNo());
if (delete) {
redisTemplate.opsForValue().set("devices:" + device.getDeviceNo(), JSON.toJSONString(device), 300, TimeUnit.SECONDS);
} else {
log.warn("缓存更新失败,请检查!");
}
} else {
redisTemplate.opsForValue().set("devices:" + device.getDeviceNo(), JSON.toJSONString(device), 300, TimeUnit.SECONDS);
}
return new Result(ResultCode.SUCCESS);
} else {
return new Result(ResultCode.ERROR);
}
}

@ApiOperation("删除设备")
@DeleteMapping("/delete/{no}")
public Result deleteDeviceById(@PathVariable("no") String no) {
if (deviceService.deleteDeviceByNo(no) == 1) {
//删除成功后处理redis
if (redisTemplate.delete("devices:" + no)) {
log.warn("缓存删除成功");
} else {
//缓存删除失败 or 从select里面取的数据,没有进redis 直接删除也会打印log
log.warn("缓存删除失败,请检查!");
}
return new Result(ResultCode.SUCCESS);
} else {
return new Result(ResultCode.ERROR);
}
}

@ApiOperation("新增设备")
@PostMapping("/insert")
public Result insertDevice(@RequestBody Device device) throws ParseException {
if (deviceService.insertDevice(device) == 1) {
redisTemplate.opsForValue().set("devices:" + device.getDeviceNo(), JSON.toJSONString(device), 300, TimeUnit.SECONDS);
return new Result(ResultCode.SUCCESS);
} else {
return new Result(ResultCode.ERROR);
}
}
}