redis缓存html图片,使用 Redis 缓存来实现用户最近浏览的商品列表

背景

最近在做商品的浏览历史,使用 Redis 中的 Map 来实现。将用户访问的所有商品编码存在 Map 里面,key为商品编码,value为浏览时间,取的时候把所有的商品编码拿出来,查询数据库后组装好数据及浏览时间,在 List 中将数据内存排序、分页后返回。

因为在购物车和用户界面来回切换,用户界面展示的足迹数量使用的是浏览足迹分页的totalCount,频繁操作拿到Redis中的数据查询后进行分页返回,导致测试环境炸掉。后面分析了一波,才使用 SortedSet 来重构。

实现工具类

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.connection.RedisZSetCommands;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.data.redis.core.ZSetOperations;

import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import java.util.Set;

/**

* @author leizige

*/

@Component

public class RedisUtil{

@Resource

private ZSetOperations zSetOperations;

private final Long EMPTY = 0L;

/**

* 添加一个元素, zset与set最大的区别就是每个元素都有一个score,因此有个排序的辅助功能; zadd

* key,value已存在,score覆盖

*

* @param key

* @param value

*/

public boolean add(String key, String value, double score) {

return zSetOperations.add(key, value, score);

}

/**

* 查询集合中指定顺序的值 zrevrange

*

* 返回有序的集合中,score大的在前面

*

* @param key

* @param offset

* @param count

* @return

*/

public Set reverseRangeByScore(String key, int offset, int count) {

return zSetOperations.reverseRangeByScore(key, 1, Long.MAX_VALUE, (offset - 1) * count, count);

}

/**

* ZCARD key

*

* 返回有序集 key 的基数。

*

* 可用版本:

* >= 1.2.0

* 时间复杂度:

* O(1)

* 返回值:

* 当 key 存在且是有序集类型时,返回有序集的基数。

* 当 key 不存在时,返回 0

*

* @param key

* @return

*/

public Long zCard(String key) {

return zSetOperations.zCard(key);

}

/**

* 删除元素 zrem

*

* @param key

* @param value

*/

public Long remove(String key, String value) {

return zSetOperations.remove(key, value);

}

/**

* 移除有序集 key 中,指定排名(rank)区间内的所有成员。

*

* 区间分别以下标参数 start 和 stop 指出,包含 start 和 stop 在内。

*

* 下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。

* 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。

* 可用版本:

* >= 2.0.0

* 时间复杂度:

* O(log(N)+M), N 为有序集的基数,而 M 为被移除成员的数量。

*

* @param key

* @param start

* @param end

* @return 被移除成员的数量

*/

public Long removeRange(String key, long start, long end) {

return zSetOperations.removeRange(key, start, end);

}

}

实现原理

为了保证 Redis 中数据量的大小,限制每个用户足迹最多保存 100 条记录,最长保存 30 天。

新增足迹

使用System.currentTimeMillis()作为SortedSet的score来排序,并且 Set 天然支持去除重复数据,使用 ItemCode+LocalDate.now() 作为key,可以避免当天重复浏览一个商品,但Redis中只保存一条记录。

@Value("${browsingHistory.maxSize}")//在配置文件中配置最大缓存数量

private Long maxSize;

private final static Long MAX_SIXE = 100L;

/**

* 默认过期时长,单位:秒

*/

private final static int DEFAULT_EXPIRE = 60 * 60 * 24 * 30;

public String set(String key,String value) {

redisUtil.add(key, value,System.currentTimeMillis());

Long size = redisUtil.zCard(key);

if(null == maxSize){

maxSize = MAX_SIXE;

}

//如果最大数量超过配置的,就把超出的那一个干掉

if(size > maxSize){

Long removeRange = redisUtil.removeRange(key, 0,0);

}

redisUtils.expire(key, DEFAULT_EXPIRE);

return key;

}

查询足迹

先查看该用户有没有浏览历史,数量为0直接返回

在从 Redis 中取出数据的时候就进行分页,避免在内存中进行分页操作。

public Pager queryAll(String key,int currentPage, int pageSize) {

Long size = redisUtil.zCard(key);

if (null == size || size.equals(EMPTY_SIZE)) {

return new Pager<>();

}

//这里将缓存中的商品编码拿出来,组装商品信息后返回

Set values = redisUtil.reverseRangeByScore(key, currentPage, pageSize);

return new Pager<>(newItemResDtoList, size, pageSize, currentPage);

}

清空足迹

public void removeAll(String key) {

redisUtils.delete(key);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值