更新時間:2021-09-22 11:22:38 來源:動力節(jié)點 瀏覽1531次
在Java開發(fā)工具當(dāng)中,Java序列化工具是比較常用的,而且種類也有不少,下面小編就來做個對比:
Binary Formats & language-specific Ones
Javabuiltin (Java native), javamanual (根據(jù)成員變量類型手動編寫), fstserliazation , kryo
二進制格式-通用語言-非特定 Ones
protobuf (Google) , Thrift (Facebook) , Avrogeneric, Hessian
JSON 格式
Jackson、Gson、Fastjson
Json-like:
CKS (Textual json-like format), BSON (json-like format with extended datatypes), Jacksonbson, MongoDB
基于 xml 的格式
Xmlxstream
Java序列化工具大致可以分為以上幾類,簡單概括分為二進制二進制和文本格式(JSON、XML)兩大類。
在速度的比較上,一般有以下規(guī)律:
Binary > textual
Language-specific > Language-unspecific
在 textual 中,XML 冗余度低于 JSON,這使得它在文本序列化上更加 bson 和更加復(fù)雜JSON,框架選擇更豐富、更優(yōu)秀。下面重點介紹下Kryo、Fast-serialiation、Fastjson、Protocol-buffer
互聯(lián)網(wǎng)公司使用Protobuf、Thrift、Avro等成熟的序列化解決方案來構(gòu)建RPC框架是一個經(jīng)過驗證的解決方案。
(1)Java Native 序列化工具
Java本身提供的序列化工具基本上可以在大部分場景下對任務(wù)進行序列化,本文的序列化機制是非常詳細的講解(7820018),值得一讀。Java自帶的序列化工具在序列化過程中不僅需要記錄對象的完整類名,還需要記錄類的定義,包括所有其他引用的類,尤其是在非常大的開銷下序列化單個對象時. 因為Java的序列化機制記錄了所有的元數(shù)據(jù),修改類的包名時反序列化是錯誤的。Java自序列化工具的性能問題總結(jié)如下:
單個對象的序列化是與所有成員變量(instsnce 變量)一起遞歸序列化,這是一種默認(rèn)機制,很容易導(dǎo)致不必要的序列化開銷。
序列化和反序列化的過程需要使用這種機制,使用反射機制遞歸合并所有成員變量的信息,如果沒有定義自己的serialversionuid,那么對象和其他變量必須自己產(chǎn)生一個。上述過程成本很高。
使用默認(rèn)的序列化機制,記錄所有序列化類定義的完整信息,包括所有包名、父類信息和成員變量
(2)優(yōu)化的Java序列化工具
Kryo
Kryo基于Java原生序列化機制的一些問題,做了很多優(yōu)化,提供了很多序列化器,甚至封裝了不安全序列化的類型,以及更多關(guān)于不安全序列化方法的類型,請注意這里, jdk1.7后默認(rèn)關(guān)閉Unsafe Class(Sun.misc.Unsafe)包。更多 Kryo 參考 Kryo 維基介紹。
Fast-serialization
fst-serialozation是一個比較新的序列化工具,雖然從2-1的kryo的速度評價還有一些差距,但是根據(jù)我在現(xiàn)場的生產(chǎn)環(huán)境測試,kryo的效果幾乎一致, 可以即時反序列化內(nèi)容和渲染
(3)JSON
好的 JSON 解析工具還是比較好的,有些 JSON 解析工具甚至比一些二進制序列化方法還要快。
(4)協(xié)議緩沖區(qū)
Protocol buffers 是一種序列化結(jié)構(gòu)化數(shù)據(jù)的技術(shù),支持 C++、Java、Python 等多種語言,可用于持久化數(shù)據(jù)或序列化要通過網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)。與其他一些 XML 技術(shù)相比,這種技術(shù)的一個明顯特點是它更節(jié)省空間(存儲在二進制流中)、速度更快、更靈活。
另外,PROTOBUF 支持的數(shù)據(jù)類型比較少,不支持常量類型。由于其設(shè)計理念純粹是表示層協(xié)議(Presentation layer),目前還沒有專門支持PROTOBUF的RPC框架。
(5)節(jié)儉
Thrift 是 Facebook 開源的高性能、輕量級 RPC 服務(wù)框架,旨在滿足當(dāng)今大數(shù)據(jù)量、分布式、跨語言、跨平臺數(shù)據(jù)通信的需求。然而,Thrift 不僅僅是一個序列化協(xié)議,而是一個 RPC 框架。與 JSON 和 XML 相比,thrift 在空間成本和解析性能上有很大的提升,對于性能要求很高的分布式系統(tǒng)來說是一個很好的 RPC 解決方案,但是因為 thrift 框架內(nèi)嵌了 thrift 序列化,所以 thrift 框架本身并沒有透露序列化和反序列化接口,這使得它很難與其他傳輸層協(xié)議(例如 HTTP)一起使用。
(6)阿夫羅
Avro解析性能高,序列化后的數(shù)據(jù)非常簡潔,更適合高性能的序列化服務(wù)。
Avro 提供了兩種序列化格式:JSON 格式或二進制格式。二進制格式在空間開銷和解析性能上可以與protobuf相媲美,JSON 格式有助于測試階段的調(diào)試。Avro 支持非常豐富的數(shù)據(jù)類型,包括 C++ 語言中的聯(lián)合類型。AVRO支持JSON格式的IDL和類似于thrift和protobuf的IDL(實驗階段),可以相互轉(zhuǎn)換。模式可以在傳輸數(shù)據(jù)的同時發(fā)送,加上 JSON 的自描述屬性,這使得 Avro 非常適合動態(tài)類型語言。Avro通常在文件持久化時和schema一起存儲,因此Avro序列化文件本身具有自描述屬性,因此非常適合hive、pig和MapReduce的數(shù)據(jù)格式持久化。對于不同版本的schema,在進行RPC調(diào)用時,服務(wù)端和客戶端可以在握手階段相互確認(rèn)schema,
Kryoregister、FST、Kryo、Gson、Fastjson、JDK
(1)JDK
public static byte[] serialize(Object obj) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj); byte[] bs = baos.toByteArray(); baos.close(); oos.close(); return bs; } catch (IOException e) { throw new RuntimeException(e); }}public static Object deserialize(byte[] bits) { try { ByteArrayInputStream bais = new ByteArrayInputStream(bits); ObjectInputStream ois = new ObjectInputStream(bais); Object obj = ois.readObject(); bais.close(); ois.close(); return obj; } catch (Exception e) { throw new RuntimeException(e); }}
(2)Fastjson
JSON 庫中涉及的最基本功能之一是序列化和反序列化。Fastjson 支持 Java bean 的直接序列化。使用 Com.alibaba.fastjson.JSON 類進行序列化和反序列化。
public static String serialize(Object obj){ String json = JSON.toJSONString(obj); return json;}public static Object deserialize(String json, Class<?> clazz){ Object obj = JSON.parseObject(json, clazz); return obj;}
(3)第一時間
FST Fast-serialization是一個重新實現(xiàn)的Java快速對象序列化開發(fā)包。序列化速度更快(2-10倍),體積更小,兼容JDK原生序列化。
Java Fast Serialization 庫FST 2.0 版本已經(jīng)發(fā)布,包名更改為不平滑升級。另外,出于穩(wěn)定性考慮,官方建議使用最新的1.58版本。
static FSTConfiguration configuration = FSTConfiguration .createDefaultConfiguration();public static byte[] serialize(Object obj){ return configuration.asByteArray((Serializable)obj);}public static Object deserialize(byte[] sec){ return configuration.asObject(sec);}
(4)Gson
這以 JSON 格式使用,并使用 Google Gson 進行轉(zhuǎn)義。
static Gson gson = new Gson();public static String serialize(Object obj){ String json = gson.toJson(obj); return json;}public static Object deserialize(String json, Class<?> clazz){ Object obj = gson.fromJson(json, clazz); return obj;}
對于原本采用Java Native序列化方案的系統(tǒng),Kryo Fst-serializer是Java Native序列化方案的一個很好的替代方案,不僅體現(xiàn)了重新編程的簡單性,而且在速度和性能上也有很大的提升,尤其是Fst -serializer,只是替換了Output/inputstream,升級的性能也很可觀,工具剛出來,穩(wěn)定性需要更多測試。
如果程序本身是JSON格式的序列化,可以考慮引入一個優(yōu)秀的JSON解析庫,General Service端Jackson就是一個流行的解析庫。
Protobuffer 更多是消息交換格式的 XML 替代語言,盡可能快,但是編程需要定義消息格式,關(guān)于成員變量,業(yè)務(wù)復(fù)雜 javabean 成本比較復(fù)雜,對于穩(wěn)定的現(xiàn)有系統(tǒng),整體成本更高。
想了解更多Java技術(shù),不妨關(guān)注動力節(jié)點Java在線學(xué)習(xí),教程針對沒有任何Java基礎(chǔ)的讀者學(xué)習(xí),讓你從入門到精通,主要介紹了一些Java基礎(chǔ)的核心知識,讓同學(xué)們更好更方便的學(xué)習(xí)和了解Java編程,感興趣的同學(xué)可以關(guān)注一下。