redis的scan操作

redis的scan操作

redis系列

在redis的db存在大量key或者db里头的某个set、zset、hash里头的元素非常多的话,用普通的get all操作很可能导致redis因为这个操作阻塞了,导致不能响应其他操作,特别是在高并发、海量数据的背景下,这个问题显得尤其严重。那么能不能像数据库那样有个分页的功能呢,答案就是scan操作。本文主要展示怎么在redis-cli以及SpringDataRedis中的使用。

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)"xacxedx00x05tx00btest-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)"patterncat"
 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>() {
@Override
 public Iterable doInRedis(RedisConnection connection) throws DataAccessException {

 List binaryKeys = new ArrayList();

 Cursor 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 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> cursor = template.opsForZSet().scan("sortset",ScanOptions.NONE);
 while (cursor.hasNext()){
 ZSetOperations.TypedTuple item = cursor.next();
 System.out.println(item.getValue() +":"+ item.getScore());
}
}

遍历hash

/**
 * hset mymap name"patterncat"
 * hset mymap email"pt@g.cn"
 * hset mymap age 20
 * hset mymap desc"hello"
 * hset mymap sex"male"
*/
@Test
 public void scanHash(){
 Cursor> curosr = template.opsForHash().scan("mymap", ScanOptions.NONE);
while(curosr.hasNext()){
 Map.Entry entry = curosr.next();
System.out.println(entry.getKey()+":"+entry.getValue());
}
}

参考

好烂啊有点差凑合看看还不错很精彩 (No Ratings Yet)
Loading...
105 views

One thought on “redis的scan操作

发表评论

电子邮件地址不会被公开。 必填项已用*标注

跳至工具栏