1 需求
要往redis存取List< Object>。
2 條件
1)Object:是一個UserEvent對象,對應(yīng)3個字段:
Integer productId;
String eventCode;
Long timestamp;
2)要求
每個key里存取對象個數(shù)不超過xx個。
超過xx個,則剔除早期加入的對象數(shù)據(jù)。
備注:存之前的每個userEvent對象都是不一樣的。
3)使用zset實(shí)現(xiàn)。
3 zset使用原理
1)zset是有一個score參數(shù),這個分?jǐn)?shù)是zset存儲結(jié)構(gòu)的順序依據(jù)。可以按分?jǐn)?shù)從小到大查詢,也可以逆序查詢。
2)因?yàn)楫?dāng)前場景,UserEvent對象的timestamp參數(shù)是一個時間戳,是對象產(chǎn)生的時間,可以用來做剔除早期數(shù)據(jù)的規(guī)則使用。使用這個參數(shù)作為zest的分?jǐn)?shù)。
4 代碼實(shí)現(xiàn)——存
1)思路
把對象的三個字段進(jìn)行拼接,作為一個String類型的value。示例:productId,eventCode,timestamp
108634,1,1623136194
使用時間戳作為分?jǐn)?shù),主要分?jǐn)?shù)是double類型。long型時間戳可以進(jìn)行轉(zhuǎn)換成double。
ps:2038年前時間戳都是可以使用的。:p
/*** 測試redis的zset*/@Testpublic void testRedisZset() {JedisPool jedisPool = new JedisPool("127.0.0.1", 6379);Jedis jedis = jedisPool.getResource();Map<String, Double> map = Maps.newHashMap();Map<String, Double> map2 = Maps.newHashMap();Map<String, Double> newMap = Maps.newHashMap();map.put("121624,1,1623136190", 1623136190.0);map.put("105916,2,1623136191", 1623136191.0);map2.put("107770,1,1623136192", 1623136192.0);map2.put("105916,2,1623136193", 1623136193.0);map2.put("105917,2,1623136193", 1623136193.0);jedis.zadd("user12", map);jedis.zadd("user12", map2);//查詢添加后的總個數(shù) 5個int oldCount = jedis.zcard("user12").intValue();newMap.put("108634,1,1623136194", 1623136194.0);newMap.put("108634,3,1623136195", 1623136195.0);newMap.put("108635,3,1623136195", 1623138109.0);newMap.put("108638,3,1623136195", 1623138120.0);//需要新加入 4個int newCount = 4;//要求value容量是6個int size = 6;int diff = oldCount + newCount - size;if (diff > 0) {//移除得分最小的前3個 第0-2個jedis.zremrangeByRank("user12", 0, diff - 1);//再追加新的jedis.zadd("user12", newMap);} else {//還沒有加滿,直接追加jedis.zadd("user12", newMap);}//查詢value zrange得分從小到大排序 取size個Set<String> user12 = jedis.zrange("user12", 0, size);}
5 代碼實(shí)現(xiàn)——取
1)另外一個項(xiàng)目需要取這些數(shù)據(jù)。
取出來之后stringToUserEvent方法進(jìn)行切割還原成List< UserEvent>
@Testpublic void redisGetZSet() {//取3個int size=3;List<UserEvent> userEvents = Lists.newArrayListWithExpectedSize(size);//reverseRange按從大往小取size個,也就是取最新的Set<String> range = stringRedisTemplate.opsForZSet().getOperations().boundZSetOps("user12").reverseRange(0, size);if (range != null && range.size() > 0) {userEvents = range.stream().map(a -> stringToUserEvent(a)).filter(userEvent -> userEvent != null).collect(Collectors.toList());}System.out.println(userEvents);}
6 小烏龍
阿里云數(shù)據(jù)庫查看key的數(shù)據(jù),發(fā)現(xiàn)左側(cè)的序號不對應(yīng)得分排序。奇怪?沒排序好嗎?
原來左側(cè)的序號不是排序號。
畢竟zset的查詢,是通過分?jǐn)?shù)score來排序來查詢結(jié)果的,不要以為左側(cè)的序號是排序號!
不過云數(shù)據(jù)庫結(jié)果呈現(xiàn)的順序是什么依據(jù)呢?只是方便看總的個數(shù)吧!
總結(jié)
以上是生活随笔為你收集整理的redis的zset使用(java)——存取List< Object>的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。