通过redis进行缓存分页,通过SCAN扫描进行缓存更新

问题:当我们要添加缓存时,如果我们用了PageHelper时,PageHelper只会对查询语句有效(使用到sql的查询),那么如果我们把查询到的数据都添加到缓存时,就会无法进行分页;

此时我们选择将分页后的数据加入缓存,前端传入page和count表示查询页数和个数,我们将其拼接到查询物品key作为唯一key添加进入redis中,每次查询不同页数都会添加缓存,

但是,当我们数据进行更新时可能会导致所有添加的缓存都会与数据库不符合,所以每次更新我们都要将缓存进行删除操作,下次查询再次进行缓存~

下面我们使用PageHelper和redis做缓存分页

每次查询页码数和每页数量和对应的key拼接起来存入redis中、

下面我们使用redisClient存入redis,通过redisTemplate进行模糊扫描扫描对于key下各个页码的缓存,当内容进行更新时删除掉之前的缓存,当我们再次请求时才会去加缓存

直接看代码

👇

@Service

public class AAAAServiceImpl implements aaaaService {

@Autowired

private TIntegralPrizesMapper integralPrizesMapper;

@Resource

private RedisTemplate<String,String> redisTemplate;

@Autowired

private IRedisClient redisClient;

@Autowired

private AAAAOrderMapper aaaaMapper;

@Autowired

private AAAAServiceImpl aaaaService;

public static final String XXX_KEY="XXX_AS_";

@Override

public void addPrizes(AAAA aaaa) {

aaaa.setId(UUID.randomUUID().toString().replace("-",""));

aaaa.setCreateTime(new Date());

aaaa.setUpdateTime(new Date());

// 处理传入数据

aaaaMapper.addPrizes(aaaa);

//查询以XXX_KEY+aaaa.getxx()开头的所有缓存(count表示要查询的数量,我们可以大概设置一个最大值(不要太大,不然影响性能))

ScanOptions options=ScanOptions.scanOptions().match(XXX_KEY+aaaa.getxx()+"*").count(100).build();

Cursor<byte[]> cursor=redisTemplate.getConnectionFactory().getConnection().scan(options);

//循环查询数据

while (cursor.hasNext()){

//将得到的字符组转换为String

String key=new String(cursor.next());

//删除缓存

redisClient.delete(key);

}

try {

//关闭游标

cursor.close();

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public String deleteXX(AAAADTO aaaaDTO) {

//更新时间

aaaaDTO.setUpdateTime(new java.util.Date());

aaaaMapper.deleteSXPrizes(aaaaDTO);

ScanOptions options=ScanOptions.scanOptions().match(XXX_KEY+aaaDTO.getxx()+"*").count(100).build();

Cursor<byte[]> cursor=redisTemplate.getConnectionFactory().getConnection().scan(options);

while (cursor.hasNext()){

String key=new String(cursor.next());

redisClient.delete(key);

}

try {

cursor.close();

} catch (IOException e) {

e.printStackTrace();

}

return msg;

}

@Override

public PageInfo<XXXPrizes> selectXXX(AAADTO aaaDTO) {

//对于每一页设置唯一的key存入redis

String key = XXX_KEY+aaaDTO.getxx()

+"page="+aaaDTO.getPage()

+"count="+aaaDTO.getCount();

//查询缓存

String tagsStr = redisClient.get(key);

if (StrUtil.isNotBlank(tagsStr)) {

//将String解析

return JSON.parseObject(tagsStr, new TypeReference<PageInfo<XXXPrizes>>() {});

}

//pc进行分页

PageHelper.startPage(aaaDTO.getPage(),aaaDTO.getCount());

List<TIntegralPrizes> tX = aaaMapper.selectxxx(aaaDTO);

PageInfo<XXXPrizes> pageInfo=new PageInfo<>(tX);

//解决缓存穿透问题()当数据库为空时,给缓存一个值,使其不会一直访问数据库

//因为这里我们set的值为pageInfo所以不用关心这个问题

//转换为json字符串

//存入缓存

String strList = JSON.toJSONString(pageInfo);

redisClient.set(key, strList, 5 * ((int) (Math.random() * 4) + 1), TimeUnit.MINUTES);

return pageInfo;

}

}

以上就是一个缓存分页的例子,当然做缓存分页方法有很多,此方法仅供参考

相关推荐
Cyan_RA919 小时前
SpringMVC @RequestMapping的使用演示和细节 详解
java·开发语言·后端·spring·mvc·ssm·springmvc
MarkHard1231 天前
如何利用redis使用一个滑动窗口限流
数据库·redis·缓存
hdsoft_huge1 天前
Java & Spring Boot常见异常全解析:原因、危害、处理与防范
java·开发语言·spring boot
island13141 天前
【Redis#10】渐进式遍历 | 数据库管理 | redis_cli | RES
数据库·redis·bootstrap
心想事成的幸运大王1 天前
Redis的过期策略
数据库·redis·缓存
AD钙奶-lalala1 天前
SpringBoot实现WebSocket服务端
spring boot·后端·websocket
毕设源码-朱学姐1 天前
【开题答辩全过程】以 4S店汽车维修保养管理系统为例,包含答辩的问题和答案
java·spring boot·汽车
BXCQ_xuan1 天前
软件工程实践二:Spring Boot 知识回顾
java·spring boot·后端
wuxuanok1 天前
SpringBoot -原理篇
java·spring boot·spring
云动雨颤1 天前
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
数据库·spring boot·tomcat