在項目有個需求要保存一個字元串到redis,並設置一個過期時間。這個需求一看非常簡單,使用redisTemplate一行代碼搞定,代碼如下 redisTemplate.opsForValue().set("userKey", data, 10000); 但保存後,查看redis發現value的首碼多 ...
在項目有個需求要保存一個字元串到redis,並設置一個過期時間。這個需求一看非常簡單,使用redisTemplate一行代碼搞定,代碼如下
redisTemplate.opsForValue().set("userKey", data, 10000);
但保存後,查看redis發現value的首碼多出了
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
一開始以為是redis的序列化問題,於是就修改了redisTemplate的序列化方式,終於還是沒能解決問題。那問題出在哪裡?翻看源碼,發現redisTemplate.opsForValue().set()有重載方法,一個是
void set(K key, V value, long offset)
另外一個是
void set(K key, V value, long timeout, TimeUnit unit)
調用set(K key, V value, long offset)這個方法,其底層調用的是redis的setrange命令,這個命令看官網介紹
Overwrites part of the string stored at key, starting at the specified offset, for the entire length of value. If the offset is larger than the current length of the string at key, the string is padded with zero-bytes to make offset fit. Non-existing keys are considered as empty strings, so this command will make sure it holds a string large enough to be able to set value at offset
其含義是從指定的偏移量開始,覆蓋整個值範圍內從key存儲的字元串的一部分。如果偏移量大於key處字元串的當前長度,則該字元串將填充零位元組以使偏移量適合。不存在的鍵被視為空字元串,因此此命令將確保它包含足夠大的字元串以能夠將值設置為offset。
調用set(K key, V value, long timeout, TimeUnit unit)這個方法,其底層調用的是redis命令setex。這個命令看官網介紹
Set key to hold the string value and set key to timeout after a given number of seconds
很顯然這個方法,才是我們真正想要的方法。因此解決使用restemplate set方法保存出現\x00\問題的方案就是使用
void set(K key, V value, long timeout, TimeUnit unit)
這個方法