最近公司由于业务中需要将帖子,评论,视频等加入缓存,以前没怎么操作过缓存得分页,看了一下源码,这里主要用到redis两个数据类型:SortedSet(Zset)和hash两种数据类型,至于为什么选择这两个后面再说。
SortedSet(Zset)是有序的集合类型,但是它和LinkedHashSet还不一样,LinkedHashSet维护的是插入时的顺序,而SortedSet维护的是元素之间大小关系的顺序(比如升序、降序等,是根据大小关系来维护顺序的),简单就是说我们可以根据我们需求对其排序,有分页就肯定有排序所以这里我选择的用sortset。
这里主要用到该数据类型的Zrevrangebyscore和zadd两种类型,zadd负责向里面插入对应数据,Zrevrangebyscore负责分页。
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);
}