为什么存 Redis 要加 Serializable

在使用 Redis 进行数据存储时,我们经常会遇到需要将对象进行序列化(Serialization)的情况。序列化是将对象转换为字节流的过程,这样可以方便地将对象存储在内存或者硬盘上,便于传输和持久化。

Redis 是一种高性能的内存数据库,常用于缓存、消息队列等场景。它支持多种数据结构,如字符串、列表、哈希、集合等,可以满足各种不同的业务需求。在 Redis 中存储对象时,为了能够正确地保存和获取对象的数据,我们需要对对象进行序列化和反序列化操作。

Redis 序列化

Redis 提供了两种序列化方式:默认的序列化方式自定义的序列化方式。默认的序列化方式是指 Redis 将对象转化为字符串进行存储,这种方式可以直接存储大部分基本类型以及字符串。但是对于复杂的对象,如自定义的类对象或者集合对象,这种方式可能会存在问题。

示例代码1:使用默认的序列化方式将对象存入 Redis

import redis.clients.jedis.Jedis;

public class RedisSerializationDemo {
    public static void main(String[] args) {
        // 连接 Redis
        Jedis jedis = new Jedis("localhost", 6379);
        
        // 创建一个自定义对象
        User user = new User("Alice", 18);
        
        // 将对象转换为字符串并存入 Redis
        jedis.set("user", user.toString());
        
        // 从 Redis 中获取字符串并转换为对象
        String userStr = jedis.get("user");
        User retrievedUser = User.fromString(userStr);
        
        // 打印获取到的对象
        System.out.println(retrievedUser);
        
        // 关闭连接
        jedis.close();
    }
}

class User {
    private String name;
    private int age;
    
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    // 将对象转换为字符串
    @Override
    public String toString() {
        return name + "," + age;
    }
    
    // 将字符串转换为对象
    public static User fromString(String str) {
        String[] parts = str.split(",");
        String name = parts[0];
        int age = Integer.parseInt(parts[1]);
        
        return new User(name, age);
    }
}

上述代码中,我们使用了默认的序列化方式将一个自定义的 User 对象存入 Redis 中。我们调用了 toString() 方法将 User 对象转换为字符串,并使用 set() 方法存入 Redis。然后使用 get() 方法从 Redis 中获取字符串,并调用 fromString() 方法将字符串转换为 User 对象。最后打印获取到的 User 对象。

这种默认的序列化方式看似简单,但存在一些潜在的问题。由于 Redis 是一个键值数据库,它对数据的存储和读取都是基于字符串的。因此,将对象序列化为字符串时,可能会引入一些额外的字符,导致存储和读取出现问题。这种方式对于复杂的对象结构而言可能不够灵活,而且对于大规模的数据存储也不够高效。

Redis 自定义序列化

为了解决上述问题,我们需要对对象进行自定义序列化。自定义序列化可以将对象转换为字节流,并将字节流存入 Redis。这样可以保证数据的完整性和高效性。

示例代码2:使用自定义的序列化方式将对象存入 Redis

import redis.clients.jedis.Jedis;

import java.io.*;

public class RedisSerializationDemo {
    public static void main(String[] args) {
        // 连接 Redis
        Jedis jedis = new Jedis("localhost", 6379);
        
        // 创建一个自定义对象
        User user = new User("Alice", 18);
        
        // 将对象序列化为字节数组并存入 Redis
        jedis.set("user".getBytes(), serialize(user));
        
        // 从 Redis 中获取字节数组并反序列化为对象
        byte[] userBytes = jedis.get("user".getBytes());
        User retrievedUser = (User