通过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;

}

}

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

相关推荐
流烟默1 天前
SSE 实战:在 SpringBoot + Vue 项目中零依赖实现轻量级实时消息推送
vue.js·spring boot·后端·sse
七夜zippoe1 天前
Spring AI 是什么?Java 工程师的 AI 开发第一站
java·人工智能·spring·ai·开发
ly76891 天前
Spring Boot 集成 PostgreSQL 的连接池调优:HikariCP、prepared statement 与服务器资源边界
spring boot·postgresql·hikaricp·连接池调优
wangjialelele1 天前
一文梳理 Spring Cloud 核心组件:Eureka、Nacos、OpenFeign、LoadBalancer 与 Gateway
java·spring boot·spring·spring cloud·微服务·nacos
萧瑟余晖1 天前
Spring Security综合实战与安全加固详解
java·安全·spring
imDwAaY1 天前
操作系统如何管理程序运行?从线程、进程到内存隔离与用户态切换:CS162 Note2
android·java·redis
CarIise1 天前
Spring MVC 请求参数绑定与常用注解2
java·spring·mvc
七夜zippoe1 天前
Spring Boot 接通义千问:从拿 Key 到第一个对话接口跑通(保姆级)
java·spring boot·后端
Nebula_g1 天前
SpringBoot企业级实战项目—云禾外卖—SpringBoot常用注解解析
java·网络·数据库·spring boot·后端·spring·javase
企业数字化笔记1 天前
租户停用后数据和任务怎么处理?冻结、恢复与保留策略的实现
android·java·spring boot