Redis数据乱码修复折腾记,怎么越改越乱还没头绪
- 问答
- 2025-12-25 04:23:57
- 4
(来源:知乎用户“码农小张的日常”博客分享)
那天下午,我正喝着咖啡摸鱼,突然测试群里炸了锅,好几个同事反馈说,后台管理系统里显示的用户昵称和备注信息变成了一堆乱码,像“ååå¾é•¿çš„用戔这样的天书,我心里咯噔一下,完了,肯定是Redis又出幺蛾子了。
我们的项目用的是Java,配合Spring Boot和Jedis客户端操作Redis,一开始,我以为是简单的编码问题。(来源:博主初步判断)心想,这还不简单嘛,肯定是存数据的时候和取数据的时候编码对不上,我印象中Redis默认编码是UTF-8,于是我先登录服务器,用redis-cli直接查了一下那个出问题的用户key,果然,在命令行里直接get user:123:info,显示出来的也是一堆乱码,这似乎印证了我的想法——数据在存入时就已经错了。
我的第一个“妙招”是:检查连接配置。(来源:博主第一次尝试)我冲到项目的配置文件中,找到了Jedis的连接池配置,反复确认了没有设置什么奇怪的charset参数,按理说,默认就是UTF-8啊,我不放心,又显式地在配置里加上了spring.redis.charset=UTF-8(虽然我知道新版本Spring Boot可能已经不这么配了),重启应用,满怀期待地刷新页面——结果乱码纹丝不动,还是那副鬼样子。

一计不成,又生一计,我怀疑是Redis服务端本身的配置有问题。(来源:博主第二次折腾)我查遍了Redis的配置文件redis.conf,里面压根就没有一个可以设置默认字符集的选项,网上搜了一圈,有人说可能和redis-cli的启动参数有关,于是我又尝试用redis-cli --raw命令来查询,这次--raw模式显示出来的中文居然是正常的!“张三”显示成了“张三”,不再是乱码,我一下子来了精神,以为找到了关键所在。
问题肯定出在客户端读取的方式上!(来源:博主的错误推论)我以为--raw参数是解决问题的金钥匙,于是开始疯狂地在Java代码里寻找等效设置,我把Jedis客户端的各种参数翻了个底朝天,什么client.setEncoding("UTF-8")之类的法子都试了(后来发现方法可能都不存在),折腾了半天,代码编译都过不去,我又尝试换用Lettuce客户端,结果乱码依旧,这时候我已经有点上头了,感觉问题像个泥鳅,怎么也抓不住。

就在我快要放弃的时候,一位路过的高级工程师看我对着屏幕龇牙咧嘴,凑过来问了一句:“你是不是用redis-cli直接存过中文?”(来源:关键转折点,同事提醒)这句话像一道闪电劈中了我,我猛地想起来,大概一周前,我确实为了测试一个紧急功能,在没有设置--raw参数的情况下,直接用redis-cli的set命令插入过几条包含中文的测试数据!
真相大白了。(来源:问题根源剖析)原因根本不在Java应用端,而在于我那次不规范的操作,标准的redis-cli在没有--raw参数时,会对输入输出进行编码转换,如果我当时输入的中文终端编码(比如是GBK)和Redis实际存储的编码(期望是UTF-8)不一致,存入的就已经是错误编码的二进制数据了,之后Java应用用UTF-8方式去读这些“脏数据”,自然就解码成了乱码,而我后来用redis-cli --raw去读,它不做转换直接显示二进制,碰巧我终端的编码是UTF-8,反而把当初错误存入的GBK编码数据“蒙”对了,显示成了正常中文,这给了我一个巨大的误导。
修复过程反而简单了。(来源:最终解决方案)我写了个小脚本,用Java程序遍历所有可能污染的key,先用错误的编码(GBK)把二进制数据解码成字符串,然后再用正确的编码(UTF-8)重新编码成二进制,最后再写回Redis,执行完脚本,刷新页面,所有乱码都恢复了正常。
经过这番折腾,我算是彻底明白了:(来源:博主总结教训)乱码问题不能想当然,一定要搞清楚数据生命周期的每一个环节——从哪个客户端、以什么编码写入,存储为什么二进制,又被哪个客户端、以什么编码读出,任何一个环节 mismatch,都会导致一场抓狂的乱码风波,以后用命令行操作Redis,我一定记得带上--raw参数,从源头上杜绝这种糊涂账,这次经历,真是应了那句话——解决问题最大的障碍,不是问题本身有多难,而是我们自己先入为主的错误判断。
本文由帖慧艳于2025-12-25发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://haoid.cn/wenda/67952.html
