注意:本章代碼是在上一章的基礎上進行添加修改,上一章鏈接《第九章 企業項目開發--分布式緩存Redis(1)》
上一章說了ShardedJedisPool的創建過程,以及redis五種數據結構的第一種String類型的常用緩存操作方法。下面說余下的四種:
- list(有序列表)
- set(無序集合)
- sorted set(有序集合)
- hash
1、ssmm0-cache
1.1、RedisListUtil(有序列表工具類)

1 package com.xxx.cache.redis; 2 3 import java.util.List; 4 5 import redis.clients.jedis.ShardedJedis; 6 7 /** 8 * list緩存操作類 9 * 1、順序為插入list的順序 10 * 2、允許存放重復元素 11 * 3、可用作模擬隊列(queue)、堆棧(stack),支持雙向操作(L--首部或者R--尾部) 12 * 4、index從0開始 -1表示結尾 -2表示倒數第二個 13 * 5、API中的 start end參數 都是包前也包后的 14 */ 15 public class RedisListUtil extends RedisBaseUtil{ 16 17 /***************************添加緩存*****************************/ 18 /** 19 * 從左邊(首部)加入列表 20 * 注意: 21 * 1、可以一次性入隊n個元素(這里使用了不定參數,當然可以換做數組) 22 * 2、不定參數必須放在所有參數的最后邊 23 * 3、左邊入隊,相當於在隊頭插入元素,則之后的元素都要后移一位;而右邊入隊的話元素直接插在隊尾,之前的元素的索引不變 24 * 4、沒有從list中獲取指定value的運算 25 */ 26 public static void lpush(String list, String... values){ 27 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 28 ShardedJedis jedis = null; 29 try { 30 jedis = getJedis();//獲取jedis實例 31 if(jedis==null){ 32 broken = true; 33 return; 34 } 35 /* 36 * lpush(String key, String... strings); 37 * 返回push之后的list中包含的元素個數 38 */ 39 jedis.lpush(list, values); 40 } catch (Exception e) { 41 broken = true; 42 }finally{ 43 returnJedis(jedis, broken); 44 } 45 } 46 47 /** 48 * 從左邊(首部)加入列表 49 * 並指定列表緩存過期時間 50 */ 51 public static void lpush(String list, int expire, String... values){ 52 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 53 ShardedJedis jedis = null; 54 try { 55 jedis = getJedis();//獲取jedis實例 56 if(jedis==null){ 57 broken = true; 58 return; 59 } 60 /* 61 * lpush(String key, String... strings); 62 * 返回push之后的list中包含的元素個數 63 */ 64 jedis.lpush(list, values); 65 jedis.expire(list, expire);//為該list設置緩存過期時間 66 } catch (Exception e) { 67 broken = true; 68 }finally{ 69 returnJedis(jedis, broken); 70 } 71 } 72 73 /** 74 * 從右邊(尾部)加入列表 75 */ 76 public static void rpush(String list, String... values){ 77 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 78 ShardedJedis jedis = null; 79 try { 80 jedis = getJedis();//獲取jedis實例 81 if(jedis==null){ 82 broken = true; 83 return; 84 } 85 jedis.rpush(list, values); 86 } catch (Exception e) { 87 broken = true; 88 }finally{ 89 returnJedis(jedis, broken); 90 } 91 } 92 93 /** 94 * 從右邊(尾部)加入列表 95 * 並設置緩存過期時間 96 */ 97 public static void rpush(String list, int expire, String... values){ 98 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 99 ShardedJedis jedis = null; 100 try { 101 jedis = getJedis();//獲取jedis實例 102 if(jedis==null){ 103 broken = true; 104 return; 105 } 106 jedis.rpush(list, values); 107 jedis.expire(list, expire);//設置緩存過期時間 108 } catch (Exception e) { 109 broken = true; 110 }finally{ 111 returnJedis(jedis, broken); 112 } 113 } 114 115 /** 116 * 設置list中index位置的元素 117 * index==-1表示最后一個元素 118 */ 119 public static void lSetIndex(String list, long index, String value){ 120 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 121 ShardedJedis jedis = null; 122 try { 123 jedis = getJedis();//獲取jedis實例 124 if(jedis==null){ 125 broken = true; 126 return; 127 } 128 jedis.lset(list, index, value); 129 } catch (Exception e) { 130 broken = true; 131 }finally{ 132 returnJedis(jedis, broken); 133 } 134 } 135 136 /***************************獲取緩存*****************************/ 137 /** 138 * 從左邊(首部)出列表 139 */ 140 public static String lpop(String list){ 141 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 142 ShardedJedis jedis = null; 143 try { 144 jedis = getJedis();//獲取jedis實例 145 if(jedis==null){ 146 broken = true; 147 return null; 148 } 149 return jedis.lpop(list); 150 } catch (Exception e) { 151 broken = true; 152 }finally{ 153 returnJedis(jedis, broken); 154 } 155 return null; 156 } 157 158 /** 159 * 從右邊出列表 160 */ 161 public static String rpop(String list){ 162 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 163 ShardedJedis jedis = null; 164 try { 165 jedis = getJedis();//獲取jedis實例 166 if(jedis==null){ 167 broken = true; 168 return null; 169 } 170 return jedis.rpop(list); 171 } catch (Exception e) { 172 broken = true; 173 }finally{ 174 returnJedis(jedis, broken); 175 } 176 return null; 177 } 178 179 /** 180 * 返回list中index位置的元素 181 */ 182 public static String lGetIndex(String list, long index){ 183 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 184 ShardedJedis jedis = null; 185 try { 186 jedis = getJedis();//獲取jedis實例 187 if(jedis==null){ 188 broken = true; 189 return null; 190 } 191 return jedis.lindex(list, index); 192 } catch (Exception e) { 193 broken = true; 194 }finally{ 195 returnJedis(jedis, broken); 196 } 197 return null; 198 } 199 200 /** 201 * 返回list指定區間[start,end]內的元素 202 */ 203 public static List<String> lrange(String list, long start, long end){ 204 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 205 ShardedJedis jedis = null; 206 try { 207 jedis = getJedis();//獲取jedis實例 208 if(jedis==null){ 209 broken = true; 210 return null; 211 } 212 return jedis.lrange(list, start, end);// 213 } catch (Exception e) { 214 broken = true; 215 }finally{ 216 returnJedis(jedis, broken); 217 } 218 return null; 219 } 220 221 /** 222 * 返回list內的全部元素 223 */ 224 public static List<String> lrange(String list){ 225 return lrange(list, 0, -1); 226 } 227 228 /*** 刪除緩存(刪除整個list,直接用RedisStringUtil的delete就好)******/ 229 /** 230 * 讓list只保留指定區間[start,end]內的元素,不在指定區間內的元素都將被刪除 231 */ 232 public static void ltrim(String list, long start, long end){ 233 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 234 ShardedJedis jedis = null; 235 try { 236 jedis = getJedis();//獲取jedis實例 237 if(jedis==null){ 238 broken = true; 239 return; 240 } 241 jedis.ltrim(list, start, end); 242 } catch (Exception e) { 243 broken = true; 244 }finally{ 245 returnJedis(jedis, broken); 246 } 247 } 248 249 /** 250 * 刪除list中所有與value相等的元素 251 * 注意: 252 * count 253 * ==0 :刪除表中所有與value相等的元素 254 * >0:從表頭開始向表尾搜索,移除count個與value相等的元素 255 * <0:從表尾開始向表頭搜索,移除count個與value相等的元素 256 */ 257 public static void lremove(String list, long count, String value){ 258 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 259 ShardedJedis jedis = null; 260 try { 261 jedis = getJedis();//獲取jedis實例 262 if(jedis==null){ 263 broken = true; 264 return; 265 } 266 jedis.lrem(list, count, value);//返回刪除了多少個元素 267 } catch (Exception e) { 268 broken = true; 269 }finally{ 270 returnJedis(jedis, broken); 271 } 272 } 273 274 /** 275 * 刪除list中所有與value相等的元素 276 */ 277 public static void lremove(String list, String value){ 278 lremove(list, 0, value); 279 } 280 281 /***************************其他*****************************/ 282 /** 283 * 返回list中共有多少個元素 284 */ 285 public static long llength(String list){ 286 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 287 ShardedJedis jedis = null; 288 try { 289 jedis = getJedis();//獲取jedis實例 290 if(jedis==null){ 291 broken = true; 292 return 0; 293 } 294 return jedis.llen(list); 295 } catch (Exception e) { 296 broken = true; 297 }finally{ 298 returnJedis(jedis, broken); 299 } 300 return 0; 301 } 302 303 public static void main(String[] args) { 304 lpush("adminList", "jigang"); 305 lpush("adminList", "nana");//頭部 306 System.out.println(llength("adminList")); 307 System.out.println(lrange("adminList")); 308 //lpop("adminList"); 309 //System.out.println(llength("adminList")); 310 //ltrim("adminList", 0, 1); 311 //System.out.println(lrange("adminList")); 312 //System.out.println(lpop("adminList"));//左邊進左邊出,棧(后進先出) 313 //System.out.println(rpop("adminList"));//左邊進右邊出,隊列(先進先出) 314 System.out.println(lGetIndex("adminList",1)); 315 316 } 317 }
注意:
- 元素在list中的存放順序為:插入list的順序(從左邊插入在頭部,從右邊插入在尾部)
- 允許存放重復元素
- 可用作模擬隊列(queue)、堆棧(stack),支持雙向操作(L--首部或者R--尾部)
- index從0開始 -1表示結尾 -2表示倒數第二個
- API中的 start end參數 都是包前也包后的
- 左邊入隊,相當於在隊頭插入元素,則之后的元素都要后移一位;而右邊入隊的話元素直接插在隊尾,之前的元素的索引不變(推薦使用右邊入隊,即隊尾入隊)
- 沒有從list中獲取指定value的運算(這也是set/sorted set所沒有的)
- 沒有直接的指定緩存過期的API(這也是set/sorted set/hash所沒有的),但是可以按例如如下的方式指定緩存過期時間
1 /** 2 * 從左邊(首部)加入列表 3 * 並指定列表緩存過期時間 4 */ 5 public static void lpush(String list, int expire, String... values){ 6 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 7 ShardedJedis jedis = null; 8 try { 9 jedis = getJedis();//獲取jedis實例 10 if(jedis==null){ 11 broken = true; 12 return; 13 } 14 /* 15 * lpush(String key, String... strings); 16 * 返回push之后的list中包含的元素個數 17 */ 18 jedis.lpush(list, values); 19 jedis.expire(list, expire);//為該list設置緩存過期時間 20 } catch (Exception e) { 21 broken = true; 22 }finally{ 23 returnJedis(jedis, broken); 24 } 25 }
- 刪除整個list可以直接使用jedis.del(list)(set/sorted set/hash同理)
1.2、RedisSetUtil(無序集合工具類)

1 package com.xxx.cache.redis; 2 3 import java.util.Set; 4 5 import redis.clients.jedis.ShardedJedis; 6 7 /** 8 * set緩存操作類 9 * 1、無序集合,最后的順序不一定是插入順序 10 * 2、元素不能重復 11 * 3、對於set而言,Jedis有交集、差集、並集運算,可是ShardJedis沒有 12 * 4、沒有從set中獲取指定value的運算 13 */ 14 public class RedisSetUtil extends RedisBaseUtil { 15 /***************************添加緩存*****************************/ 16 /** 17 * 添加緩存 18 * @param set 緩存將要添加到的set集合 19 * @param values 添加的緩存元素 20 */ 21 public static void sadd(String set, String... values){ 22 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 23 ShardedJedis jedis = null; 24 try { 25 jedis = getJedis();//獲取jedis實例 26 if(jedis==null){ 27 broken = true; 28 return; 29 } 30 /* 31 * 對比: 32 * lpush(String key, String... strings); 33 * 返回push之后的list中包含的元素個數 34 * 35 * sadd(String key, String... members) 36 * 1:添加元素成功 37 * 0:set中已經有要添加的元素了 38 */ 39 jedis.sadd(set, values); 40 } catch (Exception e) { 41 broken = true; 42 }finally{ 43 returnJedis(jedis, broken); 44 } 45 } 46 47 /***************************獲取緩存*****************************/ 48 /** 49 * 獲取set集合中的所有緩存 50 * @param set 51 */ 52 public static Set<String> smembers(String set){ 53 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 54 ShardedJedis jedis = null; 55 try { 56 jedis = getJedis();//獲取jedis實例 57 if(jedis==null){ 58 broken = true; 59 return null; 60 } 61 return jedis.smembers(set); 62 } catch (Exception e) { 63 broken = true; 64 }finally{ 65 returnJedis(jedis, broken); 66 } 67 return null; 68 } 69 70 /***************************刪除緩存*****************************/ 71 /** 72 * 刪除緩存 73 * @param set 74 * @param values 75 */ 76 public static void sremove(String set, String... values){ 77 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 78 ShardedJedis jedis = null; 79 try { 80 jedis = getJedis();//獲取jedis實例 81 if(jedis==null){ 82 broken = true; 83 return; 84 } 85 jedis.srem(set, values); 86 } catch (Exception e) { 87 broken = true; 88 }finally{ 89 returnJedis(jedis, broken); 90 } 91 } 92 93 /***************************其他*****************************/ 94 /** 95 * set集合是否包含value 96 * @param set 97 */ 98 public static boolean sismembers(String set, String value){ 99 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 100 ShardedJedis jedis = null; 101 try { 102 jedis = getJedis();//獲取jedis實例 103 if(jedis==null){ 104 broken = true; 105 return false; 106 } 107 return jedis.sismember(set, value); 108 } catch (Exception e) { 109 broken = true; 110 }finally{ 111 returnJedis(jedis, broken); 112 } 113 return false; 114 } 115 116 /** 117 * 返回set集合的元素個數 118 * @param set 119 */ 120 public static long ssize(String set){ 121 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 122 ShardedJedis jedis = null; 123 try { 124 jedis = getJedis();//獲取jedis實例 125 if(jedis==null){ 126 broken = true; 127 return 0; 128 } 129 return jedis.scard(set); 130 } catch (Exception e) { 131 broken = true; 132 }finally{ 133 returnJedis(jedis, broken); 134 } 135 return 0; 136 } 137 138 /** 139 * 測試 140 */ 141 public static void main(String[] args) { 142 sadd("adminset", "nana","jigang"); 143 sadd("adminset", "nana2"); 144 System.out.println(smembers("adminset")); 145 System.out.println(ssize("adminset")); 146 System.out.println(sismembers("adminset", "jigang")); 147 sremove("adminset", "jigang"); 148 System.out.println(sismembers("adminset", "jigang")); 149 } 150 151 }
注意:
- 元素在set中的存放順序為:與插入set的先后書順序無關(即無序)
- 不允許存放重復元素
- 對於set而言,Jedis有交集、差集、並集運算,可是ShardJedis沒有
1.3、RedisSortedSet(有序集合工具類)

1 package com.xxx.cache.redis; 2 3 import java.util.Map; 4 import java.util.Set; 5 6 import redis.clients.jedis.ShardedJedis; 7 import redis.clients.jedis.Tuple; 8 9 /** 10 * sorted set緩存操作類 11 * 1、有序集合,最后的順序是按照score從小到大的順序排列 12 * 2、元素不能重復 13 * 3、沒有從set中獲取指定value的運算 14 */ 15 public class RedisSortedSetUtil extends RedisBaseUtil { 16 /***************************添加緩存*****************************/ 17 /** 18 * 添加緩存(一個) 19 * @param sortedSet 添加入的集合 20 * @param score 權重 21 * @param value 值 22 */ 23 public static void zadd(String sortedSet,double score, String value){ 24 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 25 ShardedJedis jedis = null; 26 try { 27 jedis = getJedis();//獲取jedis實例 28 if(jedis==null){ 29 broken = true; 30 return; 31 } 32 jedis.zadd(sortedSet, score, value); 33 } catch (Exception e) { 34 broken = true; 35 }finally{ 36 returnJedis(jedis, broken); 37 } 38 } 39 40 /** 41 * 添加緩存(一次可添加多個) 42 * @param sortedSet 添加入的集合 43 * @param value2score 加入集合的元素集 44 */ 45 public static void zadd(String sortedSet,Map<String, Double> value2score){ 46 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 47 ShardedJedis jedis = null; 48 try { 49 jedis = getJedis();//獲取jedis實例 50 if(jedis==null){ 51 broken = true; 52 return; 53 } 54 jedis.zadd(sortedSet, value2score); 55 } catch (Exception e) { 56 broken = true; 57 }finally{ 58 returnJedis(jedis, broken); 59 } 60 } 61 62 /***************************獲取緩存*****************************/ 63 /** 64 * 返回sortedSet內[start,end]索引的元素set 65 * 1、在sortedSet中,元素是按照score從小到大排列的, 66 * 此方法從前向后獲取元素(即按元素的score從小到大排列) 67 * @param sortedSet 68 * @param start 69 * @param end 70 */ 71 public static Set<String> zrange(String sortedSet, long start, long end){ 72 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 73 ShardedJedis jedis = null; 74 try { 75 jedis = getJedis();//獲取jedis實例 76 if(jedis==null){ 77 broken = true; 78 return null; 79 } 80 return jedis.zrange(sortedSet, start, end); 81 } catch (Exception e) { 82 broken = true; 83 }finally{ 84 returnJedis(jedis, broken); 85 } 86 return null; 87 } 88 89 /** 90 * 返回sortedSet內所有元素,元素按照score從小到大排列 91 */ 92 public static Set<String> zrange(String sortedSet){ 93 return zrange(sortedSet, 0, -1); 94 } 95 96 /** 97 * 返回sortedSet集合[start, end]中的元素 98 * 1、此方法相當於從后向前取元素,即元素從大到小排列 99 * 或者相當於將sortedSet從大到小排列,然后從前向后去元素 100 * @param sortedSet 101 * @param start 102 * @param end 103 * @return 104 */ 105 public static Set<String> zrevrange(String sortedSet, long start, long end){ 106 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 107 ShardedJedis jedis = null; 108 try { 109 jedis = getJedis();//獲取jedis實例 110 if(jedis==null){ 111 broken = true; 112 return null; 113 } 114 return jedis.zrevrange(sortedSet, start, end); 115 } catch (Exception e) { 116 broken = true; 117 }finally{ 118 returnJedis(jedis, broken); 119 } 120 return null; 121 } 122 123 /** 124 * 返回sortedSet內所有元素,元素按照score從大到小排列 125 */ 126 public static Set<String> zrevrange(String sortedSet){ 127 return zrevrange(sortedSet, 0, -1); 128 } 129 130 /** 131 * 獲取sortedSet內[minScore, maxScore]的元素 132 * @param sortedSet 133 * @param minScore 134 * @param maxScore 135 * @return 136 */ 137 public static Set<String> zrangeByScore(String sortedSet, double minScore, double maxScore){ 138 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 139 ShardedJedis jedis = null; 140 try { 141 jedis = getJedis();//獲取jedis實例 142 if(jedis==null){ 143 broken = true; 144 return null; 145 } 146 return jedis.zrangeByScore(sortedSet, minScore, maxScore); 147 } catch (Exception e) { 148 broken = true; 149 }finally{ 150 returnJedis(jedis, broken); 151 } 152 return null; 153 } 154 155 /** 156 * 獲取Set<Tuple>集合,其中Tuple是value與score的結構體 157 * @param sortedSet 158 * @param minScore 159 * @param maxScore 160 * @return 161 */ 162 public static Set<Tuple> zrevrangeByScoreWithScores(String sortedSet, double minScore, double maxScore){ 163 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 164 ShardedJedis jedis = null; 165 try { 166 jedis = getJedis();//獲取jedis實例 167 if(jedis==null){ 168 broken = true; 169 return null; 170 } 171 return jedis.zrevrangeByScoreWithScores(sortedSet, maxScore, minScore); 172 } catch (Exception e) { 173 broken = true; 174 }finally{ 175 returnJedis(jedis, broken); 176 } 177 return null; 178 } 179 180 /***************************刪除緩存*****************************/ 181 /** 182 * 刪除多個緩存 183 * @param sortedSet 184 * @param values 185 */ 186 public static void zremove(String sortedSet, String... values){ 187 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 188 ShardedJedis jedis = null; 189 try { 190 jedis = getJedis();//獲取jedis實例 191 if(jedis==null){ 192 broken = true; 193 return; 194 } 195 jedis.zrem(sortedSet, values); 196 } catch (Exception e) { 197 broken = true; 198 }finally{ 199 returnJedis(jedis, broken); 200 } 201 } 202 203 /** 204 * 刪除指定范圍(按照索引,包前包后)的緩存 205 * @param sortedSet 206 * @param start 207 * @param end 208 */ 209 public static void zremrangeByRank(String sortedSet, long start, long end){ 210 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 211 ShardedJedis jedis = null; 212 try { 213 jedis = getJedis();//獲取jedis實例 214 if(jedis==null){ 215 broken = true; 216 return; 217 } 218 jedis.zremrangeByRank(sortedSet, start, end); 219 } catch (Exception e) { 220 broken = true; 221 }finally{ 222 returnJedis(jedis, broken); 223 } 224 } 225 226 /** 227 * 刪除指定范圍(按照分數,包前包后)的緩存 228 * @param sortedSet 229 * @param minScore 230 * @param maxScore 231 */ 232 public static void zremrangeByScore(String sortedSet, double minScore, double maxScore){ 233 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 234 ShardedJedis jedis = null; 235 try { 236 jedis = getJedis();//獲取jedis實例 237 if(jedis==null){ 238 broken = true; 239 return; 240 } 241 jedis.zremrangeByScore(sortedSet, minScore, maxScore); 242 } catch (Exception e) { 243 broken = true; 244 }finally{ 245 returnJedis(jedis, broken); 246 } 247 } 248 249 /***************************其他*****************************/ 250 /** 251 * 獲取集合sortedSet的長度 252 * @param sortedSet 253 * @return 254 */ 255 public static long zlength(String sortedSet){ 256 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 257 ShardedJedis jedis = null; 258 try { 259 jedis = getJedis();//獲取jedis實例 260 if(jedis==null){ 261 broken = true; 262 return 0; 263 } 264 return jedis.zcard(sortedSet); 265 } catch (Exception e) { 266 broken = true; 267 }finally{ 268 returnJedis(jedis, broken); 269 } 270 return 0; 271 } 272 273 /** 274 * 獲取sortedSet中的value的權重score 275 * @param sortedSet 276 * @param value 277 * @return 278 */ 279 public static double zscore(String sortedSet, String value){ 280 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 281 ShardedJedis jedis = null; 282 try { 283 jedis = getJedis();//獲取jedis實例 284 if(jedis==null){ 285 broken = true; 286 return 0; 287 } 288 return jedis.zscore(sortedSet, value); 289 } catch (Exception e) { 290 broken = true; 291 }finally{ 292 returnJedis(jedis, broken); 293 } 294 return 0; 295 } 296 297 /** 298 * 為sortedSet中的value的權重加上增量score 299 * @param sortedSet 300 * @param score 301 * @param value 302 */ 303 public static void zincrby(String sortedSet,double score, String value){ 304 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 305 ShardedJedis jedis = null; 306 try { 307 jedis = getJedis();//獲取jedis實例 308 if(jedis==null){ 309 broken = true; 310 return; 311 } 312 jedis.zincrby(sortedSet, score, value); 313 } catch (Exception e) { 314 broken = true; 315 }finally{ 316 returnJedis(jedis, broken); 317 } 318 } 319 320 /** 321 * 測試 322 */ 323 public static void main(String[] args) { 324 zadd("aaset", 1, "aa"); 325 zadd("aaset", 4, "bb"); 326 zadd("aaset", 0, "cc"); 327 328 System.out.println(zrange("aaset", 0, -1));//[cc, aa, bb] 329 System.out.println(zrange("aaset", 0, 1));//[cc, aa] 330 System.out.println(zrevrange("aaset", 0, -1));//[bb, aa, cc] 331 System.out.println(zrevrange("aaset", 0, 1));//[bb, aa] 332 System.out.println(zrangeByScore("aaset", 0, 2));//[cc, aa] 333 Set<Tuple> s = zrevrangeByScoreWithScores("aaset", 0, 2); 334 for(Tuple t : s){ 335 System.out.println(t.getElement()+"-->"+t.getScore());//aa-->1.0 cc-->0.0 336 } 337 338 System.out.println(zlength("aaset"));//3 339 System.out.println(zscore("aaset","bb"));//4.0 340 zincrby("aaset",10,"bb"); 341 System.out.println(zscore("aaset","bb"));//14.0 342 zremove("aaset", "cc"); 343 System.out.println(zrange("aaset"));//[aa, bb] 344 zremrangeByScore("aaset", 10, 20); 345 System.out.println(zrange("aaset"));//[aa] 346 } 347 348 }
注意:
- 元素在set中的存放順序為:根據score(權重)從小到大排列
- 不允許存放重復元素
1.4、RedisHashUtil(hash工具類)

1 package com.xxx.cache.redis; 2 3 import java.util.HashMap; 4 import java.util.List; 5 import java.util.Map; 6 import java.util.Set; 7 8 import redis.clients.jedis.ShardedJedis; 9 10 /** 11 * hash緩存操作類 12 */ 13 public class RedisHashUtil extends RedisBaseUtil { 14 /***************************添加緩存*****************************/ 15 /** 16 * 添加單個緩存key-value到map中 17 */ 18 public static void hset(String map, String key, String value){ 19 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 20 ShardedJedis jedis = null; 21 try { 22 jedis = getJedis();//獲取jedis實例 23 if(jedis==null){ 24 broken = true; 25 return; 26 } 27 jedis.hset(map, key, value); 28 } catch (Exception e) { 29 broken = true; 30 }finally{ 31 returnJedis(jedis, broken); 32 } 33 } 34 35 /** 36 * 添加單個緩存key-value到map中 37 * 若已經存在於指定key相同的key,那么就不操作 38 */ 39 public static void hsetnx(String map, String key, String value){ 40 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 41 ShardedJedis jedis = null; 42 try { 43 jedis = getJedis();//獲取jedis實例 44 if(jedis==null){ 45 broken = true; 46 return; 47 } 48 jedis.hsetnx(map, key, value); 49 } catch (Exception e) { 50 broken = true; 51 }finally{ 52 returnJedis(jedis, broken); 53 } 54 } 55 56 /** 57 * 在map中添加key2value的map,即一次性添加多條緩存 58 * @param map 59 * @param key2value 60 */ 61 public static void hmset(String map, Map<String, String> key2value){ 62 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 63 ShardedJedis jedis = null; 64 try { 65 jedis = getJedis();//獲取jedis實例 66 if(jedis==null){ 67 broken = true; 68 return; 69 } 70 jedis.hmset(map, key2value); 71 } catch (Exception e) { 72 broken = true; 73 }finally{ 74 returnJedis(jedis, broken); 75 } 76 } 77 78 /***************************獲取緩存*****************************/ 79 /** 80 * 獲取map中key的集合 81 * @param set 82 */ 83 public static Set<String> hkeys(String map){ 84 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 85 ShardedJedis jedis = null; 86 try { 87 jedis = getJedis();//獲取jedis實例 88 if(jedis==null){ 89 broken = true; 90 return null; 91 } 92 return jedis.hkeys(map); 93 } catch (Exception e) { 94 broken = true; 95 }finally{ 96 returnJedis(jedis, broken); 97 } 98 return null; 99 } 100 101 /** 102 * 獲取map中的所有key的value 103 */ 104 public static List<String> hvals(String map){ 105 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 106 ShardedJedis jedis = null; 107 try { 108 jedis = getJedis();//獲取jedis實例 109 if(jedis==null){ 110 broken = true; 111 return null; 112 } 113 return jedis.hvals(map); 114 } catch (Exception e) { 115 broken = true; 116 }finally{ 117 returnJedis(jedis, broken); 118 } 119 return null; 120 } 121 122 /** 123 * 從map中獲取多個key的value,並放在List集合中 124 */ 125 public static List<String> hmget(String map, String... keys){ 126 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 127 ShardedJedis jedis = null; 128 try { 129 jedis = getJedis();//獲取jedis實例 130 if(jedis==null){ 131 broken = true; 132 return null; 133 } 134 return jedis.hmget(map, keys); 135 } catch (Exception e) { 136 broken = true; 137 }finally{ 138 returnJedis(jedis, broken); 139 } 140 return null; 141 } 142 143 /** 144 * 從map中獲取全部的緩存key-value對 145 */ 146 public static Map<String, String> hgetAll(String map){ 147 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 148 ShardedJedis jedis = null; 149 try { 150 jedis = getJedis();//獲取jedis實例 151 if(jedis==null){ 152 broken = true; 153 return null; 154 } 155 return jedis.hgetAll(map); 156 } catch (Exception e) { 157 broken = true; 158 }finally{ 159 returnJedis(jedis, broken); 160 } 161 return null; 162 } 163 164 /** 165 * 從map中獲取相應key的緩存value 166 */ 167 public static String hget(String map, String key){ 168 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 169 ShardedJedis jedis = null; 170 try { 171 jedis = getJedis();//獲取jedis實例 172 if(jedis==null){ 173 broken = true; 174 return null; 175 } 176 return jedis.hget(map, key); 177 } catch (Exception e) { 178 broken = true; 179 }finally{ 180 returnJedis(jedis, broken); 181 } 182 return null; 183 } 184 185 /***************************刪除緩存*****************************/ 186 /** 187 * 從map中刪除多個緩存 188 */ 189 public static void hdel(String map, String... keys){ 190 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 191 ShardedJedis jedis = null; 192 try { 193 jedis = getJedis();//獲取jedis實例 194 if(jedis==null){ 195 broken = true; 196 return; 197 } 198 jedis.hdel(map, keys); 199 } catch (Exception e) { 200 broken = true; 201 }finally{ 202 returnJedis(jedis, broken); 203 } 204 } 205 206 /***************************其他*****************************/ 207 /** 208 * 獲取map中的key-value數 209 */ 210 public static long hlen(String map){ 211 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 212 ShardedJedis jedis = null; 213 try { 214 jedis = getJedis();//獲取jedis實例 215 if(jedis==null){ 216 broken = true; 217 return 0; 218 } 219 return jedis.hlen(map); 220 } catch (Exception e) { 221 broken = true; 222 }finally{ 223 returnJedis(jedis, broken); 224 } 225 return 0; 226 } 227 228 /** 229 * map中是否存在鍵為key的緩存 230 */ 231 public static boolean hexists(String map, String key){ 232 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 233 ShardedJedis jedis = null; 234 try { 235 jedis = getJedis();//獲取jedis實例 236 if(jedis==null){ 237 broken = true; 238 return false; 239 } 240 return jedis.hexists(map, key); 241 } catch (Exception e) { 242 broken = true; 243 }finally{ 244 returnJedis(jedis, broken); 245 } 246 return false; 247 } 248 249 /** 250 * 測試 251 */ 252 public static void main(String[] args) { 253 hset("aamap", "aa1", "aa11"); 254 Map<String,String> maps = new HashMap<String, String>(); 255 maps.put("aa2", "aa22"); 256 maps.put("aa3", "aa33"); 257 hmset("aamap", maps); 258 259 System.out.println(hkeys("aamap"));//[aa3, aa2, aa1] 260 System.out.println(hvals("aamap"));//[aa33, aa22, aa11] 261 System.out.println(hgetAll("aamap"));//{aa3=aa33, aa2=aa22, aa1=aa11} 262 System.out.println(hget("aamap","aa2"));//aa22 263 System.out.println(hmget("aamap","aa2","aa1"));//[aa22, aa11] 264 265 System.out.println(hlen("aamap"));//3 266 System.out.println(hexists("aamap","aa3"));//true 267 System.out.println(hexists("aamap","aa0"));//false 268 269 hdel("aamap","aa0"); 270 hdel("aamap","aa1"); 271 System.out.println(hgetAll("aamap"));//{aa3=aa33, aa2=aa22} 272 273 } 274 }
注意:
- 有根據key獲取緩存value的方法
1.5、RedisCacheConstant(創建一些redis使用的自定義的map/set/list/soretd set名)

1 package com.xxx.cache.util; 2 3 /** 4 * 創建一些redis使用的自定義的map/set/list/soretd set名 5 */ 6 public enum RedisCacheConstant { 7 USER_MANAGEMENT_MAP, //人員管理業務類緩存map 8 HOTEL_MANAGEMENT_MAP; //酒店管理業務類緩存map 9 }
注意:
- 這一塊兒與業務有關
- 在我們的API的設計過程中,可以直接將自己封裝的方法中的list/set/sorted set/map參數的類型有String改為RedisCacheConstant,而在方法內部你調用ShardJedis的API的時候,使用String.valueOf(RedisCacheConstant)這樣的方式,這樣就會減少在實際開發中的代碼量。
2、ssmm0-data
AdminService:

1 /*********************redis hash********************/ 2 /* 3 * 此處用set、list、sorted set都不太好,因為三者都不具備根據key查找值的能力, 4 * 以set為例,你緩存的時候,只能緩存一個id進去,最后查詢緩存,查到緩存中有ID之后,還需要再根據此ID查詢數據庫,才能返回具體的admin,還不如直接根據ID去數據庫查詢 5 * 6 * set的一個典型應用場景: 7 * 當有用戶注冊或者用戶信息修改或用戶被刪除之后,我們將其ID放入緩存, 8 * 之后可能會啟動一個定時任務,定時掃描該set中是否有ID存在,如果有,說明有用戶信息發生變化, 9 * 然后再進行一些操作,操作之后將set清空。之后繼續循環上述的方式 10 * 11 * 這里有個問題?set的操作是線程安全的嗎? 12 */ 13 public Admin findAdminByIdFromRedisHash(int id) { 14 //從緩存中獲取數據:注意這里可以直接將RedisHashUtil中的hget方法的map改為RedisCacheConstant類型,下邊同理,其他set、list、sorted set也同理 15 String adminStr = RedisHashUtil.hget(String.valueOf(RedisCacheConstant.USER_MANAGEMENT_MAP), String.valueOf(id)); 16 //若緩存中有,直接返回 17 if(StringUtils.isNoneBlank(adminStr)){ 18 return Admin.parseJsonToAdmin(adminStr); 19 } 20 //若緩存中沒有,從數據庫查詢 21 Admin admin = adminDao.getUserById(id); 22 //若查詢出的數據不為null 23 if(admin!=null){ 24 //將數據存入緩存 25 RedisHashUtil.hset(String.valueOf(RedisCacheConstant.USER_MANAGEMENT_MAP), String.valueOf(id), admin.toJson()); 26 } 27 //返回從數據庫查詢的admin(當然也可能數據庫中也沒有,就是null) 28 return admin; 29 }
說明:在AdminService類中只添加了如上方法。
注意:
- String、hash具有按key查找value的功能
- list、set、sorted set沒有按key查找的功能
適用場景:
- 需要按key查找value的,用hash和String
- set類的兩種典型應用場景:(歸結為一句話:存儲特殊的key,之后可能還需要根據這些key進行數據庫的查詢)
- 當有用戶注冊或者用戶信息修改或用戶被刪除之后,我們將其ID放入緩存,之后可能會啟動一個定時任務,定時掃描該set中是否有ID存在,如果有,說明有用戶信息發生變化,然后再進行一些操作,操作之后將set清空。之后繼續循環上述的方式
- 存儲一個網站的活躍的用戶ID,之后我們可以確定set中存在的所有ID都是活躍用戶,之后可以按照他們的ID進行數據庫的查詢;如果用MySQL去做這個事兒,可能需要掃描全表,然后再進行一些操作
3、ssmm0-userManagement
AdminController:

1 /** 2 * 根據id查找Admin 3 */ 4 @ResponseBody 5 @RequestMapping("/findAdminByIdFromRedisHash") 6 public Admin findAdminByIdFromRedisHash(@RequestParam(value="id") int id){ 7 8 return adminService.findAdminByIdFromRedisHash(id); 9 }
說明:AdminController中只添加了如上方法。
4、測試
測試方法同上一章。
總結:
- list
- 元素在list中的存放順序為:插入list的順序(從左邊插入在頭部,從右邊插入在尾部)
- 允許存放重復元素
- 可用作模擬隊列(queue)、堆棧(stack),支持雙向操作(L--首部或者R--尾部)
- 左邊入隊,相當於在隊頭插入元素,則之后的元素都要后移一位;而右邊入隊的話元素直接插在隊尾,之前的元素的索引不變(推薦使用右邊入隊,即隊尾入隊)
- set
- 元素在set中的存放順序為:與插入set的先后書順序無關(即無序)
- 不允許存放重復元素
- 對於set而言,Jedis有交集、差集、並集運算,可是ShardJedis沒有
- soretd set
- 元素在set中的存放順序為:根據score(權重)從小到大排列
- 不允許存放重復元素
相同點:
- index
- 從0開始 -1表示結尾 -2表示倒數第二個
- API中的 start end參數
- 都是包前也包后的
- 按key查找功能
- list、set、sorted set沒有按key查找的功能
- String、hash具有按key查找value的功能
- 直接的指定緩存過期的API
- String有
- list、set、sorted set、hash沒有,但是可以按例如如下的方式指定緩存過期時間
1 /** 2 * 從左邊(首部)加入列表 3 * 並指定列表緩存過期時間 4 */ 5 public static void lpush(String list, int expire, String... values){ 6 boolean broken = false;//標記:該操作是否被異常打斷而沒有正常結束 7 ShardedJedis jedis = null; 8 try { 9 jedis = getJedis();//獲取jedis實例 10 if(jedis==null){ 11 broken = true; 12 return; 13 } 14 /* 15 * lpush(String key, String... strings); 16 * 返回push之后的list中包含的元素個數 17 */ 18 jedis.lpush(list, values); 19 jedis.expire(list, expire);//為該list設置緩存過期時間 20 } catch (Exception e) { 21 broken = true; 22 }finally{ 23 returnJedis(jedis, broken); 24 } 25 }
- 刪除整個元素
- jedis.del(list):可用於五種結構
疑問:關於jedis、xmemcached的線程安全問題,是如何解決的?