redisTemplate批量查詢返回空值原因及解決方案
使用Java的redisTemplate進行Redis管道(pipeline)批量查詢時,經常會遇到一個棘手的問題:即使keys集合包含有效數據,Redis中也存在對應數據,但返回結果卻全是NULL。這是因為RedisTemplate的管道操作的特性導致的。
問題根源:
RedisTemplate的管道操作會將多個Redis命令批量發送到服務器,但不會立即返回結果。所有命令的執行結果會被緩存,直到調用executePipelined方法后,才一次性從服務器接收響應,并返回一個包含每個命令響應的列表。 因此,在RedisCallback或SessionCallback內部直接處理結果是無效的,因為此時Redis的響應尚未返回。
錯誤代碼示例 (類似原文中的錯誤代碼):
以下代碼片段演示了錯誤的處理方式,它試圖在管道操作內部處理結果:
// 錯誤示例:在pipeline內部嘗試處理結果 public <T> List<T> batchGetList(Collection<String> keys) { List<T> list = new ArrayList<>(); // ... (省略部分代碼) ... List<Object> results = redisTemplate.executePipelined(new RedisCallback<Object>() { @Override public Object doInRedis(RedisConnection connection) throws DataAccessException { for (String key : keys) { byte[] bytes = connection.get(redisTemplate.getKeySerializer().serialize(key)); T obj = (T) redisTemplate.getValueSerializer().deserialize(bytes); // 錯誤:結果尚未返回 list.add(obj); } return null; } }); return list; }
正確解決方案:
正確的做法是在executePipelined之后處理結果列表。 以下代碼展示了正確的處理方式:
public <T> List<T> batchGetList(Collection<String> keys) { if (CollectionUtil.isEmpty(keys)) { return new ArrayList<>(); } List<Object> results = redisTemplate.executePipelined((RedisConnection connection) -> { RedisSerializer<String> keySerializer = redisTemplate.getKeySerializer(); for (String key : keys) { connection.get(keySerializer.serialize(key)); } return null; // executePipelined需要返回null }); // 在管道執行之后處理結果 List<T> resultList = results.stream() .map(result -> { if (result != null) { return (T) redisTemplate.getValueSerializer().deserialize((byte[]) result); } else { return null; // 處理null結果 } }) .collect(Collectors.toList()); return resultList; }
這段代碼首先執行管道操作,然后遍歷results列表,使用redisTemplate.getValueSerializer()對每個byte[]結果進行反序列化。 添加了對null結果的處理,以避免NullPointerException。 確保你的RedisTemplate配置了正確的序列化器。
關鍵點:
- executePipelined的返回值: executePipelined方法返回一個包含所有命令執行結果的列表。 在Lambda表達式中返回null是必要的。
- 結果處理位置: 結果處理必須在executePipelined調用之后進行。
- 序列化器: 確保RedisTemplate配置了正確的鍵和值序列化器,以匹配你存儲在Redis中的數據類型。
- 空值處理: 對results列表中的null值進行處理,防止出現異常。
通過以上改進,可以有效解決RedisTemplate管道批量查詢返回空值的問題。 記住,管道操作的效率提升來自于批量執行,結果處理必須在批量操作完成之后進行。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END