欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot整合Redis實現(xiàn)序列化的7種策略詳解

 更新時間:2025年04月25日 08:42:53   作者:風象南  
在分布式系統(tǒng)中,Redis作為高性能的緩存和數(shù)據(jù)存儲解決方案被廣泛應用,本文將介紹SpringBoot中Redis的7種序列化策略,有需要的小伙伴可以根據(jù)需求進行選擇

在分布式系統(tǒng)中,Redis作為高性能的緩存和數(shù)據(jù)存儲解決方案被廣泛應用。當使用SpringBoot框架整合Redis時,序列化策略的選擇直接影響到系統(tǒng)的性能、兼容性和可維護性。

序列化是將Java對象轉換為可在網(wǎng)絡上傳輸或存儲在磁盤上的過程,反序列化則是將這些數(shù)據(jù)重新轉換為Java對象。

合適的序列化策略能夠帶來以下好處:

  • 提高系統(tǒng)性能和存儲效率
  • 增強跨語言和跨平臺互操作性
  • 降低網(wǎng)絡傳輸和存儲開銷
  • 提供更好的安全性和可維護性

本文將介紹SpringBoot中Redis的7種序列化策略

1. JdkSerializationRedisSerializer

1.1 原理介紹

JdkSerializationRedisSerializer是Spring Data Redis默認的序列化策略,它使用Java原生的序列化機制(java.io.Serializable)將對象序列化為字節(jié)數(shù)組。這種方式要求被序列化的對象必須實現(xiàn)Serializable接口。

1.2 實現(xiàn)方式

@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 使用JdkSerializationRedisSerializer對value進行序列化
        template.setValueSerializer(new JdkSerializationRedisSerializer());
        
        // 使用StringRedisSerializer對key進行序列化
        template.setKeySerializer(new StringRedisSerializer());
        
        template.afterPropertiesSet();
        return template;
    }
}

使用示例:

@Service
public class UserService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public void saveUser(User user) {
        // User類必須實現(xiàn)Serializable接口
        redisTemplate.opsForValue().set("user:" + user.getId(), user);
    }
    
    public User getUser(Long id) {
        return (User) redisTemplate.opsForValue().get("user:" + id);
    }
}

1.3 優(yōu)缺點分析

優(yōu)點

  • 集成在JDK中,無需引入第三方依賴
  • 使用簡單,與Spring Data Redis無縫集成
  • 能處理復雜的對象圖和循環(huán)引用

缺點

  • 序列化后的數(shù)據(jù)體積較大,占用存儲空間
  • 序列化/反序列化性能較差,影響系統(tǒng)吞吐量
  • 序列化結果是二進制,不可讀性
  • 強耦合于Java平臺,不支持跨語言操作
  • 對類的修改敏感,可能導致反序列化兼容性問題

適用場景

  • 內(nèi)部系統(tǒng)臨時緩存,數(shù)據(jù)量不大且性能要求不高
  • 簡單快速搭建原型系統(tǒng)
  • 系統(tǒng)全部采用Java技術棧,無跨語言需求
  • 對象結構復雜且包含循環(huán)引用

2. StringRedisSerializer

2.1 原理介紹

StringRedisSerializer是最簡單的序列化器,它直接將String類型的數(shù)據(jù)按照指定的字符集(默認UTF-8)編碼為字節(jié)數(shù)組。由于其簡單高效的特性,它通常用于Redis的key序列化,也適用于value為String類型的場景。

2.2 實現(xiàn)方式

@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, String> stringRedisTemplate(RedisConnectionFactory connectionFactory) {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(connectionFactory);
        return template;
    }
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 對key使用StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        
        // 對value可以使用其他序列化器
        // ...
        
        template.afterPropertiesSet();
        return template;
    }
}

使用示例:

@Service
public class CacheService {
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    public void saveString(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }
    
    public String getString(String key) {
        return stringRedisTemplate.opsForValue().get(key);
    }
}

2.3 優(yōu)缺點分析

優(yōu)點

  • 結果可讀性好,便于調(diào)試和監(jiān)控
  • 內(nèi)存占用少,序列化后體積小
  • 與Redis命令行客戶端兼容,便于管理
  • 支持跨語言操作

缺點

  • 僅支持String類型,無法直接存儲復雜對象
  • 存儲對象需要先轉為字符串(如JSON),增加額外步驟

適用場景

  • Redis的key值序列化
  • 存儲簡單的字符串數(shù)據(jù)
  • 存儲已序列化為字符串的數(shù)據(jù)(如JSON、XML)
  • 需要通過Redis命令行查看或修改數(shù)據(jù)
  • 多語言系統(tǒng)協(xié)作場景

3. Jackson2JsonRedisSerializer

3.1 原理介紹

Jackson2JsonRedisSerializer使用Jackson庫將對象序列化為JSON格式的字符串。它能處理大多數(shù)常見的Java對象,并產(chǎn)生人類可讀的序列化結果,同時提供了較好的性能和壓縮率。該序列化器需要指定序列化的目標類型。

3.2 實現(xiàn)方式

@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, User> userRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, User> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 對key使用StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        
        // 對User對象使用Jackson2JsonRedisSerializer
        Jackson2JsonRedisSerializer<User> serializer = new Jackson2JsonRedisSerializer<>(User.class);
        
        // 配置ObjectMapper以增強序列化功能
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, 
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        serializer.setObjectMapper(mapper);
        
        template.setValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }
}

使用示例:

@Service
public class UserCacheService {
    
    @Autowired
    private RedisTemplate<String, User> userRedisTemplate;
    
    public void saveUser(User user) {
        userRedisTemplate.opsForValue().set("user:" + user.getId(), user);
    }
    
    public User getUser(Long id) {
        return userRedisTemplate.opsForValue().get("user:" + id);
    }
}

3.3 優(yōu)缺點分析

優(yōu)點

  • 序列化結果是JSON格式,具有很好的可讀性
  • 性能較好,序列化后體積適中
  • JSON格式支持跨語言和跨平臺操作

缺點

  • 需要指定序列化的目標類型,不夠靈活
  • 無法直接處理泛型和多態(tài)對象
  • 序列化/反序列化復雜對象可能需要額外配置
  • 容易出現(xiàn)類型轉換問題

適用場景

  • 已知且固定類型的對象緩存
  • 需要跨語言讀取緩存數(shù)據(jù)
  • 緩存數(shù)據(jù)需要人工查看和修改
  • RESTful API系統(tǒng)使用Redis作為緩存層

4. GenericJackson2JsonRedisSerializer

4.1 原理介紹

GenericJackson2JsonRedisSerializer是Jackson2JsonRedisSerializer的增強版,它無需指定目標類型,能夠處理任何類型的Java對象。它通過在JSON中嵌入類型信息來支持泛型和多態(tài),使反序列化能夠正確恢復對象類型。

4.2 實現(xiàn)方式

@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 對key使用StringRedisSerializer
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        
        // 使用GenericJackson2JsonRedisSerializer進行序列化
        GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
        template.setValueSerializer(jsonSerializer);
        template.setHashValueSerializer(jsonSerializer);
        
        template.afterPropertiesSet();
        return template;
    }
}

使用示例

@Service
public class CacheService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // 可以存儲任何類型的對象
    public <T> void save(String key, T object) {
        redisTemplate.opsForValue().set(key, object);
    }
    
    // 無需進行類型轉換
    @SuppressWarnings("unchecked")
    public <T> T get(String key, Class<T> type) {
        return (T) redisTemplate.opsForValue().get(key);
    }
    
    // 存儲泛型集合
    public <T> void saveList(String key, List<T> list) {
        redisTemplate.opsForValue().set(key, list);
    }
    
    // 獲取泛型集合
    @SuppressWarnings("unchecked")
    public <T> List<T> getList(String key) {
        return (List<T>) redisTemplate.opsForValue().get(key);
    }
}

4.3 優(yōu)缺點分析

優(yōu)點

  • 支持任意Java類型,無需指定目標類
  • 能正確處理泛型和多態(tài)對象
  • 序列化結果是JSON格式,具有很好的可讀性
  • 性能較好,與Jackson2JsonRedisSerializer相當

缺點

  • 序列化結果中包含類型信息,導致體積增大
  • 反序列化需要類路徑中存在相應的類
  • 類重構后可能導致反序列化失敗
  • 包含類型信息的JSON不易于其他語言處理

適用場景:

  • 存儲多種不同類型的Java對象
  • 需要處理泛型集合和多態(tài)對象
  • 類型不確定或頻繁變化的場景
  • 純Java技術棧且序列化數(shù)據(jù)不需要跨語言處理

5. FastJsonRedisSerializer

5.1 原理介紹

FastJsonRedisSerializer基于阿里巴巴的FastJson庫,F(xiàn)astJson是一個性能優(yōu)越的JSON處理庫,專為Java平臺設計。它提供了極高的序列化和反序列化性能,在處理大量數(shù)據(jù)時尤其明顯。

5.2 實現(xiàn)方式

首先,添加FastJson依賴:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

創(chuàng)建自定義FastJson序列化器

public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {

    private final Class<T> clazz;
    
    public FastJsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        try {
            return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(StandardCharsets.UTF_8);
        } catch (Exception ex) {
            throw new SerializationException("Could not serialize: " + ex.getMessage(), ex);
        }
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            String str = new String(bytes, StandardCharsets.UTF_8);
            return JSON.parseObject(str, clazz);
        } catch (Exception ex) {
            throw new SerializationException("Could not deserialize: " + ex.getMessage(), ex);
        }
    }
}

配置RedisTemplate

@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 使用StringRedisSerializer來序列化key
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        
        // 使用FastJsonRedisSerializer來序列化value
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);
        
        // 配置FastJson的特性
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        
        template.afterPropertiesSet();
        return template;
    }
}

使用示例

@Service
public class ProductService {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    public void saveProduct(Product product) {
        redisTemplate.opsForValue().set("product:" + product.getId(), product);
    }
    
    public Product getProduct(Long id) {
        return (Product) redisTemplate.opsForValue().get("product:" + id);
    }
    
    public void saveProductList(List<Product> products) {
        redisTemplate.opsForValue().set("products:list", products);
    }
    
    @SuppressWarnings("unchecked")
    public List<Product> getProductList() {
        return (List<Product>) redisTemplate.opsForValue().get("products:list");
    }
}

5.3 優(yōu)缺點分析

優(yōu)點

  • 序列化/反序列化性能卓越,比Jackson快1.5-2倍
  • 內(nèi)存占用較小,序列化后的數(shù)據(jù)體積較小
  • 處理大數(shù)據(jù)量時優(yōu)勢明顯
  • 支持自動類型識別和泛型處理

缺點

  • 存在安全漏洞風險,需要注意版本選擇,建議使用fastjson2版本
  • 對于復雜對象的處理可能不如Jackson穩(wěn)定
  • 不是跨平臺標準,主要在Java生態(tài)系統(tǒng)中使用

適用場景

  • 對性能要求極高的系統(tǒng)
  • 大數(shù)據(jù)量的緩存場景
  • 純Java技術棧應用

6. Kryo序列化

6.1 原理介紹

Kryo是一個快速高效的Java序列化框架,它產(chǎn)生的序列化結果非常緊湊,序列化和反序列化速度極快。

Kryo不僅比Java原生序列化快,而且比JSON序列化也快很多。它使用二進制格式,且支持對象圖的處理(包括循環(huán)引用)。

6.2 實現(xiàn)方式

首先,添加Kryo依賴:

<dependency>
    <groupId>com.esotericsoftware</groupId>
    <artifactId>kryo</artifactId>
    <version>5.3.0</version>
</dependency>

創(chuàng)建Kryo序列化器:

public class KryoRedisSerializer<T> implements RedisSerializer<T> {
    
    private static final byte[] EMPTY_ARRAY = new byte[0];
    
    private final Class<T> clazz;
    private final ThreadLocal<Kryo> kryoThreadLocal = ThreadLocal.withInitial(() -> {
        Kryo kryo = new Kryo();
        kryo.setRegistrationRequired(false); // 關閉注冊要求,自動注冊類
        kryo.setReferences(true); // 支持循環(huán)引用
        return kryo;
    });
    
    public KryoRedisSerializer(Class<T> clazz) {
        this.clazz = clazz;
    }
    
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return EMPTY_ARRAY;
        }
        
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             Output output = new Output(baos)) {
            
            Kryo kryo = kryoThreadLocal.get();
            kryo.writeObject(output, t);
            output.flush();
            
            return baos.toByteArray();
        } catch (Exception e) {
            throw new SerializationException("Error serializing object using Kryo", e);
        }
    }
    
    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        
        try (Input input = new Input(bytes)) {
            Kryo kryo = kryoThreadLocal.get();
            return kryo.readObject(input, clazz);
        } catch (Exception e) {
            throw new SerializationException("Error deserializing object using Kryo", e);
        }
    }
}

配置RedisTemplate:

@Configuration
public class RedisKryoConfig {
    
    @Bean
    public RedisTemplate<String, Object> kryoRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 使用StringRedisSerializer來序列化key
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        
        // 使用KryoRedisSerializer來序列化value
        KryoRedisSerializer<Object> kryoSerializer = new KryoRedisSerializer<>(Object.class);
        template.setValueSerializer(kryoSerializer);
        template.setHashValueSerializer(kryoSerializer);
        
        template.afterPropertiesSet();
        return template;
    }
}

使用示例:

@Service
public class UserSessionService {
    
    @Autowired
    @Qualifier("kryoRedisTemplate")
    private RedisTemplate<String, Object> kryoRedisTemplate;
    
    public void saveUserSession(String sessionId, UserSession session) {
        kryoRedisTemplate.opsForValue().set("session:" + sessionId, session, 30, TimeUnit.MINUTES);
    }
    
    public UserSession getUserSession(String sessionId) {
        return (UserSession) kryoRedisTemplate.opsForValue().get("session:" + sessionId);
    }
    
    public void saveComplexObject(String key, ComplexObject object) {
        kryoRedisTemplate.opsForValue().set(key, object);
    }
    
    public ComplexObject getComplexObject(String key) {
        return (ComplexObject) kryoRedisTemplate.opsForValue().get(key);
    }
}

6.3 優(yōu)缺點分析

優(yōu)點

  • 卓越的序列化/反序列化性能,比JSON快3-5倍
  • 序列化結果體積非常小,內(nèi)存占用低
  • 能夠處理復雜對象圖和循環(huán)引用
  • 支持對象版本控制,有一定的向前兼容性

缺點

  • 序列化結果為二進制,不可讀
  • 使用復雜度較高,需要考慮線程安全
  • 對大量類型需要注冊以獲得最佳性能
  • 跨語言支持有限
  • 類模型變更后可能面臨兼容性問題

適用場景

  • 對性能和內(nèi)存占用有極高要求的場景
  • 序列化大量復雜對象圖
  • 需要高效處理循環(huán)引用的情況
  • 純Java技術棧,無跨語言需求

7. Protocol Buffers (ProtoBuf)

7.1 原理介紹

Protocol Buffers(ProtoBuf)是由Google開發(fā)的一種語言無關、平臺無關、可擴展的結構化數(shù)據(jù)序列化機制。它比XML更小、更快、更簡單,適用于通信協(xié)議、數(shù)據(jù)存儲等場景。

ProtoBuf使用預定義的消息格式,通過專用編譯器生成代碼,實現(xiàn)高效的序列化和反序列化。

7.2 實現(xiàn)方式

首先,添加Protocol Buffers依賴:

<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.21.7</version>
</dependency>
<dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java-util</artifactId>
    <version>3.21.7</version>
</dependency>

定義.proto文件 (src/main/proto/user.proto):

syntax = "proto3";

package com.example.model;
option java_package = "com.example.model.proto";
option java_outer_classname = "UserProto";

message User {
  int64 id = 1;
  string username = 2;
  string email = 3;
  int32 age = 4;
  
  enum UserType {
    NORMAL = 0;
    VIP = 1;
    ADMIN = 2;
  }
  
  UserType userType = 5;
  repeated string roles = 6;
  map<string, string> attributes = 7;
}

配置Maven插件生成Java代碼:

<plugin>
    <groupId>org.xolstice.maven.plugins</groupId>
    <artifactId>protobuf-maven-plugin</artifactId>
    <version>0.6.1</version>
    <extensions>true</extensions>
    <configuration>
        <protocArtifact>com.google.protobuf:protoc:3.21.7:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <protoSourceRoot>${project.basedir}/src/main/proto</protoSourceRoot>
        <outputDirectory>${project.build.directory}/generated-sources/protobuf/java</outputDirectory>
        <clearOutputDirectory>false</clearOutputDirectory>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

創(chuàng)建ProtoBuf序列化器:

public class ProtobufRedisSerializer<T extends MessageLite> implements RedisSerializer<T> {
    
    private final Class<T> clazz;
    private final Method parseFromMethod;
    
    public ProtobufRedisSerializer(Class<T> clazz) {
        this.clazz = clazz;
        try {
            this.parseFromMethod = clazz.getMethod("parseFrom", byte[].class);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException("Could not find parseFrom method on class " + clazz.getName());
        }
    }
    
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        try {
            return t.toByteArray();
        } catch (Exception e) {
            throw new SerializationException("Error serializing ProtoBuf message", e);
        }
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            return (T) parseFromMethod.invoke(null, bytes);
        } catch (Exception e) {
            throw new SerializationException("Error deserializing ProtoBuf message", e);
        }
    }
}

配置RedisTemplate:

@Configuration
public class RedisProtobufConfig {
    
    @Bean
    public RedisTemplate<String, UserProto.User> protobufRedisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<String, UserProto.User> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        
        // 使用StringRedisSerializer來序列化key
        template.setKeySerializer(new StringRedisSerializer());
        
        // 使用ProtobufRedisSerializer來序列化value
        ProtobufRedisSerializer<UserProto.User> protobufSerializer = new ProtobufRedisSerializer<>(UserProto.User.class);
        template.setValueSerializer(protobufSerializer);
        
        template.afterPropertiesSet();
        return template;
    }
}

使用示例:

@Service
public class UserProtobufService {
    
    @Autowired
    private RedisTemplate<String, UserProto.User> protobufRedisTemplate;
    
    public void saveUser(UserProto.User user) {
        protobufRedisTemplate.opsForValue().set("proto:user:" + user.getId(), user);
    }
    
    public UserProto.User getUser(long id) {
        return protobufRedisTemplate.opsForValue().get("proto:user:" + id);
    }
    
    // 創(chuàng)建示例用戶對象
    public UserProto.User createSampleUser(long id, String username) {
        return UserProto.User.newBuilder()
                .setId(id)
                .setUsername(username)
                .setEmail(username + "@example.com")
                .setAge(30)
                .setUserType(UserProto.User.UserType.VIP)
                .addRoles("USER")
                .addRoles("EDITOR")
                .putAttributes("department", "Engineering")
                .putAttributes("location", "Beijing")
                .build();
    }
}

將ProtoBuf對象轉換為業(yè)務對象:

@Component
public class UserMapper {
    
    // ProtoBuf對象轉換為業(yè)務對象
    public User protoToUser(UserProto.User protoUser) {
        User user = new User();
        user.setId(protoUser.getId());
        user.setUsername(protoUser.getUsername());
        user.setEmail(protoUser.getEmail());
        user.setAge(protoUser.getAge());
        
        // 轉換枚舉類型
        switch (protoUser.getUserType()) {
            case VIP:
                user.setUserType(UserType.VIP);
                break;
            case ADMIN:
                user.setUserType(UserType.ADMIN);
                break;
            default:
                user.setUserType(UserType.NORMAL);
        }
        
        // 轉換列表
        user.setRoles(new ArrayList<>(protoUser.getRolesList()));
        
        // 轉換Map
        user.setAttributes(new HashMap<>(protoUser.getAttributesMap()));
        
        return user;
    }
    
    // 業(yè)務對象轉換為ProtoBuf對象
    public UserProto.User userToProto(User user) {
        UserProto.User.Builder builder = UserProto.User.newBuilder()
                .setId(user.getId())
                .setUsername(user.getUsername())
                .setEmail(user.getEmail())
                .setAge(user.getAge());
        
        // 轉換枚舉類型
        switch (user.getUserType()) {
            case VIP:
                builder.setUserType(UserProto.User.UserType.VIP);
                break;
            case ADMIN:
                builder.setUserType(UserProto.User.UserType.ADMIN);
                break;
            default:
                builder.setUserType(UserProto.User.UserType.NORMAL);
        }
        
        // 轉換列表
        if (user.getRoles() != null) {
            builder.addAllRoles(user.getRoles());
        }
        
        // 轉換Map
        if (user.getAttributes() != null) {
            builder.putAllAttributes(user.getAttributes());
        }
        
        return builder.build();
    }
}

7.3 優(yōu)缺點分析

優(yōu)點

  • 序列化/反序列化性能極高
  • 序列化結果體積小,是XML的10倍壓縮比
  • 跨語言,支持多種編程語言
  • 向前兼容和向后兼容性良好
  • 自帶字段類型校驗
  • 代碼生成,減少編碼錯誤

缺點

  • 需要預定義消息結構(Proto文件)
  • 實現(xiàn)復雜度高,需要額外的構建步驟
  • 對象模型變更需要重新生成代碼
  • 動態(tài)類型支持有限
  • 難以直接查看或調(diào)試緩存內(nèi)容

適用場景:

  • 多語言系統(tǒng)協(xié)作場景
  • 性能要求極高的實時系統(tǒng)
  • 對帶寬要求苛刻的系統(tǒng)
  • 需要嚴格的字段驗證
  • 消息格式相對穩(wěn)定且可預定義的場景
  • 大規(guī)模分布式系統(tǒng)

總結對比

序列化方式序列化性能體積大小可讀性跨語言復雜度類型信息向前兼容性
JDK完整
String極高優(yōu)極低優(yōu)
Jackson2Json優(yōu)
GenericJackson2Json中偏大完整
FastJson中偏小優(yōu)有限可選
Kryo極高極小有限
ProtoBuf極高極小極高完整優(yōu)

選型建議

根據(jù)不同的應用場景,以下是序列化策略的選擇建議:

  • 通用Web應用

    • 推薦:GenericJackson2JsonRedisSerializer
    • 理由:通用性好,可讀性高,支持復雜對象,性能適中
  • 高性能Java應用

    • 推薦:Kryo 或 FastJsonRedisSerializer
    • 理由:極高的性能和低內(nèi)存占用,適合同構Java系統(tǒng)
  • 跨語言系統(tǒng)

    • 推薦:ProtoBuf 或 StringRedisSerializer + JSON
    • 理由:良好的跨語言支持,嚴格的類型控制
  • 僅存儲簡單數(shù)據(jù)

    • 推薦:StringRedisSerializer
    • 理由:極簡實現(xiàn),極高性能,無需關注序列化問題
  • 混合數(shù)據(jù)類型

    • 推薦:使用多個RedisTemplate,針對不同數(shù)據(jù)類型采用不同序列化
    • 理由:針對特定數(shù)據(jù)類型優(yōu)化性能和兼容性
  • 臨時解決方案

    • 推薦:JdkSerializationRedisSerializer
    • 理由:快速實現(xiàn),無需額外配置,但不建議在生產(chǎn)環(huán)境長期使用
  • 大規(guī)模分布式緩存

    • 推薦:ProtoBuf 或 Kryo
    • 理由:極小的序列化體積和極高性能,降低網(wǎng)絡和存儲開銷

總結

選擇合適的Redis序列化策略對于系統(tǒng)性能和兼容性至關重要。

最佳實踐是針對不同類型的數(shù)據(jù)和不同的使用場景,以獲得最佳的性能和開發(fā)體驗。同時,應考慮版本控制、數(shù)據(jù)壓縮等高級特性,為系統(tǒng)的長期演進做好準備。

通過合理選擇和配置Redis序列化策略,可以顯著提升系統(tǒng)性能,降低資源消耗,提高開發(fā)效率,使系統(tǒng)更加健壯和可擴展。

以上就是SpringBoot整合Redis實現(xiàn)序列化的7種策略詳解的詳細內(nèi)容,更多關于SpringBoot Redis序列化的資料請關注腳本之家其它相關文章!

相關文章

  • SpringBoot實現(xiàn)攔截器、過濾器、監(jiān)聽器過程解析

    SpringBoot實現(xiàn)攔截器、過濾器、監(jiān)聽器過程解析

    這篇文章主要介紹了SpringBoot實現(xiàn)攔截器、過濾器、監(jiān)聽器過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • 深入分析JAVA 反射和泛型

    深入分析JAVA 反射和泛型

    這篇文章主要介紹了JAVA 反射和泛型的的相關資料,文中講解非常細致,代碼幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2020-06-06
  • SpringCloud微服務應用config配置中心詳解

    SpringCloud微服務應用config配置中心詳解

    這篇文章主要介紹了SpringCloud微服務應用-config配置中心,包括相關知識介紹、搭建、動態(tài)刷新、測試,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • SpringBoot實現(xiàn)文件下載的四種方式

    SpringBoot實現(xiàn)文件下載的四種方式

    本文主要介紹了SpringBoot實現(xiàn)文件下載的四種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-11-11
  • Netty分布式FastThreadLocal的set方法實現(xiàn)邏輯剖析

    Netty分布式FastThreadLocal的set方法實現(xiàn)邏輯剖析

    這篇文章主要為大家介紹了Netty分布式FastThreadLocal的set方法實現(xiàn)邏輯剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03
  • java使用poi生成excel的步驟

    java使用poi生成excel的步驟

    2010以上格式使用XSSFWorkBook對象, 2003格式使用HSSFWorkBook對象, 其他對象操作基本一樣,本文重點給大家介紹java使用poi生成excel的相關知識,感興趣的朋友一起看看吧
    2022-04-04
  • 你知道將Bean交給Spring容器管理有幾種方式(推薦)

    你知道將Bean交給Spring容器管理有幾種方式(推薦)

    Spring核心是?IOC?和?AOP?,我們在Spring項目中,我們需要將Bean交給Spring容器,也就是IOC管理,這樣你才可以使用注解來進行依賴注入,這篇文章主要介紹了你知道將Bean交給Spring容器管理有幾種方式,需要的朋友可以參考下
    2022-10-10
  • SpringBoot整合Sa-Token實現(xiàn)登錄認證的示例代碼

    SpringBoot整合Sa-Token實現(xiàn)登錄認證的示例代碼

    本文主要介紹了SpringBoot整合Sa-Token實現(xiàn)登錄認證的示例代碼,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 解讀JDK、JRE、JVM的區(qū)別與聯(lián)系

    解讀JDK、JRE、JVM的區(qū)別與聯(lián)系

    這篇文章主要介紹了解讀JDK、JRE、JVM的區(qū)別與聯(lián)系,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringCloud中的openFeign調(diào)用服務并傳參的過程

    SpringCloud中的openFeign調(diào)用服務并傳參的過程

    服務和服務之間通信,不僅僅是調(diào)用,往往在調(diào)用過程中還伴隨著參數(shù)傳遞,接下來重點來看看OpenFeign在調(diào)用服務時如何傳遞參數(shù),感興趣的朋友一起看看吧
    2023-11-11

最新評論