1.需求分析
近期项目上使用redis进行用户历史记录的定期保存,很明显是一对多的关系,看我存的redis
2.项目难点
同一短剧id只保留最新的一个集数记录,需定时刷新;数据超过7天的需定时清理。
3.方案一开发思路
果断选择list操作,发现定时无法做,又改成了zset但多数据存储又不方便,最终选择list在里面添加时间字段,循环拿出时间字段与当前时间进行比较。
方案一:
/**
* ran
* 用户历史记录
*/
@RestController
@RequestMapping("/tb-user-history")
public class TbUserHistoryController {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* Ran
* 方案一:利用时间过期策略删除数据
* 保存用户记录到redis,适用于各平台数据
*/
@PostMapping("/save")
public Result saveredis(@RequestBody TbUserHistoryDTO historyDTO) throws JsonProcessingException {
if (historyDTO.getUid() == null || historyDTO.getUid() == "") return Result.errCode_400();
// 设置统一时间格式
String setDate = LocalDateTime.now().toString();
historyDTO.setCreateTime(setDate);
String uid = historyDTO.getUid();
historyDTO.getCategoryId();//短剧id
List<TbUserHistoryDTO> list = new ArrayList<>();
list.add(historyDTO);
ObjectMapper objectMapper = new ObjectMapper();
// 根据uid取出list集合,遍历list集合做判断
List<String> redisUidList = redisTemplate.opsForList().range(uid, 0, -1);// 取出0,最后
System.out.println("长度" + redisUidList.size());
// 遍历list集合,取出所有元素
// 遍历列表
ObjectMapper jsonObject = new ObjectMapper();
if (redisUidList.size() != 0) {
for (int i = 0; i < redisUidList.size(); i++) {
String s = redisUidList.get(i);//两条string类型的,list数据
JsonNode jsonNode = jsonObject.readTree(s);//转为json对象
int shortplayId = jsonNode.get(0).get("shortplayId").asInt();//短剧id
if (historyDTO.getShortplayId() == shortplayId) {
// 根据下标删除这条数据
redisTemplate.opsForList().remove(uid, i, jsonNode.toString());
//保存新数据
String strJson = objectMapper.writeValueAsString(list);
redisTemplate.opsForList().leftPush(uid, strJson);
return Result.ok();
}
// 时间转为string
String redisCreateTime = jsonNode.get(0).get("createTime").asText();
System.out.println("redis中的时间" + redisCreateTime);
// // 定义日期时间格式
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
//把redis里面的时间格式放进去,转换一下
LocalDateTime createTime = LocalDateTime.parse(redisCreateTime, formatter);
System.out.println("redis转换后的时间===" + createTime);
获取当前时间
LocalDateTime now = LocalDateTime.now();
System.out.println("后期时间===" + now);
计算时间差 用天数计算
long daysBetween = ChronoUnit.DAYS.between(createTime, now);
System.out.println("时间差" + daysBetween);
// 判断是否大于7天
if (daysBetween > 7)
// 删除这条数据
redisTemplate.opsForList().remove(uid, i, jsonNode.toString());
System.out.println("删除下标为" + i);
//如果短剧信息接口相等
}
}
// list添加
String strJson = objectMapper.writeValueAsString(list);//转成json
redisTemplate.opsForList().leftPush(uid, strJson);//存入redis
return Result.ok();
}
方案二开发思路
如果对时间过期没有强制要求可以使用裁剪list长度,保留用户最新的50条记录,因为redis每过来一条记录都是从下标0开始添加,这样50条以后的记录就会被删掉,确保冗余数据不易过大。
方案二:
/**
* Ran
* 方案二
* 保留用户前50条数据
*/
@PostMapping("/save2")
public Result saveredis2(@RequestBody TbUserHistoryDTO historyDTO) throws JsonProcessingException {
if (historyDTO.getUid() == null || historyDTO.getUid() == "") return Result.errCode_400();
// 设置统一时间格式
String uid = historyDTO.getUid();
historyDTO.getCategoryId();//短剧id
List<TbUserHistoryDTO> list = new ArrayList<>();
list.add(historyDTO);
ObjectMapper objectMapper = new ObjectMapper();
// 根据uid取出list集合,遍历list集合做判断
List<String> redisUidList = redisTemplate.opsForList().range(uid, 0, -1);// 取出0,最后
System.out.println("长度" + redisUidList.size());
// 遍历list集合,取出所有元素
// 遍历列表
ObjectMapper jsonObject = new ObjectMapper();
if (redisUidList.size() != 0) {
for (int i = 0; i < redisUidList.size(); i++) {
String s = redisUidList.get(i);//两条string类型的,list数据
JsonNode jsonNode = jsonObject.readTree(s);//转为json对象
int shortplayId = jsonNode.get(0).get("shortplayId").asInt();//短剧id
if (historyDTO.getShortplayId() == shortplayId) {
// 根据下标删除这条数据
redisTemplate.opsForList().remove(uid, i, jsonNode.toString());
//保存新数据
String strJson = objectMapper.writeValueAsString(list);
redisTemplate.opsForList().leftPush(uid, strJson);
// 截取
redisTemplate.opsForList().trim(uid, 0, 49);//只保留前50条数据
return Result.ok();
}
}
}
// list添加
String strJson = objectMapper.writeValueAsString(list);//转成json
redisTemplate.opsForList().leftPush(uid, strJson);//存入redis
redisTemplate.opsForList().trim(uid, 0, 49);//只保留前50条数据
return Result.ok();
}
(,,´•ω•)ノ"(´っω•`。)牧码亲亲贝贝