如何使用Lettuce客户端读取AWS ElastiCache(Valkey引擎)缓存数据而无需指定键名?
如何使用Lettuce客户端读取AWS ElastiCache(Valkey引擎)缓存数据而无需指定键名?
嘿,针对你的场景我给你梳理下具体的实现方案哈~首先得明确:Valkey和Redis是兼容的,要“不指定具体键名”读取数据,本质是先拿到符合规则的键集合,再批量拉取对应的值。结合你的情况,缓存键都是user:xxx的格式,咱们可以用前缀匹配来过滤,而且绝对要优先用SCAN命令,别用KEYS——KEYS会一次性遍历所有键,在生产环境尤其是无服务器实例上很容易阻塞服务,影响性能,这一点一定要记牢!
方案一:用Spring Boot整合的RedisTemplate实现(推荐,因为Spring Boot已经帮你封装了Lettuce的连接配置)
假设你已经在Spring Boot里配置好了RedisTemplate<String, String>(用Lettuce作为底层客户端),可以直接写一个服务类来实现:
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ScanOptions; import com.fasterxml.jackson.databind.ObjectMapper; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; // 假设你已经定义好对应的User实体类 public class UserCacheService { private final RedisTemplate<String, String> redisTemplate; private final ObjectMapper objectMapper; // 构造注入Spring容器里的RedisTemplate和ObjectMapper public UserCacheService(RedisTemplate<String, String> redisTemplate, ObjectMapper objectMapper) { this.redisTemplate = redisTemplate; this.objectMapper = objectMapper; } public List<User> getAllUsersFromCache() throws Exception { // 1. 用SCAN迭代获取所有匹配`user:*`前缀的键 ScanOptions scanOptions = ScanOptions.scanOptions() .match("user:*") // 精准匹配你的键前缀 .count(100) // 每次迭代建议返回的键数量,不是精确值,可根据实际调整 .build(); List<String> userKeys = new ArrayList<>(); // 执行SCAN迭代逻辑 redisTemplate.execute((RedisCallback<Void>) connection -> { RedisKeyCommands keyCommands = connection.keyCommands(); Cursor<byte[]> cursor = keyCommands.scan(scanOptions); while (cursor.hasNext()) { String key = new String(cursor.next(), StandardCharsets.UTF_8); userKeys.add(key); } cursor.close(); return null; }); // 2. 批量获取所有匹配键对应的值 List<String> userJsonList = redisTemplate.opsForValue().multiGet(userKeys); // 3. 把JSON字符串反序列化为User对象列表 List<User> userList = new ArrayList<>(); for (String json : userJsonList) { if (json != null) { userList.add(objectMapper.readValue(json, User.class)); } } return userList; } }
方案二:用原生Lettuce客户端实现(如果没用到Spring的封装)
如果是直接用原生Lettuce客户端连接ElastiCache Valkey,代码大概是这样的:
import io.lettuce.core.RedisClient; import io.lettuce.core.RedisCommands; import io.lettuce.core.ScanArgs; import io.lettuce.core.ScanCursor; import io.lettuce.core.api.StatefulRedisConnection; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.List; public class LettuceValkeyReader { public static void main(String[] args) throws Exception { // 替换成你的AWS ElastiCache Valkey实例的端点和端口 String valkeyUri = "redis://your-elasticache-endpoint:6379"; RedisClient redisClient = RedisClient.create(valkeyUri); // 用try-with-resources自动管理连接关闭 try (StatefulRedisConnection<String, String> connection = redisClient.connect()) { RedisCommands<String, String> syncCommands = connection.sync(); ObjectMapper objectMapper = new ObjectMapper(); List<String> userKeys = new ArrayList<>(); ScanCursor cursor = ScanCursor.INITIAL; // 循环执行SCAN,直到遍历完所有匹配的键 do { ScanArgs scanArgs = ScanArgs.Builder.matches("user:*").count(100); io.lettuce.core.ScanResult<String> scanResult = syncCommands.scan(cursor, scanArgs); userKeys.addAll(scanResult.getKeys()); cursor = scanResult.getCursor(); } while (!cursor.isFinished()); // 批量拉取所有键对应的值 List<String> userJsonList = syncCommands.mget(userKeys.toArray(new String[0])); // 反序列化为User对象 List<User> userList = new ArrayList<>(); for (String json : userJsonList) { if (json != null) { userList.add(objectMapper.readValue(json, User.class)); } } // 这里就可以处理拿到的userList了,比如打印或者业务逻辑处理 for (User user : userList) { System.out.printf("用户ID: %d, 姓名: %s %s%n", user.getUserId(), user.getFirstName(), user.getLastName()); } } finally { // 关闭客户端 redisClient.shutdown(); } } }
几个生产环境的注意事项
- 关于
SCAN的count参数:这个只是给Valkey服务器的建议值,实际返回的键数量可能多也可能少,不用纠结具体数值,根据你的缓存键总数调整就行,比如键多的话可以设为500或者1000。 - 避免全量遍历:如果不是必须,尽量不要用
*匹配所有键,用精准的前缀(比如user:*)可以减少遍历的键数量,提升效率。 - 反序列化问题:要确保你的
User实体类和缓存里的JSON结构完全匹配,比如字段名大小写、数据类型(比如userId是Integer还是Long),不然会出现反序列化失败的情况,可以在实体类上用@JsonProperty注解来对齐字段名。 - 无服务器版的特殊注意:AWS ElastiCache无服务器版有并发和资源限制,别在业务高峰期执行大规模的SCAN操作,尽量选低峰期或者拆分多次执行。
备注:内容来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

