如果键包含字符串,则从 Redis 获取完整的 Map
Get complete Map from Redis if a key contains a String
我能够从 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,这是我的完整方法:
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;
}
我建议不要在生产中使用“KEYS”命令,因为这会严重影响 REDIS 延迟 (can even bring down the cluster if you have a large number of keys stored)
相反,您可能希望使用与普通 GET/SET 不同的命令。
如果你使用 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>
使用集合,您可以简单地将用户添加到服务器密钥并获取服务器上的完整用户列表。
如果您确实需要 < 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>
另请注意,将这么多大数据保存在一个键中并不是一件理想的事情。
我不使用 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()
我能够从 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,这是我的完整方法:
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;
}
我建议不要在生产中使用“KEYS”命令,因为这会严重影响 REDIS 延迟 (can even bring down the cluster if you have a large number of keys stored)
相反,您可能希望使用与普通 GET/SET 不同的命令。
如果你使用 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>
使用集合,您可以简单地将用户添加到服务器密钥并获取服务器上的完整用户列表。
如果您确实需要 < 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>
另请注意,将这么多大数据保存在一个键中并不是一件理想的事情。
我不使用 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()