共计 1165 个字符,预计需要花费 3 分钟才能阅读完成。
在项目有个需求要保存一个字符串到 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)
这个方法