本文目录导读:

- 内置序列化(Java原生)
- JSON序列化(Jackson)
- Protocol Buffers(Protobuf)
- Avro序列化
- Kryo高性能序列化
- 分布式场景配置(Spring Boot + Redis)
- 性能对比与选择建议
- 最佳实践建议
在Java分布式系统中,数据格式化器(通常是序列化器)的选择直接影响系统的性能、跨语言兼容性和可维护性,以下是几种常见的序列化方案及其在分布式环境下的实现方式:
内置序列化(Java原生)
import java.io.*;
public class JavaNativeSerializer {
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(obj);
}
return bos.toByteArray();
}
public static Object deserialize(byte[] data) throws IOException, ClassNotFoundException {
ByteArrayInputStream bis = new ByteArrayInputStream(data);
try (ObjectInputStream ois = new ObjectInputStream(bis)) {
return ois.readObject();
}
}
}
// 使用示例
@Data
@AllArgsConstructor
class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
}
缺点:性能差、跨语言困难、不安全。
JSON序列化(Jackson)
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class JsonSerializer {
private static final ObjectMapper MAPPER = new ObjectMapper()
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
public static byte[] serialize(Object obj) throws Exception {
return MAPPER.writeValueAsBytes(obj);
}
public static <T> T deserialize(byte[] data, Class<T> clazz) throws Exception {
return MAPPER.readValue(data, clazz);
}
}
Protocol Buffers(Protobuf)
// 1. 定义 .proto 文件
// user.proto
// syntax = "proto3";
// message User {
// string name = 1;
// int32 age = 2;
// }
// 2. 生成 Java 代码后使用
import com.google.protobuf.InvalidProtocolBufferException;
public class ProtobufSerializer {
public static byte[] serialize(UserProto.User user) {
return user.toByteArray();
}
public static UserProto.User deserialize(byte[] data) throws InvalidProtocolBufferException {
return UserProto.User.parseFrom(data);
}
}
Avro序列化
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.io.*;
import org.apache.avro.specific.SpecificDatumWriter;
public class AvroSerializer {
private static final Schema SCHEMA;
static {
String schemaStr = "{\"type\":\"record\"," +
"\"name\":\"User\"," +
"\"fields\":[{\"name\":\"name\",\"type\":\"string\"}," +
"{\"name\":\"age\",\"type\":\"int\"}]}";
SCHEMA = new Schema.Parser().parse(schemaStr);
}
public static byte[] serialize(GenericRecord record) throws Exception {
DatumWriter<GenericRecord> writer = new SpecificDatumWriter<>(SCHEMA);
ByteArrayOutputStream out = new ByteArrayOutputStream();
BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(out, null);
writer.write(record, encoder);
encoder.flush();
return out.toByteArray();
}
}
Kryo高性能序列化
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.JavaSerializer;
public class KryoSerializer {
private static final ThreadLocal<Kryo> KRYO_THREAD_LOCAL = ThreadLocal.withInitial(() -> {
Kryo kryo = new Kryo();
kryo.setDefaultSerializer(JavaSerializer.class);
kryo.register(User.class, 1);
return kryo;
});
public static byte[] serialize(Object obj) {
Kryo kryo = KRYO_THREAD_LOCAL.get();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Output output = new Output(baos);
kryo.writeObject(output, obj);
output.close();
return baos.toByteArray();
}
public static <T> T deserialize(byte[] data, Class<T> clazz) {
Kryo kryo = KRYO_THREAD_LOCAL.get();
Input input = new Input(data);
return kryo.readObject(input, clazz);
}
}
分布式场景配置(Spring Boot + Redis)
@Configuration
public class SerializationConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用 Jackson2JsonRedisSerializer
Jackson2JsonRedisSerializer<Object> serializer =
new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(
LazyObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
性能对比与选择建议
| 序列化方式 | 数据大小 | 序列化速度 | 跨语言 | 易用性 | 推荐场景 |
|---|---|---|---|---|---|
| Java原生 | 大 | 慢 | 差 | 好 | 仅限Java单机 |
| JSON | 中 | 中 | 好 | 好 | 通用场景 |
| Protobuf | 小 | 快 | 好 | 中 | 高性能RPC |
| Avro | 小 | 快 | 好 | 中 | 数据存储 |
| Kryo | 最小 | 最快 | 差 | 好 | Java集群内部通信 |
最佳实践建议
- 内部微服务通信:推荐使用 Protobuf 或 Avro(高性能、Schema演进)
- 对外API:使用 JSON(通用性好、易于调试)
- Java集群内部:可使用 Kryo(极致性能)
- 缓存存储:推荐 JSON 或 Protobuf
- 消息队列:推荐 Protobuf 或 Avro
选择合适的序列化方案需要权衡:
- 性能要求
- 跨语言需求
- Schema演进策略
- 调试便利性
- 社区支持度
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播