1.问题背景
spring boot整合redis,用户登录成功后将用户id及随机生成的token存储在redis中,在用户做某些操作时,需要先从redis中取出token并验证通过才允许执行。token存储是通过StringRedisTemplate存储,代码如下:
String token = IdUtil.fastUUID();
stringRedisTemplate.opsForValue().set(USER_REDIS_SESSION+":"+user.getId(),token,1000*60*30);
在用户登录验证时,通过stringRedisTemplate取出用户token,代码如下:
String redisToken = stringRedisTemplate.opsForValue().get(USER_REDIS_SESSION+":"+userId);
log.info("redis中的缓存:[{}]",redisToken);
但是无论如何获取不到redis中的缓存数据。
2.问题排查
2.1debug结果如图:
2.2 RedisDesktopManager工具
然后又通过RedisDesktopManager工具查询对应的token值。但是发现查询很长时间一直在转圈,并未查到结果,并且一段时间后该工具崩溃。
2.3 连上服务器,命令行查询
前两种方式,皆不能看出为什么查不出数据。只好连上服务器通过命令行查询,查询结果全是\x00,如图:
(很是壮观啊,我在想是不是我服务器被黑了哈哈)
3.问题解决
难道存储方式有问题?
点进存数据的源码看一下。
/**
* Overwrite parts of {@code key} starting at the specified {@code offset} with given {@code value}.
*
* @param key must not be {@literal null}.
* @param value
* @param offset
* @see <a href="https://redis.io/commands/setrange">Redis Documentation: SETRANGE</a>
*/
void set(K key, V value, long offset);
是不是意识到什么了?这里第三个参数是offset即偏移。该方法的注释说的是用value覆盖该key从指定的偏移量offset开始,并不是我们想要设置的过期时间。
/**
* Set the {@code value} and expiration {@code timeout} for {@code key}.
*
* @param key must not be {@literal null}.
* @param value must not be {@literal null}.
* @param timeout the key expiration timeout.
* @param unit must not be {@literal null}.
* @see <a href="https://redis.io/commands/setex">Redis Documentation: SETEX</a>
*/
void set(K key, V value, long timeout, TimeUnit unit);
这个方法才是我们想要调用的,设置该缓存的过期时间。需要传四个参数,键、值、过期时间、以及TimeUnit即过期时间对应的时间单位,这里我们设置为秒,如图:
测试一下:
ok~问题解决