初学redis分页缓存方法实现
Posted SeptemberNotes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初学redis分页缓存方法实现相关的知识,希望对你有一定的参考价值。
初学redis分页缓存方法实现
使用缓存技术一般是在不经常增删改的数据,我们可以使用缓存技术将第一次请求访问的数据缓存到redis中保存起来,后来的请求的时候首先查询redis数据库是否查询到这些数据,如果存在,则返回数据,如果不存在,则到mysql或其他数据库查询数据返回并保存到redis数据库中。
为什么要采用分页缓存?直接设置缓存,如果数据量大,操作增删改,更新缓存频率高效率低。分页缓存,通过页码设置缓存,可以提高性能。(但是其实不是很好)。
缓存的时候需要考虑的一些问题:
1.新增--删除最后一页缓存(如果倒叙排序,插入数据,第一页改变,后续页列表也都改变,需要删除所有缓存)。
2.修改--更新当前页缓存。
3.删除--更新当前页以及当前页以后的页面的缓存。
上面是分页缓存实现的时候要考虑的一些问题,而我在下面实现的代码并不是这样的,因为我懒得传当前页面cuePage了在add、delete、update的时候,所以,我选择了在add、delete、update的时候都把缓存的分页缓存相关key请理了,更新了分页缓存数据。
@RequestMapping({"/","index"})
public String index(Model model,
@RequestParam(value = "curPage",required = false,defaultValue ="1") Integer curPage){
//每页展示10条数据
int pageSize = 5;
//总数
int totalRows = userService.getUserByTotal();
//计算分页
int totalPages = totalRows / pageSize;
//可能有余页
int left = totalRows % pageSize;
if (left > 0){
totalPages = totalPages + 1;
}
if (curPage < 1 ){
curPage = 1;
}
if (curPage > totalPages ){
curPage = totalPages;
}
//计算查询的开始行
int startRow = (curPage - 1) * pageSize;
Map<String,Object> paramMap = new ConcurrentHashMap<>();
paramMap.put("startRow",startRow);
paramMap.put("pageSize",pageSize);
paramMap.put("curPage",curPage);//第几页
List<User> userList = userService.getUserBypage(paramMap);
System.out.println("curPage:"+curPage);
model.addAttribute("userList",userList);
model.addAttribute("curPage",curPage);
model.addAttribute("totalPages",totalPages);
//跳转到模板页面
return "index";
}
实现类,缓存总页数。
@Override
public int getUserByTotal() {
System.out.println("test:"+userMapper.selectUserByTotal());
//设置key的序列化方式,采用字符串方式,提高可读性
redisTemplate.setKeySerializer(new StringRedisSerializer());
//先从Redis缓存查询
Integer totalRows = (Integer) redisTemplate.opsForValue().get("totalRows");
if (null == totalRows){
synchronized (this){
totalRows = (Integer) redisTemplate.opsForValue().get("totalRows");
if (null == totalRows){
//去mysql数据库查询总数,并保存到redis缓存中
totalRows = userMapper.selectUserByTotal();
redisTemplate.opsForValue().set("totalRows",totalRows);
System.out.println("从mysql数据库获取totalRows");
}
}
}
return totalRows;
}
查询分页缓存,按照查询当前页进行缓存。缓存在redis数据库中的key="curPage1"、key="curPage2"
key="curPage3"、key="curPage*"。
@Autowired
private UserMapper userMapper;
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
@Override
public List<User> getUserBypage(Map<String, Object> paramMap) {
//设置key的序列化方式,采用字符串方式,提高可读性
redisTemplate.setKeySerializer(new StringRedisSerializer());
Integer curPage = (Integer) paramMap.get("curPage");
List<User> userList = (List<User>) redisTemplate.opsForValue().get("curPage"+String.valueOf(curPage));
if (null == userList){
userList = userMapper.selectUserBypage(paramMap);
redisTemplate.opsForValue().set("curPage"+String.valueOf(curPage),userList);
System.out.println("从mysql数据库获取userList");
}
return userList;
}
add。添加成功后,mysql数据库+1,redis缓存数据库需要更新一下数据总数的缓存,mysql数据库数据改变了,之前的redis中的分页缓存就不能用了,则在这里删除分页缓存,等下次最新请求访问后先查询mysql,再保存到redsi中。
@Override
public int addUser(User user) {
//设置key的序列化方式,采用字符串方式,提高可读性
redisTemplate.setKeySerializer(new StringRedisSerializer());
int add = userMapper.insertSelective(user);
if (add > 0){
//添加成功后,mysql数据库+1,redis缓存数据库需要更新一下数据
int totalRows = userMapper.selectUserByTotal();
redisTemplate.opsForValue().set("totalRows",totalRows);
//更新缓存
Set<Object> keys = redisTemplate.keys("curPage"+"*");
redisTemplate.delete(keys);
}
return add;
}
delete。删除成功后,mysql数据库-1,redis缓存数据库需要更新一下数据总数的缓存,mysql数据库数据改变了,之前的redis中的分页缓存就不能用了,则在这里删除分页缓存,等下次最新请求访问后先查询mysql,再保存到redsi中。
@Override
public int deleteUser(Integer id) {
//设置key的序列化方式,采用字符串方式,提高可读性
redisTemplate.setKeySerializer(new StringRedisSerializer());
int delete = userMapper.deleteByPrimaryKey(id);
if (delete > 0){
//删除成功后,mysql数据库-1,redis缓存数据库需要更新一下数据
int totalRows = userMapper.selectUserByTotal();
redisTemplate.opsForValue().set("totalRows",totalRows);
//更新缓存
Set<Object> keys = redisTemplate.keys("curPage"+"*");
redisTemplate.delete(keys);
}
return delete;
}
update。update后mysql数据库数据改变了,之前的redis中的分页缓存就不能用了,则在这里删除分页缓存,等下次最新请求访问后先查询mysql,再保存到redsi中。
@Override
public int updateUser(User user) {
//设置key的序列化方式,采用字符串方式,提高可读性
redisTemplate.setKeySerializer(new StringRedisSerializer());
//boolean b = redisTemplate.delete("curPage"+"*");//
Set<Object> keys = redisTemplate.keys("curPage"+"*");
redisTemplate.delete(keys);
return userMapper.updateByPrimaryKey(user);
}
redisTemplate模糊匹配删除
Set<Object> keys = redisTemplate.keys("curPage"+"*");
redisTemplate.delete(keys);
return userMapper.updateByPrimaryKey(user);
下面这样不行的,当时一直很疑惑,只能更新第一页的缓存,后面页的进行add、delete、update后都没有更新。百度一下,换了这么删除key的方法,是可以的。
edisTemplate.delete("curPage"+"*");//这样不行
上面代码的实现缓存并不是很好,缓存需要优雅的使用,并不是所有的项目都需要缓存技术,在使用缓存之前,需要确认你的项目是否真的需要缓存,使用缓存会引入一定的技术复杂度。笔者在这里只是在学习缓存技术时,学习过程中的一些思考与记录。
以上是关于初学redis分页缓存方法实现的主要内容,如果未能解决你的问题,请参考以下文章