计算机单机性能一直受到摩尔定律的约束,随着移动互联网的兴趣,单机性能不足的瓶颈越来越明显,制约着整个行业的发展 。不过我们虽然不能无止境的纵向扩容系统,但是我们可以分布式、横向的扩容系统 , 这听起来非常的美好 , 不过也带来了今天要说明的问题 , 分布式的节点越多,通信产生的成本就越大 。
- 网络传输带宽变得越来越紧缺,我们服务器的标配上了10Gbps的网卡
- HTTPx.x 时代TCP/IP协议通讯低效,我们即将用上QUIC HTTP 3.0
- 同机器走Socket协议栈太慢,我们用起了eBPF
- ....
之前笔者做一个项目时,就遇到了一个选型的问题,我们有数亿行数据需要缓存到Redis中,每行数据有数百个字段 , 如果用Json序列化存储的话它的内存消耗是数TB级别的(部署个集群再做个主从、多中心需要成倍的内存、太贵了,用不起) 。于是我们就在找有没有除了JSON其它更好的序列化方式?
看看都有哪些目前市面上序列化协议有很多比如XML、JSON、Thrift、Kryo等等,我们选取了在.NET平台上比较常用的序列化协议来做比较:
- JSON:JSON是一种轻量级的数据交换格式 。采用完全独立于编程语言的文本格式来存储和表示数据 。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言 。
- Protobuf:Protocol Buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法 , 它可用于(数据)通信协议、数据存储等,它类似XML , 但比它更小、更快、更简单 。
- MessagePack:是一种高效的二进制序列化格式 。它可以让你像JSON一样在多种语言之间交换数据 。但它更快、更小 。小的整数被编码成一个字节,典型的短字符串除了字符串本身之外,只需要一个额外的字节 。
- MemoryPack:是Yoshifumi Kawai大佬专为C#设计的一个高效的二进制序列化格式,它有着.NET平台很多新的特性,并且它是Code First开箱即用,非常简单;同时它还有着非常好的性能 。
准备工作我们准备了一个DemoClass类,里面简单的设置了几个不同类型的属性,然后依赖了一个子类数组 。暂时忽略上面的一些头标记 。
[MemoryPackable][MessagePackObject][ProtoContract]public partial class DemoClass{[Key(0)] [ProtoMember(1)] public int P1 { get; set; }[Key(1)] [ProtoMember(2)] public bool P2 { get; set; }[Key(2)] [ProtoMember(3)] public string P3 { get; set; } = null!;[Key(3)] [ProtoMember(4)] public double P4 { get; set; }[Key(4)] [ProtoMember(5)] public long P5 { get; set; }[Key(5)] [ProtoMember(6)] public DemoSubClass[] Subs { get; set; } = null!;}[MemoryPackable][MessagePackObject][ProtoContract]public partial class DemoSubClass{[Key(0)] [ProtoMember(1)] public int P1 { get; set; }[Key(1)] [ProtoMember(2)] public bool P2 { get; set; }[Key(2)] [ProtoMember(3)] public string P3 { get; set; } = null!;[Key(3)] [ProtoMember(4)] public double P4 { get; set; }[Key(4)] [ProtoMember(5)] public long P5 { get; set; }}
System.Text.Json选用它的原因很简单,这应该是.NET目前最快的JSON序列化框架之一了 , 它的使用非常简单,已经内置在.NET BCL中,只需要引用System.Text.Json
命名空间,访问它的静态方法即可完成序列化和反序列化 。using System.Text.Json;var obj = ....;// Serializevar json = JsonSerializer.Serialize(obj);// Deserializevar newObj = JsonSerializer.Deserialize<T>(json)
Google Protobuf.NET上最常用的一个Protobuf序列化框架,它其实是一个工具包,通过工具包+*.proto
文件可以生成GRPC Service或者对应实体的序列化代码 , 不过它使用起来有点麻烦 。使用它我们需要两个Nuget包 , 如下所示:
<!--Google.Protobuf 序列化和反序列化帮助类--><PackageReference Include="Google.Protobuf" Version="3.21.9" /><!--Grpc.Tools 用于生成protobuf的序列化反序列化类 和 GRPC服务--><PackageReference Include="Grpc.Tools" Version="2.50.0"><PrivateAssets>all</PrivateAssets><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets></PackageReference>
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 华为云 MRS 基于 Apache Hudi 极致查询优化的探索实践
- 基于 .NET 7 的 QUIC 实现 Echo 服务
- 《ASP.NET Core技术内幕与项目实战》精简集-目录
- 上 学习ASP.NET Core Blazor编程系列十——路由
- 重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]
- Sql Server性能排查和优化懒人攻略
- 在 .NET 7上使用 WASM 和 WASI
- 重新整理 .net core 实践篇 ———— linux上排查问题实用工具 [外篇]
- .NET 7 中 LINQ 的疯狂性能提升
- Vue3的新特性