SpringBoot整合Redis實現(xiàn)序列化的7種策略詳解
在分布式系統(tǒng)中,Redis作為高性能的緩存和數(shù)據(jù)存儲解決方案被廣泛應(yīng)用。當(dāng)使用SpringBoot框架整合Redis時,序列化策略的選擇直接影響到系統(tǒng)的性能、兼容性和可維護性。
序列化是將Java對象轉(zhuǎn)換為可在網(wǎng)絡(luò)上傳輸或存儲在磁盤上的過程,反序列化則是將這些數(shù)據(jù)重新轉(zhuǎn)換為Java對象。
合適的序列化策略能夠帶來以下好處:
- 提高系統(tǒng)性能和存儲效率
- 增強跨語言和跨平臺互操作性
- 降低網(wǎng)絡(luò)傳輸和存儲開銷
- 提供更好的安全性和可維護性
本文將介紹SpringBoot中Redis的7種序列化策略
1. JdkSerializationRedisSerializer
1.1 原理介紹
JdkSerializationRedisSerializer是Spring Data Redis默認(rèn)的序列化策略,它使用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無縫集成
- 能處理復(fù)雜的對象圖和循環(huán)引用
缺點
- 序列化后的數(shù)據(jù)體積較大,占用存儲空間
- 序列化/反序列化性能較差,影響系統(tǒng)吞吐量
- 序列化結(jié)果是二進制,不可讀性
- 強耦合于Java平臺,不支持跨語言操作
- 對類的修改敏感,可能導(dǎo)致反序列化兼容性問題
適用場景
- 內(nèi)部系統(tǒng)臨時緩存,數(shù)據(jù)量不大且性能要求不高
- 簡單快速搭建原型系統(tǒng)
- 系統(tǒng)全部采用Java技術(shù)棧,無跨語言需求
- 對象結(jié)構(gòu)復(fù)雜且包含循環(huán)引用
2. StringRedisSerializer
2.1 原理介紹
StringRedisSerializer是最簡單的序列化器,它直接將String類型的數(shù)據(jù)按照指定的字符集(默認(rèn)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)點
- 結(jié)果可讀性好,便于調(diào)試和監(jiān)控
- 內(nèi)存占用少,序列化后體積小
- 與Redis命令行客戶端兼容,便于管理
- 支持跨語言操作
缺點
- 僅支持String類型,無法直接存儲復(fù)雜對象
- 存儲對象需要先轉(zhuǎn)為字符串(如JSON),增加額外步驟
適用場景
- Redis的key值序列化
- 存儲簡單的字符串?dāng)?shù)據(jù)
- 存儲已序列化為字符串的數(shù)據(jù)(如JSON、XML)
- 需要通過Redis命令行查看或修改數(shù)據(jù)
- 多語言系統(tǒng)協(xié)作場景
3. Jackson2JsonRedisSerializer
3.1 原理介紹
Jackson2JsonRedisSerializer使用Jackson庫將對象序列化為JSON格式的字符串。它能處理大多數(shù)常見的Java對象,并產(chǎn)生人類可讀的序列化結(jié)果,同時提供了較好的性能和壓縮率。該序列化器需要指定序列化的目標(biāo)類型。
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)點
- 序列化結(jié)果是JSON格式,具有很好的可讀性
- 性能較好,序列化后體積適中
- JSON格式支持跨語言和跨平臺操作
缺點
- 需要指定序列化的目標(biāo)類型,不夠靈活
- 無法直接處理泛型和多態(tài)對象
- 序列化/反序列化復(fù)雜對象可能需要額外配置
- 容易出現(xiàn)類型轉(zhuǎn)換問題
適用場景
- 已知且固定類型的對象緩存
- 需要跨語言讀取緩存數(shù)據(jù)
- 緩存數(shù)據(jù)需要人工查看和修改
- RESTful API系統(tǒng)使用Redis作為緩存層
4. GenericJackson2JsonRedisSerializer
4.1 原理介紹
GenericJackson2JsonRedisSerializer是Jackson2JsonRedisSerializer的增強版,它無需指定目標(biāo)類型,能夠處理任何類型的Java對象。它通過在JSON中嵌入類型信息來支持泛型和多態(tài),使反序列化能夠正確恢復(fù)對象類型。
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);
}
// 無需進行類型轉(zhuǎn)換
@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類型,無需指定目標(biāo)類
- 能正確處理泛型和多態(tài)對象
- 序列化結(jié)果是JSON格式,具有很好的可讀性
- 性能較好,與Jackson2JsonRedisSerializer相當(dāng)
缺點
- 序列化結(jié)果中包含類型信息,導(dǎo)致體積增大
- 反序列化需要類路徑中存在相應(yīng)的類
- 類重構(gòu)后可能導(dǎo)致反序列化失敗
- 包含類型信息的JSON不易于其他語言處理
適用場景:
- 存儲多種不同類型的Java對象
- 需要處理泛型集合和多態(tài)對象
- 類型不確定或頻繁變化的場景
- 純Java技術(shù)棧且序列化數(shù)據(jù)不需要跨語言處理
5. FastJsonRedisSerializer
5.1 原理介紹
FastJsonRedisSerializer基于阿里巴巴的FastJson庫,F(xiàn)astJson是一個性能優(yōu)越的JSON處理庫,專為Java平臺設(shè)計。它提供了極高的序列化和反序列化性能,在處理大量數(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)勢明顯
- 支持自動類型識別和泛型處理
缺點
- 存在安全漏洞風(fēng)險,需要注意版本選擇,建議使用fastjson2版本
- 對于復(fù)雜對象的處理可能不如Jackson穩(wěn)定
- 不是跨平臺標(biāo)準(zhǔn),主要在Java生態(tài)系統(tǒng)中使用
適用場景
- 對性能要求極高的系統(tǒng)
- 大數(shù)據(jù)量的緩存場景
- 純Java技術(shù)棧應(yīng)用
6. Kryo序列化
6.1 原理介紹
Kryo是一個快速高效的Java序列化框架,它產(chǎn)生的序列化結(jié)果非常緊湊,序列化和反序列化速度極快。
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); // 關(guān)閉注冊要求,自動注冊類
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倍
- 序列化結(jié)果體積非常小,內(nèi)存占用低
- 能夠處理復(fù)雜對象圖和循環(huán)引用
- 支持對象版本控制,有一定的向前兼容性
缺點
- 序列化結(jié)果為二進制,不可讀
- 使用復(fù)雜度較高,需要考慮線程安全
- 對大量類型需要注冊以獲得最佳性能
- 跨語言支持有限
- 類模型變更后可能面臨兼容性問題
適用場景
- 對性能和內(nèi)存占用有極高要求的場景
- 序列化大量復(fù)雜對象圖
- 需要高效處理循環(huán)引用的情況
- 純Java技術(shù)棧,無跨語言需求
7. Protocol Buffers (ProtoBuf)
7.1 原理介紹
Protocol Buffers(ProtoBuf)是由Google開發(fā)的一種語言無關(guān)、平臺無關(guān)、可擴展的結(jié)構(gòu)化數(shù)據(jù)序列化機制。它比XML更小、更快、更簡單,適用于通信協(xié)議、數(shù)據(jù)存儲等場景。
ProtoBuf使用預(yù)定義的消息格式,通過專用編譯器生成代碼,實現(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對象轉(zhuǎn)換為業(yè)務(wù)對象:
@Component
public class UserMapper {
// ProtoBuf對象轉(zhuǎn)換為業(yè)務(wù)對象
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());
// 轉(zhuǎn)換枚舉類型
switch (protoUser.getUserType()) {
case VIP:
user.setUserType(UserType.VIP);
break;
case ADMIN:
user.setUserType(UserType.ADMIN);
break;
default:
user.setUserType(UserType.NORMAL);
}
// 轉(zhuǎn)換列表
user.setRoles(new ArrayList<>(protoUser.getRolesList()));
// 轉(zhuǎn)換Map
user.setAttributes(new HashMap<>(protoUser.getAttributesMap()));
return user;
}
// 業(yè)務(wù)對象轉(zhuǎn)換為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());
// 轉(zhuǎn)換枚舉類型
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);
}
// 轉(zhuǎn)換列表
if (user.getRoles() != null) {
builder.addAllRoles(user.getRoles());
}
// 轉(zhuǎn)換Map
if (user.getAttributes() != null) {
builder.putAllAttributes(user.getAttributes());
}
return builder.build();
}
}
7.3 優(yōu)缺點分析
優(yōu)點
- 序列化/反序列化性能極高
- 序列化結(jié)果體積小,是XML的10倍壓縮比
- 跨語言,支持多種編程語言
- 向前兼容和向后兼容性良好
- 自帶字段類型校驗
- 代碼生成,減少編碼錯誤
缺點
- 需要預(yù)定義消息結(jié)構(gòu)(Proto文件)
- 實現(xiàn)復(fù)雜度高,需要額外的構(gòu)建步驟
- 對象模型變更需要重新生成代碼
- 動態(tài)類型支持有限
- 難以直接查看或調(diào)試緩存內(nèi)容
適用場景:
- 多語言系統(tǒng)協(xié)作場景
- 性能要求極高的實時系統(tǒng)
- 對帶寬要求苛刻的系統(tǒng)
- 需要嚴(yán)格的字段驗證
- 消息格式相對穩(wěn)定且可預(yù)定義的場景
- 大規(guī)模分布式系統(tǒng)
總結(jié)對比
| 序列化方式 | 序列化性能 | 體積大小 | 可讀性 | 跨語言 | 復(fù)雜度 | 類型信息 | 向前兼容性 |
|---|---|---|---|---|---|---|---|
| JDK | 低 | 大 | 差 | 否 | 低 | 完整 | 差 |
| String | 極高 | 小 | 優(yōu) | 是 | 極低 | 無 | 優(yōu) |
| Jackson2Json | 中 | 中 | 優(yōu) | 是 | 中 | 無 | 中 |
| GenericJackson2Json | 中 | 中偏大 | 中 | 否 | 中 | 完整 | 中 |
| FastJson | 高 | 中偏小 | 優(yōu) | 有限 | 中 | 可選 | 中 |
| Kryo | 極高 | 極小 | 差 | 否 | 高 | 有限 | 中 |
| ProtoBuf | 極高 | 極小 | 差 | 是 | 極高 | 完整 | 優(yōu) |
選型建議
根據(jù)不同的應(yīng)用場景,以下是序列化策略的選擇建議:
通用Web應(yīng)用
- 推薦:GenericJackson2JsonRedisSerializer
- 理由:通用性好,可讀性高,支持復(fù)雜對象,性能適中
高性能Java應(yīng)用
- 推薦:Kryo 或 FastJsonRedisSerializer
- 理由:極高的性能和低內(nèi)存占用,適合同構(gòu)Java系統(tǒng)
跨語言系統(tǒng)
- 推薦:ProtoBuf 或 StringRedisSerializer + JSON
- 理由:良好的跨語言支持,嚴(yán)格的類型控制
僅存儲簡單數(shù)據(jù)
- 推薦:StringRedisSerializer
- 理由:極簡實現(xiàn),極高性能,無需關(guān)注序列化問題
混合數(shù)據(jù)類型
- 推薦:使用多個RedisTemplate,針對不同數(shù)據(jù)類型采用不同序列化
- 理由:針對特定數(shù)據(jù)類型優(yōu)化性能和兼容性
臨時解決方案
- 推薦:JdkSerializationRedisSerializer
- 理由:快速實現(xiàn),無需額外配置,但不建議在生產(chǎn)環(huán)境長期使用
大規(guī)模分布式緩存
- 推薦:ProtoBuf 或 Kryo
- 理由:極小的序列化體積和極高性能,降低網(wǎng)絡(luò)和存儲開銷
總結(jié)
選擇合適的Redis序列化策略對于系統(tǒng)性能和兼容性至關(guān)重要。
最佳實踐是針對不同類型的數(shù)據(jù)和不同的使用場景,以獲得最佳的性能和開發(fā)體驗。同時,應(yīng)考慮版本控制、數(shù)據(jù)壓縮等高級特性,為系統(tǒng)的長期演進做好準(zhǔn)備。
通過合理選擇和配置Redis序列化策略,可以顯著提升系統(tǒng)性能,降低資源消耗,提高開發(fā)效率,使系統(tǒng)更加健壯和可擴展。
以上就是SpringBoot整合Redis實現(xiàn)序列化的7種策略詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Redis序列化的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
IntelliJ IDEA 的 Spring 項目如何查看 @Value 的配置和值(方法詳解)
這篇文章主要介紹了IntelliJ IDEA 的 Spring 項目如何查看 @Value 的配置和值,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10
WIN10系統(tǒng)中添加bat腳本重啟jar服務(wù)
在bat腳本中執(zhí)行java服務(wù),命令與cmd中類似,下面這篇文章主要給大家介紹了關(guān)于WIN10系統(tǒng)中添加bat腳本重啟jar服務(wù)的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
Java服務(wù)假死后續(xù)之內(nèi)存溢出的原因分析
這篇文章主要介紹了Java服務(wù)假死后續(xù)之內(nèi)存溢出,本文給大家分享原因排查和故障解決方法,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
基于序列化存取實現(xiàn)java對象深度克隆的方法詳解
本篇文章是對序列化存取實現(xiàn)java對象深度克隆的方法進行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Spring?Boot?DevTools?全局配置學(xué)習(xí)指南
這篇文章主要介紹了Spring?Boot?DevTools?全局配置,注意包括直接重啟項目與devtools重啟的區(qū)別,DevTools配置,DevTools全局配置及trigger-file控制重啟行為的相關(guān)知識,需要的朋友可以參考下2022-03-03
Mybatis如何通過出入Map參數(shù)作為條件進行查詢
這篇文章主要介紹了Mybatis如何通過出入Map參數(shù)作為條件進行查詢,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06

