使用Redis sorted set實現集合設置member過期


在我們日常工作中,有許多這種邏輯

例如需要得到最近三分鍾的cache list. 例如我們監控系統需要查詢最近一分鍾的數據。

總結說來就是 需要一個list存儲對象,並且這個對象會無限制增長,需要設置過期.

普遍做法有兩種: 
1.一種就是簡單的list,存儲的對象帶有expireTime,然后定時任務不停的拿到整個list並去除過期的member.

2.一種是把整個list的每個成員都當做一個key來存,然后分別設置超時時間,雖然解決了超時問題,但是顯然這樣實在太過於浪費,而且很多操作都需要得到size或者整個list,那么就需要keys “usercache_”。一旦成員過多,key太多,keys消耗非常大,不推薦.


使用sorted set實現

redis有一個sorted set,就是一個根據score排序的set。仔細一看,極為契合我們的需求! 
話不多說,直接上代碼!

/** * 聚合器 * @author Mingchenchen * */ public class Aggregator { private RedisTemplate<String, Event> redisTemplate; private ZSetOperations<String, Event> zSetOperations; /** * constructor * @param redisTemplate * @param expireMillions */ public Aggregator(RedisTemplate<String, Event> redisTemplate){ this.redisTemplate = redisTemplate; redisTemplate.setKeySerializer(new Serializer()); redisTemplate.setValueSerializer(new EventSerializer()); this.zSetOperations = redisTemplate.opsForZSet(); } /** * 存入一條數據到sorted set * @param key * @param event */ public boolean zset(String key, Event event){ long now = System.currentTimeMillis(); return zSetOperations.add(key, event, now); } /** * 取出整個set的所有記錄 * @param key * @return */ public Set<Event> zgetAll(String key, long expireSec){ long now = System.currentTimeMillis(); long tts = now - expireSec * 1000; //下標用-1才能表示最大值 score和count要用-inf和+inf //return zSetOperations.rangeByScore(key, tts+1, -1); return zSetOperations.rangeByScore(key, tts+1, Long.MAX_VALUE); } /** * 查看匹配數目 * @param key * @param expire:過期時間 單位是秒 * @return */ public long zCount(String key, long expireSec){ long now = System.currentTimeMillis(); long tts = now - expireSec * 1000; //下標用-1才能表示最大值 score和count要用-inf和+inf //return zSetOperations.count(key, tts+1, -1); return zSetOperations.count(key, tts+1, Long.MAX_VALUE); } /** * 刪除一整個policyCache * @param zsetKey */ public void removeCache(String zsetKey){ redisTemplate.delete(zsetKey); } /** * 緩存清理者 */ @SuppressWarnings("unchecked") public void cacheCleaner(){ Cache<String, InstantPolicy> cache = SpringContextUtil.getBean("policyCache", Cache.class); if (cache==null || cache.getAll().isEmpty()) { return; } for (InstantPolicy policy : cache.getAll().values()) { String keyPref = policy.buildKeyPref(); Set<String> policyCacheKeys = redisTemplate.keys(keyPref); if (policyCacheKeys==null || policyCacheKeys.isEmpty()) { return; } //移除過期數據 long now = System.currentTimeMillis(); long tts = now - policy.getDuration() * 1000; for (String key : policyCacheKeys) { zSetOperations.removeRangeByScore(key, 0, tts); } } } private class Serializer implements RedisSerializer<String> { public byte[] serialize(String s) { if (s == null) { return null; } return s.getBytes(); } public String deserialize(byte[] bytes) { if (bytes == null) { return null; } return new String(bytes); } } private class EventSerializer implements RedisSerializer<Event> { public byte[] serialize(Event event) { if (event == null) { return null; } return JSONObject.toJSONBytes(event); } public Event deserialize(byte[] bytes) { if (bytes == null) { return null; } return JSONObject.parseObject(bytes, Event.class); } } }

附: 
sorted set學習資料

http://www.cnblogs.com/stephen-liu74/archive/2012/03/23/2354994.html

http://doc.redisfans.com/sorted_set/zrangebyscore.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM