如果键包含字符串,则从Redis获取完整的Map

问题描述

我能够从Redis添加获取特定的用户对象,我正在添加对象,如下所示:

 private static final String USER_PREFIX = ":USER:";
 public void addUserToRedis(String serverName,User user) {
    redistemplate.opsForHash().put(serverName + USER_PREFIX + user.getId(),Integer.toString(user.getId()),user);    
    }

如果userId为100,则可以通过键获取 SERVER1:USER:100
现在,我想以Map<String,List<User>>的身份检索所有用户
例如,通过此键 SERVER1:USER:
可以获取所有用户吗?或者我需要修改我的 addUserToRedis 方法?请建议我。

解决方法

我建议不要在生产环境中使用“ KEYS”命令,因为这会严重影响REDIS延迟(can even bring down the cluster if you have a large number of keys stored
相反,您可能想使用与普通GET / SET不同的命令。

如果使用SetsHashes

会更好
127.0.0.1:6379> sadd server1 user1 user2
(integer) 2
127.0.0.1:6379> smembers server1
1) "user2"
2) "user1"
127.0.0.1:6379>

使用集,您可以简单地将用户添加到服务器密钥,并获取服务器上的整个用户列表。

如果您确实需要< server,list < users > >的映射,则可以使用带有字符串化用户数据的哈希,然后在应用程序层将其转换为实际的User POJO

127.0.0.1:6379> hset server2 user11 name
(integer) 1
127.0.0.1:6379> hset server2 user13 name
(integer) 1
127.0.0.1:6379> hgetall server2
1) "user11"
2) "name"
3) "user13"
4) "name"
127.0.0.1:6379>

还要注意,将这么大的数据保存到单个密钥中并不是理想的事情。

,

最后,我想出了通配符搜索并避免使用KEYS的解决方案,这是我的完整方法:

  public Map<String,User> getUserMapFromRedis(String serverName){
    Map<String,User> users=new HashMap<>();
     RedisConnection redisConnection = null;
     try {
            redisConnection = redisTemplate.getConnectionFactory().getConnection();
           ScanOptions options = ScanOptions.scanOptions().match(serverName + USER_PREFIX+"*").build();
           Cursor<byte[]> scan = redisConnection.scan(options);
           while (scan.hasNext()) {
           byte[] next = scan.next();
           String key = new String(next,StandardCharsets.UTF_8);
           String[] keyArray=key.split(":");
           String userId=keyArray[2];
           User user=//get User by userId From Redis
           users.put(userId,user);
           }
           try {
           scan.close();
      } catch (IOException e) {
          
      }
       }finally {
       redisConnection.close(); //Ensure closing this connection.
       }
     return users;
    }
,

我不使用Java,但这是使用SCAN的方法

const Redis = require('ioredis')
const redis = new Redis()

async function main() {
    const stream = redis.scanStream({
        match: "*:user:*",count: 100,})

    stream.on("data",(resultKeys) => {
        for (let i = 0; i < resultKeys.length; i++) {
            // console.log(resultKeys[i])
            // do your things here
        }
    });
    stream.on("end",() => {
        console.log("all keys have been visited");
    });
}

main()