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

}

}

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

相关推荐
小北方城市网11 小时前
Redis 分布式锁高可用实现:从原理到生产级落地
java·前端·javascript·spring boot·redis·分布式·wpf
毕设源码-钟学长12 小时前
【开题答辩全过程】以 基于SpringBoot的智能书城推荐系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
雨中飘荡的记忆13 小时前
Spring AI Gateway:从入门到实战,打造智能AI服务网关
人工智能·spring·gateway
挺6的还13 小时前
18.缓存
redis
a程序小傲14 小时前
得物Java面试被问:RocketMQ的消息轨迹追踪实现
java·linux·spring·面试·职场和发展·rocketmq·java-rocketmq
青春男大14 小时前
Redis和RedisTemplate快速上手
java·数据库·redis·后端·spring·缓存
Script kid14 小时前
Redis的Java客户端
java·数据库·redis
heartbeat..14 小时前
Redis 哨兵模式:原理、配置与故障排查全解析
java·运维·数据库·redis
风景的人生15 小时前
请求参数相关注解
spring·mvc
不吃香菜学java16 小时前
springboot左脚踩右脚螺旋升天系列-整合开发
java·spring boot·后端·spring·ssm