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

kcrjzv8t  于 2021-06-08  发布在  Redis
关注(0)|答案(3)|浏览(345)

我可以从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,我可以通过key:server1:user:100
现在我要检索所有用户作为 Map<String,List<User>> ,
例如,通过以下键获取所有用户server1:user:
有可能吗?或者我需要修改addusertoredis方法?请建议我。

ddrv8njm

ddrv8njm1#

我建议不要在生产环境中使用“keys”命令,因为这会严重影响redis的延迟(如果存储了大量密钥,甚至会导致集群崩溃)
相反,您可能希望使用与普通get/set不同的命令。
如果使用集合或哈希,效果会更好

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>

使用集合,您可以简单地将用户添加到服务器密钥,并获得服务器上的整个用户列表。
如果你真的需要Map < 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>

还要注意的是,将这么多的大数据保存在一个键中并不是一件理想的事情。

qyswt5oh

qyswt5oh2#

最后我提出了这个解决方案,使用通配符搜索和避免键,下面是我的完整方法:

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;
    }
k4emjkb1

k4emjkb13#

我不使用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()

相关问题