最近公司由于业务中需要将帖子,评论,视频等加入缓存,以前没怎么操作过缓存得分页,看了一下源码,这里主要用到redis两个数据类型:SortedSet(Zset)和hash两种数据类型,至于为什么选择这两个后面再说。
SortedSet(Zset)数据类型SortedSet(Zset)是有序的集合类型,但是它和LinkedHashSet还不一样,LinkedHashSet维护的是插入时的顺序,而SortedSet维护的是元素之间大小关系的顺序(比如升序、降序等,是根据大小关系来维护顺序的),简单就是说我们可以根据我们需求对其排序,有分页就肯定有排序所以这里我选择的用sortset。
这里主要用到该数据类型的Zrevrangebyscore和zadd两种类型,zadd负责向里面插入对应数据,Zrevrangebyscore负责分页。
hash数据类型hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
思路:主要思路就是在数组中放入需要分页的key和排序的元素,在hash存放key所对应对象详细信息。
排序测试第一步:向hash中插入数据对象。每一个对象都有一个uuid(为了模拟数据库表对应的主键),同时插入数据时候向SortedSet member属性插入对应对象的uuid和sort插入需要排序的字段(排序的一个属性,这里先用1234排序测试)
写个测试类测试一下
public static void main(String[] args) { //存数据 Jedis jedis = new Jedis("ip", "port", 10000); jedis.auth("123456"); jedis.select(9); for (int i = 0; i < 10; i++) { String s = IdGenerator.generateId(); for (int j = 10 - i; j > 0; j--) { System.out.println(j); //数组中存值 j:排序值,s:对应数组里key jedis.zadd("list", j, s); break; } Date date = new Date(); SolrBean solrBean = new SolrBean(); solrBean.setId(s); solrBean.setContent(DateUtil.formatDate(date)); JSONObject jsonObject = JSONObject.fromObject(solrBean); Long test = jedis.hset("test", s, jsonObject.toString()); boolean d = test >= 0; } //分页取数据 Set set = jedis.zrevrangeByScore("list", "+inf", "-inf",2,5); System.out.println(set); }测试结果:
设置的是从第二个开始倒叙从大到小查,查询五个,五个对应的对象的id分别是b2cca951b81c437f9d4cf7a2a81f09a8, cf71a2a1a6764e76ad82975be90fdb5b, 28655e95aab34abf9f97399a819c713e, 3ad0375058ba4f699982dc1b1384303d, dd18a190a20d44ad802b96ddce848ee6,可以在图里看到刚好是倒叙排列
实际应用: 工具类封装: package com.citcc4.traffic.common.cache;import com.alibaba.fastjson.JSONObject;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.Set;public class VideoInfoCache { private static JedisPool jedisPool; private int index; public VideoInfoCache(JedisPool pool, int index) { this.jedisPool = pool; this.index = index; } /** * 存值 * @param key * @param imei * @param info * @return */ public boolean setVideoInfo(String key,String imei ,VideoInfo info) { if (info == null || key == null) { return false; } String json = JSONObject.toJSONString(info); try (Jedis jedis = jedisPool.getResource()) { jedis.select(index); //同时像链表加索引 Long list = jedis.zadd("video-list:"+imei, info.getUploadTime(), key); Long test = jedis.hset("video-info", key, json); System.out.println(list + "--------------" + test + "---------key---" + key); return true; } catch (Exception e) { e.printStackTrace(); } return false; } /** * 获取key对应值数量 * @param imei * @return */ public Integer getSize( String imei) { try (Jedis jedis = jedisPool.getResource()) { jedis.select(index); Long zcard = jedis.zcard("video-list:" + imei); return zcard.intValue(); } catch (Exception e) { e.printStackTrace(); } return 0; } /** * 分页取值 * @param limit 每次查几条 * @param offset 当前页*limit * @param imei * @return */ public List listVideoInfoWithPage(int limit, int offset, String imei) { try (Jedis jedis = jedisPool.getResource()) { jedis.select(index); Set list = jedis.zrevrangeByScore("video-list:"+imei, "+inf", "-inf", offset, limit); List infoList = new ArrayList(); if (list != null && list.size() > 0) { Map map = jedis.hgetAll("video-info"); for (String s : list) { //根据s取值 String json = map.get(s); VideoInfo videoInfo = JSONObject.parseObject(json, VideoInfo.class); //注意查询出来值不要在这里筛选,否则出来值会变少,筛选的时候直接在存值时候筛选 infoList.add(videoInfo); } } return infoList; } catch (Exception e) { } return null; }} 代码中应用:存值:
@RequestMapping(value = "/moveVideo2Redis", method = RequestMethod.POST) public Object moveVideo2Redis() { UserOrderInfoEntityExample userOrderInfoEntityExample=new UserOrderInfoEntityExample(); UserOrderInfoEntityExample.Criteria criteria1 = userOrderInfoEntityExample.createCriteria(); criteria1.andVideoIdIsNotNull(); List userOrderInfoEntities = userOrderInfoEntityMapper.selectByExample(userOrderInfoEntityExample); List list =new ArrayList(); if (CollectionUtil.isNotEmpty(userOrderInfoEntities)){ for (UserOrderInfoEntity userOrderInfoEntity : userOrderInfoEntities) { list.add(userOrderInfoEntity.getVideoId()); } } CapVideoEntityExample capVideoEntityExample=new CapVideoEntityExample(); CapVideoEntityExample.Criteria criteria = capVideoEntityExample.createCriteria(); //criteria.andDelFlagEqualTo("0"); criteria.andVideoIdNotIn(list); List capVideoEntities = capVideoEntityMapper.selectByExample(capVideoEntityExample); if (CollectionUtil.isNotEmpty(capVideoEntities)){ for (CapVideoEntity capVideoEntity : capVideoEntities) { VideoInfo videoInfo=new VideoInfo(); videoInfo.setVideoid(capVideoEntity.getVideoId()); videoInfo.setImei(capVideoEntity.getDeviceId()); videoInfo.setUrl(capVideoEntity.getVideoFileUrl()); videoInfo.setAddress(capVideoEntity.getVideoAddress()); videoInfo.setGps(capVideoEntity.getLocation()); videoInfo.setUploadTime(capVideoEntity.getSnapEndDate().getTime()); videoInfo.setVideoSize("25"); videoInfo.setVideoLength("17"); VideoInfoCache videoInfoCache=new VideoInfoCache(jedisPool,7); if (StringUtils.isNotEmpty(capVideoEntity.getVideoId())){ videoInfoCache.setVideoInfo(capVideoEntity.getVideoId(),capVideoEntity.getDeviceId(),videoInfo); } } } return new JsonResult(200, null, "修改成功!"); } 取值: @RequestMapping(value = "/v3/video/history/list", method = RequestMethod.GET) public Object listAll(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") Integer offset, @RequestParam(name = "limit", defaultValue = "10") Integer limit) { // 获取用户信息 String token = request.getHeader("token"); JsonResult tokenMesage = (JsonResult) tokenService.checkToken(token); if (tokenMesage.getData() == null) { return tokenMesage; } // 获取用户信息 UserEntity userEntity = (UserEntity) tokenMesage.getData(); CloudMirrorEntityExample mirrorExample = new CloudMirrorEntityExample(); CloudMirrorEntityExample.Criteria criteria = mirrorExample.createCriteria(); criteria.andUserIdEqualTo(userEntity.getUserId()); // 查询用户绑定云镜信息 List entityList = null; List videoInfos=null; int num=0; try { entityList = userService.findUserMirrorInfo(mirrorExample); if (CollectionUtil.isNotEmpty(entityList)){ String deviceId = entityList.get(0).getDeviceId(); VideoInfoCache videoInfoCache =new VideoInfoCache(jedisPool,7); videoInfos = videoInfoCache.listVideoInfoWithPage(limit, offset, deviceId); num=videoInfoCache.getSize(deviceId); logger.info(num); } } catch (BusinessException e) { e.printStackTrace(); logger.info(e.getMessage()); } return new JsonResult(200,videoInfos,"",num); }