使用RedisTemplate和Pipeline批量查詢時返回值為空的原因是什么?如何解決這一問題?

使用RedisTemplate和Pipeline批量查詢時返回值為空的原因是什么?如何解決這一問題?

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
喜歡就支持一下吧
點贊10 分享