赞
踩
当我们使用 keys * 或 hgetall 进行查询的时候会进行堵塞,导致 redis 整体不可用(因为redis是单线程的),而使用 scan 命令则不会。
从Redis v2.8开始,SCAN命令已经可用,它允许使用游标从keyspace中检索键。
对比KEYS命令,虽然SCAN无法一次性返回所有匹配结果,但是却规避了阻塞系统这个高风险,从而也让一些操作可以放在主节点上执行。
- 因为 SCAN 、 SSCAN 、 HSCAN 和 ZSCAN 四个命令的工作方式都非常相似, 要记住:
-
- SSCAN 命令、 HSCAN 命令和 ZSCAN 命令的第一个参数总是一个数据库键。
-
- 而 SCAN 命令则不需要在第一个参数提供任何数据库键 —— 因为它迭代的是当前数据库中的所有数据库键。
命令格式:
SCAN cursor [MATCH pattern] [COUNT count]
命令解释:scan 游标 MATCH <返回和给定模式相匹配的元素> count 每次迭代所返回的元素数量
SCAN命令是增量的循环,每次调用只会返回一小部分的元素。所以不会有KEYS命令的坑(key的数量比较多,一次KEYS查询会block其他操作)。
SCAN命令返回的是一个游标,从0开始遍历,到0结束遍历。
通过scan中的MATCH <pattern> 参数,可以让命令只返回和给定模式相匹配的元素,实现模糊查询的效果
- 示例:
- scan 0 match DL* count 5
- sscan myset 0 match f*
f
SCAN 命令、 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都返回一个包含两个元素的 multi-bulk 回复:
- SCAN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
- 当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。
这个 multi-bulk 回复包含了本次被迭代的元素。
SCAN命令不能保证每次返回的值都是有序的,另外同一个key有可能返回多次,不做区分,需要应用程序去处理。
SCAN 命令返回的每个元素都是一个数据库键。
SSCAN 命令返回的每个元素都是一个集合成员。
HSCAN 命令返回的每个元素都是一个键值对,一个键值对由一个键和一个值组成。
ZSCAN 命令返回的每个元素都是一个有序集合元素,一个有序集合元素由一个成员(member)和一个分值(score)组成。
- /**
- * @Description: 实现hscan dowhile形式
- * @Author: zongx
- * @Date: 2020/3/6
- * @Param: pattern
- * @return java.util.List<java.lang.String>
- */
- public Map<String,String> hscan(final String key,final String pattern) {
- return execute(new JedisAction<Map<String,String>>() {
- @Override
- public Map<String, String> action(Jedis jedis) {
- // 游标初始值为0
- String cursor = ScanParams.SCAN_POINTER_START;
- ScanParams scanParams = new ScanParams();
- scanParams.match(pattern);
- scanParams.count(Integer.MAX_VALUE);
- Map<String, String> results = new HashedMap();
- do {
- ScanResult<Map.Entry<String, String>> hscanResult =
- jedis.hscan(key, String.valueOf(cursor), scanParams);
- for (Map.Entry<String, String> en : hscanResult.getResult()) {
- results.put(en.getKey(),en.getValue());
- }
- //获取游标位置,若大于0,则代表还有数据,需要继续迭代
- cursor = hscanResult.getStringCursor();
- } while (Integer.parseInt(cursor) > 0);
-
- return results;
- }});
-
- }
-
-
-
- /**
- *scan,while形式
- * @param pattern
- * @param count
- * @return
- */
- public List<String> scan(final String pattern, final int count) {
- return execute(new JedisAction<List<String>>() {
- @Override
- public List<String> action(Jedis jedis) {
- ScanParams params = new ScanParams();
- params.match(pattern);
- params.count(count);
- String cursor = "0";
- List<String> results = new ArrayList<>();
- while (true) {
- ScanResult scanResult = jedis.scan(cursor, params);
- List<String> elements = scanResult.getResult();
- if (elements != null && elements.size() > 0) {
- results.addAll(elements);
- }
- cursor = scanResult.getStringCursor();
- if ("0".equals(cursor)) {
- break;
- }
- }
- return results;
- }
- });
- }
代码还可以参考:
https://www.xttblog.com/?p=3635
工具类在下载中心可以下载
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。