【Redis】存入redis的值,莫名其妙多了很多“\u0000”

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis缓存异常,取出的值前出现`\u0000`或部分被覆盖。问题源于误用`set(key, value, expireTime)`方法,该方法实际上按指定偏移量追加覆盖,而非设置完整值,导致额外填充`\u0000`。正确方法应为`set(key, value, timeout, TimeUnit.SECONDS)`来设置键值对和过期时间。使用重载方法时需仔细理解参数含义,避免混淆。

背景

记录在redis中的多语言缓存,突然发现取值无法正常解析,加日志后发现,从redis取出来的值,有些在正常值的前面多了很多 \u0000 ,有些值好像是覆盖原有值但没覆盖全的样子 {"key":"new Value"}lue"},导致在解析数据是报错。

定位问题

通过记录日志,发现在向redis中添加值时,值还是正常的,再取出来,就会发生这些变化,于是怀疑问题出在set方法上。

排查代码,发现代码中使用了两种set方法。

  1. set(k, v, expireTime);
  2. set(k, v, expireTime,TimeUnit.SECONDS);

这两个方法乍一看,好像是少了个设置超时时间的单位,但实际上这两个方法的功能完全不一样。

void set(K key, V value, long offset)

这个三参的方法de Jdoc如下,用指定的值,追加覆盖原有内容,追加覆盖的位置由offset确定。

Overwrite parts of key starting at the specified offset with given value.
Params:
key – must not be null.
value –
offset –

需要注意的是,如果原有内容长度不够,则会使用\u0000填充到足够的长度。

比如:现有键值对 {"test":"ABCD"}, 使用set("test","12",10),会有以下操作

ABCD不足10,所以使用 \u0000填充到长度10,即 ABCD\u0000\u0000\u0000\u0000\u0000\u0000

然后追加覆盖12, 最后的值为ABCD\u0000\u0000\u0000\u0000\u0000\u000012

这个在调试时才会看到,控制台打印出来的结果是ABCD12

void set(K key, V value, long timeout, TimeUnit unit)

这个方法才是正确的保存键值对,并设置过期时间。

Set the value and expiration timeout for key.
Params:
key – must not be null.
value – must not be null.
timeout – the key expiration timeout.
unit – must not be null.

总结

使用重载方法时,需要确认方法每个参数的含义,确认方法的功能,虽然有些参数类型是一样的,但实现的功能也会千差万别。 切记切记。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
NoSQL Java 数据库连接
使用Java实现从数据库查出数据存入Redis,并在查询时先查Redis,如果Redis中没有数据再从数据库中读取
使用Java实现从数据库查出数据存入Redis,并在查询时先查Redis,如果Redis中没有数据再从数据库中读取
659 1
|
12月前
|
缓存 NoSQL fastjson
Shiro Session集群共享存入Redis中SimpleSession的transient 属性不能序列化
Shiro Session集群共享存入Redis中SimpleSession的transient 属性不能序列化
159 0
|
NoSQL Redis
go-redis 之结构体数组的存入取出
go-redis 之结构体数组的存入取出
1255 0
|
4月前
|
存储 JSON NoSQL
JSON 存入 Redis
【7月更文挑战第8天】
106 12
|
6月前
|
NoSQL Redis
redis存入中文---的格式
redis存入中文---的格式
32 0
|
12月前
|
NoSQL Java Redis
redis命令行存入了数据,代码获取不到
redis命令行存入了数据,代码获取不到
|
存储 NoSQL 应用服务中间件
|
消息中间件 NoSQL 前端开发
实时统计每天pv,uv的sparkStreaming结合redis结果存入mysql供前端展示
最近有个需求,实时统计pv,uv,结果按照date,hour,pv,uv来展示,按天统计,第二天重新统计,当然了实际还需要按照类型字段分类统计pv,uv,比如按照date,hour,pv,uv,type来展示。这里介绍最基本的pv,uv的展示。
362 0
实时统计每天pv,uv的sparkStreaming结合redis结果存入mysql供前端展示
|
JSON NoSQL Java
【redis序列化】配置Jedis不需要序列化存入json 序列化Joda DateTime
【redis序列化】配置Jedis不需要序列化存入json 序列化Joda DateTime
1542 0
【redis序列化】配置Jedis不需要序列化存入json  序列化Joda DateTime
|
NoSQL Java Redis
从C++到JSON,存入redis数据库再逆序列化为JAVA。
目录 目录 一 基本原理 1原理图 二 从C序列化到JSON存入redis 1环境清单 2开始工作 3 总结归纳 三 从redis取出逆序列化为JAVA 四 声明 一 、基本原理. 1.1原理图 Created with Raphaël 2.1.0c++Json-Redis-Json Java 二 、从C++序列化到JS
2692 0