惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - thanks

07-紧固件MES系统 — 中小企业实施部署指南 06-紧固件MES系统 — 术语与名词解析 05-紧固件MES系统 — 推荐技术架构与智能制造方案 03-紧固件MES系统 — 模块业务详解 04-紧固件MES系统 — 重构建议与待开发分析 01-紧固件MES系统 — 系统总览与架构 02-紧固件MES系统 — 核心业务流程 VsCode+DeepSeek的AI编程助手初体验 [大数据][机器学习]之Model Card(模型卡片)介绍 Spark中的那些坑... 为啥就业这么难——聊聊我在培训机构的所见所闻 微软外服工作札记③——窗口函数的介绍 微软外服工作札记②——聊聊微软的知识管理服务平台和一些编程风格 【非技术】试占12月10日后会发生什么 聊聊我在微软外服大数据分析部门的工作经历及一些个人见解 SAAS云平台搭建札记: (四) AntD For React使用react-router-dom路由接收不同参数页面不刷新的问题 [工作札记]03: 微软Winform窗体中设计上的Bug,会导致程序编译失败,影响范围:到最新的.net4.7.2都有 [工作札记]02: .Net Winform控件TreeView最简递归绑定方法 SAAS云平台搭建札记: (三) AntDesign + .Net Core WebAPI权限控制、动态菜单的生成 [工作札记]01: CS系统中分页控件的制作 【非技术】试占新型肺炎的情况与发展趋势 给培训学校讲解ORM框架的课件 SAAS云平台搭建札记: (二) Linux Ubutu下.Net Core整套运行环境的搭建 SAAS云平台搭建札记: (一) 浅论SAAS多租户自助云服务平台的产品、服务和订单 开源三维地球GIS引擎Cesium常用功能的开发 Asp.net管理信息系统中数据统计功能的实现 - thanks
Bond——大数据时代的数据交换和存储格式
thanks · 2024-07-08 · via 博客园 - thanks

设想我们在一家很大的互联网公司做IT方面的规划、开发和维护,有以下这样的应用场景:

  • 公司里有若干个不同的开发团队,开发语言有Java、.net、Python、C++....十来种,还有很多外包团队对项目进行开发,大中小系统已经多的数不过来;并且各个团队、系统间都需要进行海量数据的交换(比如搜索引擎实时的数据,GPS物联网实时数据,电站的实时监控数据等),如何定义一种数据格式,使得各种平台和语言都能够兼容,交换的成本最低?
  • 如此多的结构化、非结构化数据都需要进行存储,有几百个哈杜集群、数十万台、百万台服务器,数据存储在Hbase、RocksDb或者其他自己开发的数据库结构中,对查询的实时性很高(内存表个位数毫秒、SSD十几毫秒等)。如何用一种较为统一的格式存放这些数据?

相信在大公司或者在大公司做过外包的童鞋,都接触过这样一种数据对象,那就是Bond格式,目前Bond由M$维护,官方网站:https://github.com/microsoft/bond/,上面提供了各种语言的示例、编译工具等。
一个基本的Bond文件如下所示:

namespace School

struct Student
{
    0: string Name;
    1: uint8 Age;
    2: bool IsBoy;
    3: optional vector<string> Interests;
}

这里定义了一个学校的命名空间,里面有个学生类,学生类里面有四个字段,依次是姓名、年龄、是否为男孩、兴趣爱好的列表(可选)。

很容易看出Bond结构实际是与平台和语言无关的,它是一个DSL,在不同的平台上,利用Bond编译工具gbc,可以把Bond文件编译成不同的类,然后就可以赋值、存储和传输了,编译好的Bond原生支持RPC调用。

Bond支持的数据类型有:

  • 基本类型:int8, int16, int32, int64, uint8, uint16, uint32, uint64, float, double, bool, string, blob等,需要注意java平台没有uint类型,会编译成带有符号的同类型,数据会丢失精度(正数变成负数);
  • 列表 vector、字典 map
  • 枚举 enum
  • 默认值
  • 可选字段 optional,必须字段 required
  • 可空字段 nullable
  • 支持类的继承
  • 支持字段的修饰 Attribute,这对前端验证和数据库存储比较有用,能定义字段长度、范围、列族等

这些类型能很好的满足数据交换和存储的需要;除此以外,Bond是一种非常高效的数据存储格式,它的二进制序列化最大程度去除了元数据的影响,极其紧凑,我们来看一个示例:

ListingItem是一个Bond类型,它的结构定义如下:

struct ListingItem
{
    1: required uint64 xxxxxxxxx; 
    2: required uint8 xxxxxxxxx; 
    3: optional uint16 score;
    4: optional vector<xxxx> xxxxxxxxxxx;
    5: optional map<xxxxxx, uint16> xxxxxxxxx; 
    6: optional xxxxxx xxxxxxxxxxx = Exxxxx;
    7: optional bool IsDeleted;
    8: optional vector<xxxxxxxx> xxxxxxxxList = nothing;
}

由于牵涉到生产环境的真实数据,所以一些字段和引用使用xxxxx来代替了,这个类的大小中等,有各种字段,还有对其它类的引用和集合等等。

我们用随机化的方式生成一百万个类,类里面的字段和引用都不一样,数值都是随机生成的,然后用Bond序列化和Java中带的Gson序列化方式进行序列化后的二进制长度比较,渣代码如下:

    @Test
    public void ListingItemTest() throws IOException {
        int cycleLength = 1000000;
        Random random = new Random();
        // Create 1000000 listing item
        List<ListingItem> items = new ArrayList<>();
        for(int i = 0; i < cycleLength; i ++){
            ListingItem item = new ListingItem();
            // ... 
            //赋值省略,利用random.nextLong() nextInt()等给字段赋值
            // ...
            items.add(item);
        }

        StopWatch stopWatch = new StopWatch();
        int length = 0;
        stopWatch.start();
        //Serialization Bond Object for 1000000 times
        for(int i = 0; i < cycleLength; i ++){
            byte[] bytes = BondSerializationUtils.serializeBondToBytes(items.get(i), ProtocolType.MARSHALED_PROTOCOL);
            length += bytes.length;
        }
        stopWatch.stop();
        System.out.println(String.format("Bond Serialization %d objects cost %d ms, avg length in bytes is %d", cycleLength, stopWatch.getTime(), length / cycleLength));

        //Serialization as Json Object
        length = 0;
        stopWatch.reset();
        stopWatch.start();
        for(int i = 0; i < cycleLength; i ++){
            String json = gson.toJson(items.get(i));
            length += json.length();
        }
        stopWatch.stop();
        System.out.println(String.format("Json Serialization %d objects cost %d ms, avg length in string is %d", cycleLength, stopWatch.getTime(), length / cycleLength));
    }

在我的破笔记本(10代i5低功耗u)运行结果如下:

Bond Serialization 1000000 objects cost 1392 ms, avg length in bytes is 60
Json Serialization 1000000 objects cost 8837 ms, avg length in string is 310

由于Java字符串getBytes()后和原长度一样,所以我们可以把字符串长度看作二进制数组长度。

多运行几遍代码,可以看到,Bond序列化的速度比Gson序列化的速度快4到5倍,序列化后的大小也只有json的1/5。(使用不同的序列化协议,比如COMPACT_PROTOCOL可以进一步压缩结果大小和序列化时间,速度能比Json序列化快10倍以上)

这是个了不起的成绩,如果我们生产环境中每天产生上百亿条数据,这些数据用于各种转换、分析与统计,使用Bond结构存储只有使用字符串存储空间的1/5,能够省下4/5以EB、PB计的存储成本;而且由于数据量的减少,传输和计算的成本也进一步压缩,每年在IT基础设施上的投入能节约上百亿上千亿美元,这些节省的成本最后都是利润。

最后,由于Java平台没有自带二进制序列化框架,我们用.net自带的序列化框架测试下二进制序列化和Json序列化,序列化的类如下:

    [Serializable]
    public class TAListings
    {
        public string LxxxxxxxxList { get; set; }
        public string Titles { get; set; }
        public string CxxxxxxxxxxxxxxList { get; set; }
        public string CxxxxxxxxxxxxxxxxList { get; set; }
    }

代码如下:

TAListings listings = new TAListings() { CxxxxxxxxxxxxxxxxList= "5033333309:-:73333333333334,34444444442:-:744444444442,54444444449:-:744444444444444448,544444443:-:744444444444444" };

var binSerilization = BinaryHelper.Serialize(listings);
var jsonSerilization = JsonHelper.Serialize(listings);

Console.WriteLine(string.Join(" ", binSerilization.Select(f => f.ToString("x2"))));
Console.WriteLine("Binary Serilization Length: " + binSerilization.Length);
Console.WriteLine();
Console.WriteLine(jsonSerilization);
Console.WriteLine("Json Serilization UTF8 Length: " + Encoding.UTF8.GetByteCount(jsonSerilization));
Console.ReadLine();

结果如截图所示:
image
可以看到,如果只是普通的类,在.net使用二进制序列化后,反而比json序列化大了不少,增加的长度在二到四倍左右不等,这很反常识,是因为.net二进制序列化需要存储更多的元数据吗?

大家对我的文章有什么问题和建议,都希望能够参与讨论,谢谢大家!