一、背景
使用Spring Boot整合Redis,将数据保存到redis后,登陆redis客户端,发现redis key前面多了一串乱码字符\xac\xed\x00\x05t\x00\x17(具体图片就不贴了,类似的图片网上有很多),排查发现是因为spring-data-redis中redisTemplate默认使用JDK的序列化策略JdkSerializationRedisSerializer,通过设置redisTemplate的序列化策略为StringRedisSerializer后,乱码key的问题解决了,但是已经写入的redis数据如何删除呢?(因为需要长期使用,在写入时没有设置过期时间)。尝试了几种方式,终于找到了一种可行的方案,记录一下,也记录一下这个过程中学到的新知识。
二、难点
为什么带乱码的redis key难删除呢?说一下操作的现象:
1、在redis-cli中可以显示成\xac\xed\x00\x05t\x00\x17的字符序列到了IDEA的控制台输出和iTerm Terminal显示成乱码,这个乱码是真的不可读的乱码。(这个应该是标准输入/输出显示的问题,不能显示这串16进制的字符)
2、在redis-cli中,正常来讲删除一个key,直接使用del key就可以了。key是否带双引号都能正常删除,但是对于这种乱码key,必须带上双引号才能删除,否则删除不了。(具体这个啥原因不太清楚)
3、redis的keys命令是被禁掉的。(redis 批量删除键给出了一个使用Lua脚本的方法,但是依赖keys命令。该方法可行与否待验证)
之前是可以用scan和del命令结合来删除redis中key的,但是因为1和2的原因,也没能成功。附一下之前使用的命令:
redis-cli -h 127.0.0.1 -p 6379 -a 123456 --scan --pattern "*" | xargs -L 1000 redis-cli -h 127.0.0.1 -p 6379 -a 123456 DEL
三、调研
3.1 观察发现2点,1、这些key前面的乱码字符都是一致的,2、在写入时设置了key前缀,这2点也为后面的批量删除操作提供了可能。
3.2 通过脚本批量执行Redis命令这篇文章,发现可以将redis命令放在一个文本中,通过--pipe方式批量执行redis命令。
如先将命令保存在command.txt中,
示例1:
SET Key0 Value0
SET Key1 Value1
...
SET KeyN ValueN
示例2:
DEL "\xac\xed\x00\x05t\x00\x17redis:prefix1"
DEL "\xac\xed\x00\x05t\x00\x17redis:prefix2"
DEL "\xac\xed\x00\x05t\x00\x17redis:prefix3"
DEL "\xac\xed\x00\x05t\x00\x17redis:prefix4"
再通过使用以下命令执行。
cat command.txt | redis-cli -h 127.0.0.1 -p 6379 -a 123456 --pipe
四、具体实施方案
1、java通过jedis连接redis,找到所有需要删除的redis key
2、把需要删除的redis key的前面不能正常显示的字符替换成\xac\xed\x00\x05t\x00\x17
3、给redis key加上双引号
4、在带双引号的redis key前面拼接上redis命令DEL
5、将所有命令保存在command.txt中,执行redis-cli --pipe命令
Done!
五、补充学习知识点
1、redis 相关、Lua脚本的使用等
Redis 4.0的了解以及使用 (注意下redis.replicate_commands())
2、spring-data-redis序列化方式的对比和选择
3、SpringBoot项目使用RedisTemplate设置序列化方式
Spring Boot 解决整合Redis后key值乱码的问题
4、字符串编码、编码格式和编码转换等
SpringBoot整合Redis乱码原因及解决方案(RedisTemplate默认使用的是JDK序列化器,而它使用的编码是ISO-8859-1。linux/unix系统默认的编码为:utf-8)
5、jedis源码