模糊匹配用keys *不就行了?,keys *是一次性返回所有满足条件的键,而redis是一个单线程的reactor,如果满足条件的数量很多的话就会堵塞线程,极大降低了redis的存取速度,那还有什么办法不堵塞线程的情况下进行模糊匹配呢,这个设计者肯定是已经想好了,通过scan就可以进行这样的操作。先把代码贴出来再讲一下代码的一些关键部分。

public Collection<Message> sgetAllMsg() {
        Set<Message> messages = new HashSet<>();
        ScanParams scanParams = new ScanParams();
        scanParams.match(keyName+"*");
        scanParams.count(1000);
        String scanRet = "0";
        do {
            ScanResult<String> result = cluster.scan(scanRet, scanParams);
            scanRet = result.getStringCursor();
            result.getResult().forEach(key -> {
                if (cluster.exists(key)){
                    messages.add((Message) JSONObject.toBean(JSONObject.fromObject(cluster.get(key)),Message.class));
                }
            });
        }while (!scanRet.equals("0"));
        return messages;
    }

首先scan先从scanRet = “0”这个下标开始搜索,每次搜索的个数可以由自己来定,即代码的scanParams.count();,需要匹配的的字符通过scanParams.match()来给定,每搜索一次返回scanRet下标和匹配的结果,其中返回的下标是下一次搜索的起始坐标,当下标重新变为“0”时就代表搜索完毕,之前书上说scan返回的搜索结果有可能重复,所以用set的唯一特性来收集结果。因为在redis中使用json格式来存的,所以在取的时候要把json变回原来的对象实例。
注意的是要保证scan的key在同一个节点上,如何保证呢?就是每个key的前后加上{ 和},即“{”+key+"}"。
代码截取于我和同学做的JMQTT项目,MQTT是一个客户端服务端架构的发布/订阅模式的消息传输协议。它的设计思想是轻巧、开放、简单、规范,易于实现。这些特点使得它对很多场景来说都是很好的选择,特别是对于受限的环境如机器与机器的通信(M2M)以及物联网环境(IoT)。我们使用Java实现这个协议并支持Websocket协议、支持数据本地持久化、支持redis存储。详细代码可以看:https://github.com/Cicizz/jmqtt/blob/master/jmqtt-store/src/main/java/org/jmqtt/store/redis/RedisStoreUtil.java 如果您觉得有帮助和对这个有兴趣欢迎给我们的项目点个watch和star。