如何使用redis緩存來實現用戶最近瀏覽的商品列表
首先,我們要弄明白兩個要點:最近瀏覽的商品肯定是一個存和取的兩個操作.好了目前擺在我們面前的有以下幾個問題:
1,最近瀏覽的記錄肯定是需要失效時間的
確定使用緩存,緩存可以設置失效時間(最大設置爲一個月,但是這已經足夠了),如果使用mysql等數據庫,還需要定時任務清除,很明顯是不切合實際的,
2,最近瀏覽的記錄肯定是有個數限制的,不可能記錄所有的瀏覽記錄
目前使用的主流緩存有 memached和redis兩種(原諒無知的我並不清楚其他的),redis有LTRM來修剪,保證存儲的瀏覽的條數;
3,我們需要在哪裏添加保存瀏覽商品的方法
用戶最近瀏覽的商品,肯定是再用戶最近打開商品詳情頁的時候纔算瀏覽,這點毋庸置疑;
4,怎麼保證每次添加的瀏覽的商品列表按着瀏覽的先後順序排序?
每次用戶的瀏覽商品的ID,可以以用戶的ID作爲key,以List作爲value,儲存在redis中,而List是有序的,而且,在使用LRANGE的時候能保證先進後出,後進先出的原則,已達到排列在最前面的商品始終是裏當前最近瀏覽的那個商品;
5,怎麼保證用戶在連續瀏覽同一個商品的時候,不會重複保存商品?
可以使用redis中LREM來移除列表中與參數 value(該商品ID) 相等的元素。同時在使用Lpush重新再List插入最新的瀏覽商品;
6,讀取緩存的時候,又該如何保證分頁?
redis中的LRANGE可以指定獲取指定長度的元素,能夠滿足需要;
下面是簡單的實現思路:
1,儲存用戶瀏覽的商品:
用戶在打開詳情頁的時候,以用戶ID作key,商品的ID做值,以List存入redi緩存中;
在加入添加緩存之前,爲了保證瀏覽商品的 唯一性,每次添加前,使用lrem將緩存的list中該商品ID去掉,在加入,以保證其瀏覽的最新的商品在最前面;
在lpush到redis的List中之後,根據產品需求還需要將該list的前60個數據之外的緩存修剪掉;
最後添加緩存失效時間30天;
2.獲取用戶最近瀏覽的商品列表:
根據用戶的ID及當前的頁數和每頁的個數,來獲取商品緩存;
下面是最後實現的代碼:
public void addMemberResentGoods(Long memberId, Long templateId) {
String key = RedisKeyUtil.generteKeyWithPlaceholder(RedisKeys.MEMBER_RECENT_GOODS, memberId);
//爲了保證瀏覽商品的 唯一性,每次添加前,將list 中該 商品ID去掉,在加入,以保證其瀏覽的最新的商品在最前面
redisService.lrem(key, 1, templateId.toString());
//將value push 到該key下的list中
redisService.lpush(key,templateId.toString());
//使用ltrim將60個數據之後的數據剪切掉
redisService.lTrim(key,0,59);
//設置緩存時間爲一個月
redisService.expire(key,60*60*24*30);
}
2,根據用戶的ID,分頁獲取最近瀏覽的商品: public Map<String,Object> queryMemberResentGoods(Long memberId, int page, int pageSize) {
String key = RedisKeyUtil.generteKeyWithPlaceholder(RedisKeys.MEMBER_RECENT_GOODS, memberId);
//獲取用戶的瀏覽的商品的總頁數;
long pageCount = redisService.llen(key);
//根據用戶的ID分頁獲取該用戶最近瀏覽的50個商品信息
List<String> result = redisService.lrange(key,(page-1)*pageSize,page*pageSize-1);
//拼裝返回
Map<String,Object> map = new HashMap<>();
map.put("result",result);
map.put("pageCount",(pageCount%pageSize == 0 ? pageCount/pageSize : pageCount/pageSize+1));
return map;
}