几种Java常用序列化框架的选型与对比

简介: 序列化与反序列化是我们日常数据持久化和网络传输中经常使用的技术,但是目前各种序列化框架让人眼花缭乱,不清楚什么场景到底采用哪种序列化框架。本文会将业界开源的序列化框架进行对比测试,分别从通用性、易用性、可扩展性、性能和数据类型与Java语法支持五方面给出对比测试。

 

image.png

 

作者 | 云烨
来源 | 阿里技术公众号

一 背景介绍

序列化与反序列化是我们日常数据持久化和网络传输中经常使用的技术,但是目前各种序列化框架让人眼花缭乱,不清楚什么场景到底采用哪种序列化框架。本文会将业界开源的序列化框架进行对比测试,分别从通用性、易用性、可扩展性、性能和数据类型与Java语法支持五方面给出对比测试。

  • 通用性:通用性是指序列化框架是否支持跨语言、跨平台。
  • 易用性:易用性是指序列化框架是否便于使用、调试,会影响开发效率。
  • 可扩展性:随着业务的发展,传输实体可能会发生变化,但是旧实体有可能还会被使用。这时候就需要考虑所选择的序列化框架是否具有良好的扩展性。
  • 性能:序列化性能主要包括时间开销和空间开销。序列化的数据通常用于持久化或网络传输,所以其大小是一个重要的指标。而编解码时间同样是影响序列化协议选择的重要指标,因为如今的系统都在追求高性能。
  • Java数据类型和语法支持:不同序列化框架所能够支持的数据类型以及语法结构是不同的。这里我们要对Java的数据类型和语法特性进行测试,来看看不同序列化框架对Java数据类型和语法结构的支持度。

下面分别对JDK Serializable、FST、Kryo、Protobuf、Thrift、Hession和Avro进行对比测试。

二 序列化框架

1 JDK Serializable

JDK Serializable是Java自带的序列化框架,我们只需要实现java.io.Serializablejava.io.Externalizable接口,就可以使用Java自带的序列化机制。实现序列化接口只是表示该类能够被序列化/反序列化,我们还需要借助I/O操作的ObjectInputStream和ObjectOutputStream对对象进行序列化和反序列化。

下面是使用JDK 序列化框架进行编解码的Demo:

 

image.png

 

通用性

由于是Java内置序列化框架,所以本身是不支持跨语言序列化与反序列化。

易用性

作为Java内置序列化框架,无序引用任何外部依赖即可完成序列化任务。但是JDK Serializable在使用上相比开源框架难用许多,可以看到上面的编解码使用非常生硬,需要借助ByteArrayOutputStream和ByteArrayInputStream才可以完整字节的转换。

可扩展性

JDK Serializable中通过serialVersionUID控制序列化类的版本,如果序列化与反序列化版本不一致,则会抛出java.io.InvalidClassException异常信息,提示序列化与反序列化SUID不一致。

java.io.InvalidClassException: com.yjz.serialization.java.UserInfo; local class incompatible: stream classdesc serialVersionUID = -5548195544707231683, local class serialVersionUID = -5194320341014913710

上面这种情况,是由于我们没有定义serialVersionUID,而是由JDK自动hash生成的,所以序列化与反序列化前后结果不一致。

但是我们可以通过自定义serialVersionUID方式来规避掉这种情况(序列化前后都是使用定义的serialVersionUID),这样JDK Serializable就可以支持字段扩展了。

private static final long serialVersionUID = 1L;

性能

JDK Serializable是Java自带的序列化框架,但是在性能上其实一点不像亲生的。下面测试用例是我们贯穿全文的一个测试实体。

public class MessageInfo implements Serializable {private String username;private String password;private int age;private HashMap<String,Object> params;...public static MessageInfo buildMessage() {MessageInfo messageInfo = new MessageInfo();messageInfo.setUsername("abcdefg");messageInfo.setPassword("123456789");messageInfo.setAge(27);Map<String,Object> map = new HashMap<>();for(int i = 0; i< 20; i++) {map.put(String.valueOf(i),"a");}return messageInfo;}
}

使用JDK序列化后字节大小为:432。光看这组数字也许不会感觉到什么,之后我们会拿这个数据和其它序列化框架进行对比。

我们对该测试用例进行1000万次序列化,然后计算时间总和:

1000万序列化耗时(ms)1000万反序列化耗时(ms)
3895296508

同样我们之后会同其它序列化框架进行对比。

数据类型和语法结构支持性

由于JDK Serializable是Java语法原生序列化框架,所以基本都能够支持Java数据类型和语法。

 

image.png

 

WeakHashMap没有实现Serializable接口。

 

image.png

 

注1:但我们要序列化下面代码:

Runnable runnable = () -> System.out.println("Hello");

直接序列化会得到以下异常:

com.yjz.serialization.SerializerFunctionTest$$Lambda$1/189568618

原因就是我们Runnable的Lambda并没有实现Serializable接口。我们可以做如下修改,即可支持Lambda表达式序列化。

Runnable runnable = (Runnable & Serializable) () -> System.out.println("Hello");

2 FST序列化框架

FST(fast-serialization)是完全兼容JDK序列化协议的Java序列化框架,它在序列化速度上能达到JDK的10倍,序列化结果只有JDK的1/3。目前FST的版本为2.56,在2.17版本之后提供了对Android的支持。

下面是使用FST序列化的Demo,FSTConfiguration是线程安全的,但是为了防止频繁调用时其成为性能瓶颈,一般会使用TreadLocal为每个线程分配一个FSTConfiguration。

private final ThreadLocal<FSTConfiguration> conf = ThreadLocal.withInitial(() -> {FSTConfiguration conf = FSTConfiguration.createDefaultConfiguration();return conf;});public byte[] encoder(Object object) {return conf.get().asByteArray(object);
}public <T> T decoder(byte[] bytes) {Object ob = conf.get().asObject(bytes);return (T)ob;
}

通用性

FST同样是针对Java而开发的序列化框架,所以也不存在跨语言特性。

易用性

在易用性上,FST可以说能够甩JDK Serializable几条街,语法极其简洁,FSTConfiguration封装了大部分方法。

可扩展性

FST通过@Version注解能够支持新增字段与旧的数据流兼容。对于新增的字段都需要通过@Version注解标识,没有版本注释意味着版本为0。

private String origiField;
@Version(1)
private String addField;

注意:

  • 删除字段将破坏向后兼容性,但是如果我们在原始字段情况下删除字段是能够向后兼容的(没有新增任何字段)。但是如果新增字段后,再删除字段的话就会破坏其兼容性。
  • Version注解功能不能应用于自己实现的readObject/writeObject情况。
  • 如果自己实现了Serializer,需要自己控制Version。

综合来看,FST在扩展性上面虽然支持,但是用起来还是比较繁琐的。

性能

使用FST序列化上面的测试用例,序列化后大小为:172,相比JDK序列化的432 ,将近减少了1/3。下面我们再看序列化与反序列化的时间开销。

 

image.png

 

我们可以优化一下FST,将循环引用判断关闭,并且对序列化类进行余注册。

private static final ThreadLocal<FSTConfiguration> conf = ThreadLocal.withInitial(() -> {FSTConfiguration conf = FSTConfiguration.createDefaultConfiguration();conf.registerClass(UserInfo.class);conf.setShareReferences(false);return conf;});

通过上面的优化配置,得到的时间开销如下:

 

image.png

 

可以看到序列化时间将近提升了2倍,但是通过优化后的序列化数据大小增长到了191 。

数据类型和语法结构支持性

FST是基于JDK序列化框架而进行开发的,所以在数据类型和语法上和Java支持性一致。

 

image.png

 

3 Kryo序列化框架

Kryo一个快速有效的Java二进制序列化框架,它依赖底层ASM库用于字节码生成,因此有比较好的运行速度。Kryo的目标就是提供一个序列化速度快、结果体积小、API简单易用的序列化框架。Kryo支持自动深/浅拷贝,它是直接通过对象->对象的深度拷贝,而不是对象->字节->对象的过程。

下面是使用Kryo进行序列化的Demo:

 

image.png

 

需要注意的是使用Output.writeXxx时候一定要用对应的Input.readxxx,比如Output.writeClassAndObject()要与Input.readClassAndObject()。

通用性

首先Kryo官网说自己是一款Java二进制序列化框架,其次在网上搜了一遍没有看到Kryo的跨语言使用,只是一些文章提及了跨语言使用非常复杂,但是没有找到其它语言的相关实现。

易用性

在使用方式上Kryo提供的API也是非常简洁易用,Input和Output封装了你几乎能够想到的所有流操作。Kryo提供了丰富的灵活配置,比如自定义序列化器、设置默认序列化器等等,这些配置使用起来还是比较费劲的。

可扩展性

Kryo默认序列化器FiledSerializer是不支持字段扩展的,如果想要使用扩展序列化器则需要配置其它默认序列化器。

比如:

private static final ThreadLocal<Kryo> kryoLocal = ThreadLocal.withInitial(() -> {Kryo kryo = new Kryo();kryo.setRegistrationRequired(false);kryo.setDefaultSerializer(TaggedFieldSerializer.class);return kryo;});

性能

使用Kryo测试上面的测试用例,Kryo序列化后的字节大小为172 ,和FST未经优化的大小一致。时间开销如下:

 

image.png

 

我们同样关闭循环引用配置和预注册序列化类,序列化后的字节大小为120,因为这时候类序列化的标识是使用的数字,而不是类全名。使用的是时间开销如下:

 

image.png

 

数据类型和语法结构支持性

Kryo对于序列化类的基本要求就是需要含有无参构造函数,因为反序列化过程中需要使用无参构造函数创建对象。

 

image.png

 

4 Protocol buffer

Protocol buffer是一种语言中立、平台无关、可扩展的序列化框架。Protocol buffer相较于前面几种序列化框架而言,它是需要预先定义Schema的。

下面是使用Protobuf的Demo:

(1)编写proto描述文件:

syntax = "proto3";option java_package = "com.yjz.serialization.protobuf3";message MessageInfo
{string username = 1;string password = 2;int32 age = 3;map<string,string> params = 4;
}

(2)生成Java代码:

protoc --java_out=./src/main/java message.proto

(3)生成的Java代码,已经自带了编解码方法:

 

image.png

 

通用性

protobuf设计之初的目标就是能够设计一款与语言无关的序列化框架,它目前支持了Java、Python、C++、Go、C#等,并且很多其它语言都提供了第三方包。所以在通用性上,protobuf是非常给力的。

易用性

protobuf需要使用IDL来定义Schema描述文件,定义完描述文件后,我们可以直接使用protoc来直接生成序列化与反序列化代码。所以,在使用上只需要简单编写描述文件,就可以使用protobuf了。

可扩展性

可扩展性同样是protobuf设计之初的目标之一,我们可以非常轻松的在.proto文件进行修改。

新增字段:对于新增字段,我们一定要保证新增字段要有对应的默认值,这样才能够与旧代码交互。相应的新协议生成的消息,可以被旧协议解析。

删除字段:删除字段需要注意的是,对应的字段、标签不能够在后续更新中使用。为了避免错误,我们可以通过reserved规避带哦。

 

image.png

 

protobuf在数据兼容性上也非常友好,int32、unit32、int64、unit64、bool是完全兼容的,所以我们可以根据需要修改其类型。

通过上面来看,protobuf在扩展性上做了很多,能够很友好的支持协议扩展。

性能

我们同样使用上面的实例来进行性能测试,使用protobuf序列化后的字节大小为 192,下面是对应的时间开销。

 

image.png

 

可以看出protobuf的反序列化性能要比FST、Kryo差一些。

数据类型和语法结构支持

Protobuf使用IDL定义Schema所以不支持定义Java方法,下面序列化变量的测试:

image.png

注:List、Set、Queue通过protobuf repeated定义测试的。只要实现Iterable接口的类都可以使用repeated列表。

5 Thrift序列化框架

Thrift是由Facebook实现的一种高效的、支持多种语言的远程服务调用框架,即RPC(Remote Procedure Call)。后来Facebook将Thrift开源到Apache。可以看到Thrift是一个RPC框架,但是由于Thrift提供了多语言之间的RPC服务,所以很多时候被用于序列化中。

使用Thrift实现序列化主要分为三步,创建thrift IDL文件、编译生成Java代码、使用TSerializer和TDeserializer进行序列化和反序列化。

(1)使用Thrift IDL定义thrift文件:

namespace java com.yjz.serialization.thriftstruct MessageInfo{1: string username;2: string password;3: i32 age;4: map<string,string> params;
}

(2)使用thrift编译器生成Java代码:

thrift --gen java message.thrift

(3)使用TSerializer和TDeserializer进行编解码:

  public static byte[] encoder(MessageInfo messageInfo) throws Exception{TSerializer serializer = new TSerializer();return serializer.serialize(messageInfo);}public static MessageInfo decoder(byte[] bytes) throws Exception{TDeserializer deserializer = new TDeserializer();MessageInfo messageInfo = new MessageInfo();deserializer.deserialize(messageInfo,bytes);return messageInfo;}

通用性

Thrift和protobuf类似,都需要使用IDL定义描述文件,这是目前实现跨语言序列化/RPC的一种有效方式。Thrift目前支持 C++、Java、Python、PHP、Ruby、 Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk、OCaml、Delphi等语言,所以可以看到Thrift具有很强的通用性。

易用性

Thrift在易用性上和protobuf类似,都需要经过三步:使用IDL编写thrift文件、编译生成Java代码和调用序列化与反序列化方法。protobuf在生成类中已经内置了序列化与反序列化方法,而Thrift需要单独调用内置序列化器来进行编解码。

可扩展性

Thrift支持字段扩展,在扩展字段过程中需要注意以下问题:

  • 修改字段名称:修改字段名称不影响序列化与反序列化,反序列化数据赋值到更新过的字段上。因为编解码过程利用的是编号对应。
  • 修改字段类型:修改字段类型,如果修改的字段为optional类型字段,则返回数据为null或0(数据类型默认值)。如果修改是required类型字段,则会直接抛出异常,提示字段没有找到。
  • 新增字段:如果新增字段是required类型,则需要为其设置默认值,负责在反序列化过程抛出异常。如果为optional类型字段,反序列化过程不会存在该字段(因为optional字段没有赋值的情况,不会参与序列化与反序列化)。如果为缺省类型,则反序列化值为null或0(和数据类型有关)。
  • 删除字段:无论required类型字段还是optional类型字段,都可以删除,不会影响反序列化。
  • 删除后的字段整数标签不要复用,负责会影响反序列化。

性能

上面的测试用例,使用Thrift序列化后的字节大小为:257,下面是对应的序列化时间与反序列化时间开销:

 

image.png

 

Thrift在序列化和反序列化的时间开销总和上和protobuf差不多,protobuf在序列化时间上更占优势,而Thrift在反序列化上有自己的优势。

数据类型和语法结构支持

数据类型支持:由于Thrift使用IDL来定义序列化类,所以能够支持的数据类型就是Thrift数据类型。Thrift所能够支持的Java数据类型:

  1. 8中基础数据类型,没有short、char,只能使用double和String代替。
  2. 集合类型,支持List、Set、Map,不支持Queue。
  3. 自定义类类型(struct类型)。
  4. 枚举类型。
  5. 字节数组。

Thrift同样不支持定义Java方法。

6 Hessian序列化框架

Hessian是caucho公司开发的轻量级RPC(Remote Procedure Call)框架,它使用HTTP协议传输,使用Hessian二进制序列化。

Hessian由于其支持跨语言、高效的二进制序列化协议,被经常用于序列化框架使用。Hessian序列化协议分为Hessian1.0和Hessian2.0,Hessian2.0协议对序列化过程进行了优化(优化内容待看),在性能上相较Hessian1.0有明显提升。

使用Hessian序列化非常简单,只需要通过HessianInput和HessianOutput即可完成对象的序列化,下面是Hessian序列化的Demo:

public static <T> byte[] encoder2(T obj) throws Exception{ByteArrayOutputStream bos = new ByteArrayOutputStream();Hessian2Output hessian2Output = new Hessian2Output(bos);hessian2Output.writeObject(obj);return bos.toByteArray();}public static <T> T decoder2(byte[] bytes) throws Exception {ByteArrayInputStream bis = new ByteArrayInputStream(bytes);Hessian2Input hessian2Input = new Hessian2Input(bis);Object obj = hessian2Input.readObject();return (T) obj;}

通用性

Hessian与Protobuf、Thrift一样,支持跨语言RPC通信。Hessian相比其它跨语言PRC框架的一个主要优势在于,它不是采用IDL来定义数据和服务,而是通过自描述来完成服务的定义。目前Hessian已经实现了语言包括:Java、Flash/Flex、Python、C++、.Net/C#、D、Erlang、PHP、Ruby、Object-C。

易用性

相较于Protobuf和Thrift,由于Hessian不需要通过IDL来定义数据和服务,对于序列化的数据只需要实现Serializable接口即可,所以使用上相比Protobuf和Thrift更加容易。

可扩展性

Hession序列化类虽然需要实现Serializable接口,但是它并不受serialVersionUID影响,能够轻松支持字段扩展。

  1. 修改字段名称:反序列化后新字段名称为null或0(受类型影响)。
  2. 新增字段:反序列化后新增字段为null或0(受类型影响)。
  3. 删除字段:能够正常反序列化。
  4. 修改字段类型:如果字段类型兼容能够正常反序列化,如果不兼容则直接抛出异常。

性能

使用Hessian1.0协议序列化上面的测试用例,序列化结果大小为277。使用Hessian2.0序列化协议,序列化结果大小为178。

序列化化与反序列化的时间开销如下:

 

image.png

 

可以看到Hessian1.0的无论在序列化后体积大小,还是在序列化、反序列化时间上都比Hessian2.0相差很远。

数据类型和语法结构支持

由于Hession使用Java自描述序列化类,所以Java原生数据类型、集合类、自定义类、枚举等基本都能够支持(SynchronousQueue不支持),Java语法结构也能够很好的支持。

7 Avro序列化框架

Avro是一个数据序列化框架。它是Apache Hadoop下的一个子项目,由Doug Cutting主导Hadoop过程中开发的数据序列化框架。Avro在设计之初就用于支持数据密集型应用,很适合远程或本地大规模数据交换和存储。

使用Avro序列化分为三步:

(1)定义avsc文件:

{"namespace": "com.yjz.serialization.avro","type": "record","name": "MessageInfo","fields": [{"name": "username","type": "string"},{"name": "password","type": "string"},{"name": "age","type": "int"},{"name": "params","type": {"type": "map","values": "string"}}]
}

(2)使用avro-tools.jar编译生成Java代码(或maven编译生成):

java -jar avro-tools-1.8.2.jar compile schema src/main/resources/avro/Message.avsc ./src/main/java

(3)借助BinaryEncoder和BinaryDecoder进行编解码:

public static  byte[] encoder(MessageInfo obj) throws Exception{DatumWriter<MessageInfo> datumWriter = new SpecificDatumWriter<>(MessageInfo.class);ByteArrayOutputStream outputStream = new ByteArrayOutputStream();BinaryEncoder binaryEncoder = EncoderFactory.get().directBinaryEncoder(outputStream,null);datumWriter.write(obj,binaryEncoder);return outputStream.toByteArray();}public static MessageInfo decoder(byte[] bytes) throws Exception{DatumReader<MessageInfo> datumReader = new SpecificDatumReader<>(MessageInfo.class);BinaryDecoder binaryDecoder = DecoderFactory.get().directBinaryDecoder(new ByteArrayInputStream(bytes),null);return datumReader.read(new MessageInfo(),binaryDecoder);}

通用性

Avro通过Schema定义数据结构,目前支持Java、C、C++、C#、Python、PHP和Ruby语言,所以在这些语言之间Avro具有很好的通用性。

易用性

Avro对于动态语言无需生成代码,但对于Java这类静态语言,还是需要使用avro-tools.jar来编译生成Java代码。在Schema编写上,个人感觉相比Thrift、Protobuf更加复杂。

可扩展性

  1. 给所有field定义default值。如果某field没有default值,以后将不能删除该field。
  2. 如果要新增field,必须定义default值。
  3. 不能修改field type。
  4. 不能修改field name,不过可以通过增加alias解决。

性能

使用Avro生成代码序列化之后的结果为:111。下面是使用Avro序列化的时间开销:

 

image.png

 

数据类型和语法结构支持

Avro需要使用Avro所支持的数据类型来编写Schema信息,所以能够支持的Java数据类型即为Avro所支持的数据类型。Avro支持数据类型有:基础类型(null、boolean、int、long、float、double、bytes、string),复杂数据类型(Record、Enum、Array、Map、Union、Fixed)。

Avro自动生成代码,或者直接使用Schema,不能支持在序列化类中定义java方法。

三 总结

1 通用性

下面是从通用性上对比各个序列化框架,可以看出Protobuf在通用上是最佳的,能够支持多种主流变成语言。

 

image.png

 

2 易用性

下面是从API使用的易用性上面来对比各个序列化框架,可以说除了JDK Serializer外的序列化框架都提供了不错API使用方式。

 

image.png

 

3 可扩展性

下面是各个序列化框架的可扩展性对比,可以看到Protobuf的可扩展性是最方便、自然的。其它序列化框架都需要一些配置、注解等操作。

 

image.png

 

4 性能

序列化大小对比

对比各个序列化框架序列化后的数据大小如下,可以看出kryo preregister(预先注册序列化类)和Avro序列化结果都很不错。所以,如果在序列化大小上有需求,可以选择Kryo或Avro。

 

image.png

 

序列化时间开销对比

下面是序列化与反序列化的时间开销,kryo preregister和fst preregister都能提供优异的性能,其中fst pre序列化时间就最佳,而kryo pre在序列化和反序列化时间开销上基本一致。所以,如果序列化时间是主要的考虑指标,可以选择Kryo或FST,都能提供不错的性能体验。

 

image.png

 

5 数据类型和语法结构支持

各序列化框架对Java数据类型支持的对比:

 

image.png

 

注:集合类型测试基本覆盖了所有对应的实现类。

  1. List测试内容:ArrayList、LinkedList、Stack、CopyOnWriteArrayList、Vector。
  2. Set测试内容:HashSet、LinkedHashSet、TreeSet、CopyOnWriteArraySet。
  3. Map测试内容:HashMap、LinkedHashMap、TreeMap、WeakHashMap、ConcurrentHashMap、Hashtable。
  4. Queue测试内容:PriorityQueue、ArrayBlockingQueue、LinkedBlockingQueue、ConcurrentLinkedQueue、SynchronousQueue、ArrayDeque、LinkedBlockingDeque和ConcurrentLinkedDeque。

下面根据测试总结了以上序列化框架所能支持的数据类型、语法。

 

image.png

 

  • 注1:static内部类需要实现序列化接口。
  • 注2:外部类需要实现序列化接口。
  • 注3:需要在Lambda表达式前添加(IXxx & Serializable)。

由于Protobuf、Thrift是IDL定义类文件,然后使用各自的编译器生成Java代码。IDL没有提供定义staic内部类、非static内部类等语法,所以这些功能无法测试。

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/513644.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

12v小型电机型号大全_电动机型号参数大全,再也不怕看不懂电机型号了

电动机型号是便于使用、设计、制造等部门进行业务联系和简化技术文件中产品名称、规格、型式等叙述而引用的一种代号。下面为大家介绍电动机型号含义等信息。1电动机型号组成及含义由电机类型代号、电机特点代号、设计序号和励磁方式代号等四个小节顺序组成。1、类型代号是表征…

基于DataWorks搭建新零售数据中台

文章作者&#xff1a;许日&#xff08;欢伯&#xff09;&#xff0c;在2016年盒马早期的时候&#xff0c;转到盒马事业部作为在线数据平台的研发负责人&#xff0c;现任阿里云计算平台DataWorks建模引擎团队负责人。 文章简介&#xff1a;本篇文章向大家分享新零售企业如何基于…

身份云平台 Authing 完成 2300 万美元 A 轮融资

10 月 24 日&#xff0c;身份云平台 Authing 宣布完成 2300 万美元 A 轮融资。本轮融资由老虎环球基金领投&#xff0c;鼎晖VGC&#xff08;创新与成长基金&#xff09;、声网 Agora、老股东 GGV纪源资本和奇绩创坛跟投&#xff0c;跃为资本担任独家财务顾问。Authing 表示&…

大数据计算存储资源池_管家实践:轻松玩转大数据计算服务

以下是直播内容精华整理&#xff0c;主要包括以下四个方面&#xff1a;1.背景速览&#xff1b;2.功能介绍&#xff1b;3.案例讲解&#xff1b;4.新功能预告。一、背景速览MaxCompute(原ODPS)是一项大数据计算服务&#xff0c;它能提供快速、完全托管的PB级数据仓库解决方案&…

客如云数据中台建设

简介&#xff1a; 本次分享介绍客如云如何利用阿里云大数据产品来建设数据中台。 客如云是2012年成立的一家公司&#xff0c;覆盖餐饮、零售、美业&#xff0c;还有其他的业态以及服务的一家综合性的SaaS公司。到2020年为止&#xff0c;客如云已经服务了60万商家&#xff0c;帮…

微博机器学习平台云上最佳实践

简介&#xff1a; 本文讲述了微博机器学习平台和深度学习平台的业务功能和云上实践&#xff0c;剖析了阿里云大数据在微博这两大学习平台的架构建设上所起到的作用。 作者&#xff1a;新浪微博数据计算平台系统架构师 曹富强 本文讲述了微博机器学习平台和深度学习平台的业务功…

搞懂异地多活,看这篇就够了

来源&#xff1a;水滴与银弹作者&#xff1a;Kaito阅读本文大约需要 20 分钟。你好&#xff0c;我是 Kaito。在软件开发领域&#xff0c;「异地多活」是分布式系统架构设计的一座高峰&#xff0c;很多人经常听过它&#xff0c;但很少人理解其中的原理。异地多活到底是什么&…

搭建一个微服务商城到底可以有多快?

简介&#xff1a; 极速部署一个微服务电商商城&#xff0c;体验 Serverless 带给您的应用全托管体验。 作者&#xff1a;云原生技术运营 - 望宸 技术实践的门槛不仅在于应用上线后各类问题的排查难度&#xff0c;也在于搭建一个 Demo 应用时的复杂度。 今天我们尝试 3 种方法来…

分享2种规划思维和4个规划方法

简介&#xff1a; 为结果买单&#xff0c;为过程鼓掌。 作者&#xff1a;不拔 每年各个部门都要进行规划&#xff0c;规划能让目标更聚焦&#xff0c;让我们清晰地知道今后我们要做什么、如何去做。并非每个人都会参与规划中去&#xff0c;但需要掌握规划的方法&#xff0c;否…

apache 统计404日志_Apache监控与调优(四)Apachetop监控

除了使用status监控外&#xff0c;还可以使用第三方软件来监控。现在使用的最多的第三方监控软件是apachetop。虽然我们使用status也可以监控到很多信息&#xff0c;但是对于一些统计信息来说&#xff0c;例如统计哪些URL的访问量最大&#xff0c;不同状态码下分别有多少个HTTP…

揭秘 | 2021年移动云API大赛决赛大奖花落谁家?

10月21日&#xff0c;2021年移动云API应用创新开发大赛决赛暨移动云开发者论坛&#xff0c;在苏州圆满举办。现场&#xff0c;移动云开发者社区重磅发布首批MVP名单&#xff0c;同时公布2021年API创新开发大赛决赛获奖名单。中国移动、英特尔、CSDN、PingCAP、各参赛团队等技术…

冷热分离之OTS表格存储实战

简介&#xff1a; 为什么要冷热分离由于2020疫情的原因&#xff0c;在线教育行业提前被大家所重视&#xff0c;钉钉教育已经服务超过21万所学校、700万教师和1.4亿学生用户&#xff0c;每天大量的教育数据产生。整体数据量&#xff1a;随着时间的积累&#xff0c;数据量越来直大…

世界地图可以无限放大_不敢相信!世界地图,你竟然骗了我这么多年...

本文转载自微信公众号&#xff1a;中国国家地理(ID:dili360)原文首发于2018年10月13日&#xff0c;标题为《世界地图&#xff0c;我竟然被你骗了这么多年&#xff01;》不代表FM93交通之声观点。都说眼见为实&#xff0c;其实眼见到的也不一定为实相信你们很多人都以为世界就像…

WebAssembly + Dapr = 下一代云原生运行时?

简介&#xff1a; 云计算已经成为了支撑数字经济发展的关键基础设施。云计算基础设施也在持续进化&#xff0c;从 IaaS&#xff0c;到容器即服务&#xff08;CaaS&#xff09;&#xff0c;再到 Serverless 容器和函数 PaaS (fPaaS 或者 FaaS)&#xff0c;新的计算形态相继出现。…

Service Mesh 开源实现之 Istio 架构概览

来源&#xff1a;无敌码农作者&#xff1a;无敌码农今天的文章将从更宏观的概念和架构入手&#xff0c;来全面介绍Istio这一最著名的服务网格开源解决方案&#xff0c;以求从整体上将Istio实现服务网格的核心原理阐述清楚&#xff01;Istio中的关键概念要学习Istio需要先明确以…

mysql外键约束分数_MySQL提高(外键约束)

外键约束1.条件语句的写法在sql中可以通过where 条件语句 来对操作对象进行筛选 -筛选a.比较运算符&#xff1a;&#xff0c;<>,,<,>注意&#xff1a;判断一个字段的值是否为空不用使用和<>&#xff0c;而是使用is null和is not nullselect number from t_co…

Java Map中那些巧妙的设计

简介&#xff1a; 他山之石可以攻玉&#xff0c;这些巧妙的设计思想非常有借鉴价值&#xff0c;可谓是最佳实践。然而&#xff0c;大多数有关Java Map原理的科普类文章都是专注于“点”&#xff0c;并没有连成“线”&#xff0c;甚至形成“网状结构”。因此&#xff0c;本文基于…

java json转xml_关于JSON与XML的区别比较

现在互联网上&#xff0c;最流行的两大传输数据的标准就是json和XML了&#xff0c;关于谁是最好的&#xff0c;一直以来都是人们争论的话题&#xff0c;其实各有各的缺点和优点&#xff1b;1.定义介绍(1).XML定义扩展标记语言 (Extensible Markup Language, XML) &#xff0c;用…

揭秘!阿里实时数仓分布式事务Scale Out设计

简介&#xff1a; Hybrid Transaction Analytical Processing(HTAP) 是著名信息技术咨询与分析公司Gartner在2014年提出的一个新的数据库系统定义&#xff0c;特指一类兼具OLTP能力&#xff08;事务能力&#xff09;和OLAP能力&#xff08;分析能力&#xff09;的数据库系统。 …

mysql对本地文件的读取_Mysql 任意读取客户端文件

load data infile "/etc/passwd" into table test FIELDS TERMINATED BY \n;实现&#xff1a;Mysql Server会读取服务端的/etc/passwd&#xff0c;然后将其数据按照\n分割插入表中&#xff0c;但现在这个语句同样要求你有FILE权限&#xff0c;以及非local加载的语句也…