在項目有個需求要保存一個字符串到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)
這個方法