spring Data redis: redisTemplate與Pipeline批量查詢返回值為空的解決方法
使用Spring Data Redis的RedisTemplate進行批量查詢時,尤其采用pipeline模式,經常會遇到返回值為空的情況。即使確認Redis中存在對應數據,問題依舊存在。本文將分析原因并提供解決方案。
問題根源:Pipeline操作結果處理時機錯誤
pipeline模式下,Redis命令并非立即執行并返回結果,而是批量發送,批量接收。 錯誤的處理方式通常在pipeline執行過程中嘗試獲取結果,而此時結果尚未返回。
錯誤示例:在pipeline內部處理結果
以下代碼片段演示了錯誤的處理方式:嘗試在RedisCallback或SessionCallback內部直接反序列化結果。
// 錯誤示例:在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(keySerializer.serialize(key)); // 獲取字節數組 T value = (T) valueSerializer.deserialize(bytes); // 立即反序列化,錯誤! list.add(value); } return null; // 返回null,pipeline結果被忽略 } }); return list; // 返回空列表 }
正確方法:在pipeline執行完畢后處理結果
executePipelined方法返回一個List,包含每個命令的執行結果。正確的做法是在executePipelined之后處理這些結果。
解決方案:正確處理Pipeline結果
以下代碼展示了正確的處理方式:
public <T> List<T> batchGetList(Collection<String> keys) { if (CollectionUtil.isEmpty(keys)) { return new ArrayList<>(); } RedisSerializer<String> keySerializer = redisTemplate.getStringSerializer(); RedisSerializer<T> valueSerializer = redisTemplate.getValueSerializer(); List<byte[]> results = redisTemplate.executePipelined((RedisConnection connection) -> { for (String key : keys) { connection.get(keySerializer.serialize(key)); } return null; // 返回null,pipeline結果在results中 }); return results.stream() .map(bytes -> valueSerializer.deserialize(bytes)) .collect(Collectors.toList()); }
這段代碼首先執行pipeline操作,將所有get命令發送到Redis。然后,在executePipelined返回后,遍歷結果列表,使用valueSerializer反序列化每個byte[]數組,最終得到正確的結果列表。
關鍵點總結:
- Pipeline的本質: 批量發送命令,批量接收結果,不是逐個命令執行和返回。
- 結果處理時機: 在executePipelined方法返回后處理結果,而不是在pipeline操作內部。
- 序列化/反序列化: 使用RedisTemplate的序列化器進行正確的序列化和反序列化操作。
通過以上方法,可以有效解決RedisTemplate和pipeline批量查詢時返回值為空的問題,確保獲取到正確的數據。 請根據實際數據類型選擇合適的序列化器。
? 版權聲明
文章版權歸作者所有,未經允許請勿轉載。
THE END