返回

Redis 默认序列化器导致 Key 乱码的解决之道

后端

为什么 Redis 默认序列化器处理之后的 Key 会带有乱码?

Redis 默认使用 JRE(Java Runtime Environment)的内置序列化机制,该机制将 Java 对象转换为字节数组。然而,如果对象中包含非 UTF-8 字符,则这些字符在序列化过程中可能会被损坏,从而导致解码后的 Key 带有乱码。

乱码产生的原因

Java 默认使用 UTF-8 编码字符,而 Redis 存储 Key 时使用二进制安全字符串。当 JRE 序列化一个包含非 UTF-8 字符的对象时,它会将其转换为一个字节数组,其中每个字节都代表一个字符。但是,如果字节数组包含非 UTF-8 字符,则 Redis 在反序列化时会将其解释为二进制数据,而不是字符,从而导致乱码。

解决乱码的方法

为了避免乱码,有以下几种解决方法:

  1. 使用自定义序列化器: 您可以使用第三方库(例如 Kryo 或 KryoNet)创建自定义序列化器。这些库提供对非 UTF-8 字符的更好的支持。
  2. 手动编码和解码 Key: 您可以手动将 Key 编码为 UTF-8 字符串,然后在反序列化时将其解码。
  3. 使用 RedisJSON 模块: 您可以使用 RedisJSON 模块存储 JSON 数据,它提供对 Unicode 字符的本机支持。
  4. 使用 Redis 提供的序列化器: Redis 提供了 redis.clients.jedis.util.SafeEncoder 类,它提供了对非 UTF-8 字符的更好的支持。

示例代码

import redis.clients.jedis.Jedis;

public class Redis 乱码解决 {

    public static void main(String[] args) {
        // 连接 Redis
        Jedis jedis = new Jedis("localhost");

        // 序列化一个包含非 UTF-8 字符的对象
        String key = "乱码测试";
        String value = "这是一些乱码字符:β€";

        // 将对象存储到 Redis
        jedis.set(key, value);

        // 反序列化并获取对象
        String decodedValue = jedis.get(key);

        // 输出反序列化的对象
        System.out.println(decodedValue); // 输出乱码

        // 使用 Redis 提供的序列化器
        key = "乱码测试2";
        value = "这是一些乱码字符:β€";

        jedis.set(SafeEncoder.encode(key), SafeEncoder.encode(value));

        // 反序列化并获取对象
        String decodedValue2 = SafeEncoder.decode(jedis.get(SafeEncoder.encode(key)));

        // 输出反序列化的对象
        System.out.println(decodedValue2); // 输出正常字符
    }
}

通过使用适当的解决方法,您可以避免 Redis 默认序列化器处理之后的 Key 带有乱码,确保数据完整性和可靠性。