redis系列
- #redis的發布訂閱功能
- redis訊息佇列
- redis的pipeline
- redis的scan操作
序
在redis的db存在大量key或db裡頭的某個set、zset、hash裡面的元素非常多的話,用普通的get all操作很可能導致redis因為這個操作阻塞了,導致不能響應其他操作,特別是在高並發、海量數據的背景下,這個問題顯得尤其嚴重。那麼能不能像資料庫一樣有個分頁的功能呢,答案就是scan操作。本文主要展示怎麼在redis-cli以及SpringDataRedis中的使用。 【推薦:redis影片教學】
scan語法
scan之後回到兩部分,第一部分是下次scan的參數,第二部分就是scan出來的項
作用物件(db、set、zset、hash)
- db(
key
)
127.0.0.1:6379> scan 0 1) "120" 2) 1) "articleMap:63" 2) "articleMap:37" 3) "counter:__rand_int__" 4) "articleMap:60" 5) "tagSet:tag5" 6) "articleMap:80" 7) "messageCache~keys" 8) "mymap" 9) "articleMap:46" 10) "articleMap:55" 127.0.0.1:6379> scan 120 1) "28" 2) 1) "articleMap:17" 2) "tagSet:tag1" 3) "articleMap:18" 4) "articleMap:81" 5) "\xac\xed\x00\x05t\x00\btest-cas" 6) "articleMap:51" 7) "articleMap:94" 8) "articleMap:26" 9) "articleMap:71" 10) "user-abcde"
登入後複製
- set (
value
)
127.0.0.1:6379> sscan myset 0 1) "3" 2) 1) "m" 2) "j" 3) "c" 4) "h" 5) "f" 6) "i" 7) "a" 8) "g" 9) "n" 10) "e" 11) "b" 127.0.0.1:6379> sscan myset 3 1) "0" 2) 1) "l" 2) "k" 3) "d"
登入後複製
- zset(
value & score
)
127.0.0.1:6379> zscan sortset 0 1) "0" 2) 1) "tom" 2) "89" 3) "jim" 4) "90" 5) "david" 6) "100"
登入後複製
- #hash(
key & value
)
127.0.0.1:6379> hscan mymap 0 1) "0" 2) 1) "name" 2) "codecraft" 3) "email" 4) "pt@g.cn" 5) "age" 6) "20" 7) "desc" 8) "hello" 9) "sex" 10) "male"
登入後複製
SCAN的額外參數
- count(
指定每次取多少條
)
127.0.0.1:6379> scan 0 count 5 1) "240" 2) 1) "articleMap:63" 2) "articleMap:37" 3) "counter:__rand_int__" 4) "articleMap:60" 5) "tagSet:tag5"
登入後複製
- match(
匹配key
)
127.0.0.1:6379> scan 0 match article* 1) "120" 2) 1) "articleMap:63" 2) "articleMap:37" 3) "articleMap:60" 4) "articleMap:80" 5) "articleMap:46" 6) "articleMap:55"
登入後複製
RedisTemplate操作
遍歷資料庫key
@Test public void scanDbKeys(){ template.execute(new RedisCallback<Iterable<byte[]>>() { @Override public Iterable<byte[]> doInRedis(RedisConnection connection) throws DataAccessException { List<byte[]> binaryKeys = new ArrayList<byte[]>(); Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().count(5).build()); while (cursor.hasNext()) { byte[] key = cursor.next(); binaryKeys.add(key); System.out.println(new String(key, StandardCharsets.UTF_8)); } try { cursor.close(); } catch (IOException e) { // do something meaningful } return binaryKeys; } }); }
登入後複製
遍歷set
/** * sadd myset a b c d e f g h i j k l m n */ @Test public void scanSet(){ Cursor<String> cursor = template.opsForSet().scan("myset",ScanOptions.NONE); while (cursor.hasNext()){ System.out.println(cursor.next()); } }
登入後複製
遍歷zset
/** * zadd sortset 89 tom 90 jim 100 david */ @Test public void scanZSet(){ Cursor<ZSetOperations.TypedTuple<String>> cursor = template.opsForZSet().scan("sortset",ScanOptions.NONE); while (cursor.hasNext()){ ZSetOperations.TypedTuple<String> item = cursor.next(); System.out.println(item.getValue() + ":" + item.getScore()); } }
登入後複製
遍歷hash
/** * hset mymap name "codecraft" * hset mymap email "pt@g.cn" * hset mymap age 20 * hset mymap desc "hello" * hset mymap sex "male" */ @Test public void scanHash(){ Cursor<Map.Entry<Object, Object>> curosr = template.opsForHash().scan("mymap", ScanOptions.NONE); while(curosr.hasNext()){ Map.Entry<Object, Object> entry = curosr.next(); System.out.println(entry.getKey()+":"+entry.getValue()); } }
登入後複製