skip to Main Content

I am able to add and get a particular user object from Redis I am adding object like this:

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

If a userId is 100 I am able to get by key: SERVER1:USER:100
Now I want to retrieve all Users as Map<String,List<User>> ,
For example, get all users by this key SERVER1:USER:
Is it possible ? Or I need to modify my addUserToRedis method? Please suggest me.

3

Answers


  1. Chosen as BEST ANSWER

    Finally I came up with this solution with wildcard search and avoiding KEYS, and here is my complete method:

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

  2. I would recommend not using the "KEYS" command in production as this can severely impact REDIS latencies (can even bring down the cluster if you have a large number of keys stored)

    Instead, you would want to use a different command than plain GET/SET.

    It would be better if you use a Sets or Hashes

    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>
    

    Using sets you can simply add your users to server keys and get the entire list of users on a server.

    If you really need a map of < server, list < users > > you can use hashes with stringified user data and then convert it to actual User POJO at application layer

    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>
    

    Also do note that keeping this much big data into a single key is not an ideal thing to do.

    Login or Signup to reply.
  3. i dont use java but here’s how to use 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()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search