前言
前面幾篇講過,元數(shù)據(jù)側重于配置【驅動】編程的思想觅丰,通過建立統(tǒng)一的數(shù)據(jù)資產(chǎn)翰铡,進一步【驅動】企業(yè)數(shù)字化升級钝域。
但數(shù)字化升級是個戰(zhàn)略性的目標,短期內效果并不明顯锭魔,甚至很多時候容易引發(fā)空談數(shù)字化轉型例证,而達不到實際意義的用途∶耘酰或者落地之后织咧,產(chǎn)生的效果比預期會低很多胀葱。
而數(shù)據(jù)質量往往卻是企業(yè)當下需要解決的問題。比元數(shù)據(jù)管理來得更迫切一些笙蒙。并且元數(shù)據(jù)是需要數(shù)據(jù)質量來引導的抵屿。
1. 元數(shù)據(jù)與數(shù)據(jù)質量的關系是什么呢?
元數(shù)據(jù)是藍圖捅位,就像建筑商建房子一樣轧葛,先要有整體規(guī)劃及配套的周邊設施。而數(shù)據(jù)質量則是執(zhí)行過程中的技術標準艇搀,讓你了解整個藍圖過程中需要面對的所有問題尿扯,以及追蹤反映相應的實際情況。
所以兩者是相輔相成的關系焰雕,彼此相互促進與發(fā)展衷笋。
但是,我們可能沒有建立元數(shù)據(jù)系統(tǒng)淀散,這并不代表沒有元數(shù)據(jù)右莱,只是元數(shù)據(jù)沒有規(guī)整成好的藍圖。就像程序員寫垃圾代碼一樣可以完成功能而已档插,只是對后期帶來了很多潛在的隱患慢蜓。并且元數(shù)據(jù)系統(tǒng)的從視野上來看非常廣泛,可能需要增量構建郭膛,這樣數(shù)據(jù)質量的必要性在這種形式下是很容易提上議程的晨抡。
對于已有的系統(tǒng),數(shù)據(jù)質量相關的問題往往更迫切则剃,這時候可能顧不上數(shù)字化藍圖耘柱。在這種形式下,數(shù)據(jù)質量系統(tǒng)的建的重要度極高棍现,在國情下更是如此调煎。隨著數(shù)據(jù)質量的建立,后期往往會促發(fā)元數(shù)據(jù)的管理己肮。畢竟數(shù)據(jù)質量的定義本身就是一種元數(shù)據(jù)【元數(shù)據(jù)的實體】士袄,而高級數(shù)據(jù)質量的建立需要于推斷功能【元數(shù)據(jù)的關系】,這個就是元數(shù)據(jù)體系的強大之處了谎僻。
所以娄柳,在筆者看來,數(shù)據(jù)質量能解決當下問題更加容易落地生根艘绍。而隨著元數(shù)據(jù)體系的建立赤拒,數(shù)據(jù)質量可以依據(jù)元數(shù)據(jù)更加強大。而元數(shù)據(jù)可以應運而生,轉動它的輪軸挎挖,【逐步驅動】一個新的數(shù)字化世界的到來这敬。
2. 數(shù)據(jù)質量的發(fā)展現(xiàn)狀
當前企業(yè)的現(xiàn)狀是,數(shù)據(jù)質量規(guī)則或多或少總會有的肋乍。畢竟數(shù)據(jù)質量問題直接引發(fā)的就是系統(tǒng)的故障感知度低鹅颊,進而運維成本極高,對業(yè)務的穩(wěn)定性帶來極大的挑戰(zhàn)性墓造。
在這種形式下,數(shù)據(jù)質量是在有限的形式下展開的锚烦。所以觅闽,這種情況下的數(shù)據(jù)質量往往是【事后】數(shù)據(jù)質量。就像上車了再買票一樣涮俄,它沒有花過多精力在前期的準備事項中蛉拙,而是等事情發(fā)生了,然后去【亡羊補牢】彻亲。畢竟有句古話說的好孕锄,相同的錯誤我允許你犯一遍,犯第二遍苞尝,但是不允許你犯第三遍畸肆。所以這種低成本,好附加的方式得到了普遍應用宙址。
雖然這樣【事后檢驗】有效地【顯示】了數(shù)據(jù)質量問題轴脐,進而反饋調節(jié),但是它并沒有從根源上解決【數(shù)據(jù)質量】問題抡砂。系統(tǒng)的復雜度反而隨著【數(shù)據(jù)質量】的建立大咱,而越發(fā)凸顯,畢竟縫縫補補的日子是無法持久的注益,總會有人跳出來的碴巾。
這時候就有出現(xiàn)了【數(shù)據(jù)標準】的概念,覺得數(shù)據(jù)應該是從【源頭】就要抓起丑搔。然而它們所謂的【數(shù)據(jù)標準】是建立在流程之上厦瓢,通過人力來解決并規(guī)范化,對于老的系統(tǒng)要逐步修正低匙,對于新的系統(tǒng)要強行審批旷痕。
而【數(shù)據(jù)標準】往往與【事后數(shù)據(jù)質量】結合得很緊密,如果【數(shù)據(jù)質量指標】提高了顽冶,說明【數(shù)據(jù)標準】得到了效果欺抗。但是這往往是只是改善了情況,還是有大量數(shù)據(jù)質量問題并不能得到解決强重,為什么呢绞呈?因為從源頭到結局贸人,涉及到了太多環(huán)節(jié)跟因素,完全靠人跟流程制度的力量是不太可取的佃声,但是對于企業(yè)高管來說卻很喜歡艺智,因為這樣會顯示他的價值,這里就不過多展開討論了圾亏。
3. 數(shù)據(jù)質量的表現(xiàn)形式
前面講過十拣,【事后數(shù)據(jù)質量】得到了很大的普及,所以ebay開源了apache griffin志鹃∝参剩基本思想就是抽象成一層dsl,然后生成sql去檢驗規(guī)則曹铃,方便使用缰趋。當然還有一些大企業(yè)會把【事后規(guī)則】滲透到etl任務中,可以進行阻塞作業(yè)的執(zhí)行陕见,但是這個架構對于etl性能有很大影響秘血,很難擴展開來。進一步评甜,也有系統(tǒng)將數(shù)據(jù)規(guī)則組成多級規(guī)則灰粮,一旦發(fā)生錯誤,進一步診斷子規(guī)則蜕着,并收集規(guī)則相應的信息谋竖,便于提升系統(tǒng)的故障感知度。
當然承匣,【事后數(shù)據(jù)質量】并沒有從根源上解決問題蓖乘,只是【窮舉檢查后顯現(xiàn)】問題。所以企業(yè)迫切需要從【事后數(shù)據(jù)質量】轉移到【事前數(shù)據(jù)質量】的思維轉變韧骗。但是【事前數(shù)據(jù)質量】由于具有非常大的開放性嘉抒,非常需要啟發(fā)性思維,大部分都在探索期袍暴,不太容易有太多成功案例的【借鑒】些侍。所以【事前數(shù)據(jù)質量】還屬于新生階段,大部分企業(yè)提供出了另外一個子系統(tǒng)概念【數(shù)據(jù)探查】政模,既然無法直接【感知】問題岗宣,那么我就提供相應的數(shù)據(jù)工具,讓其快速了解數(shù)據(jù)淋样,便于快速【分析及診斷】問題耗式。對于數(shù)據(jù)源頭有了一定的【探查】之后,再對數(shù)據(jù)進行相應的進行【約束】與【診斷】,促進【事前數(shù)據(jù)質量】體系的建立與完善刊咳。
本文不太過多關注【事后數(shù)據(jù)質量】彪见,本人覺得真正的【數(shù)據(jù)質量】必定是在源頭控制,進行【約束】娱挨,然后擴展到后期的【故障感知】余指,【事前數(shù)據(jù)質量】才是數(shù)據(jù)質量體系的一盤大期。
常見的事前數(shù)據(jù)質量又分為幾部分:提供數(shù)據(jù)源頭數(shù)據(jù)有效性檢測的【數(shù)據(jù)模式】系統(tǒng)跷坝, 提供數(shù)據(jù)統(tǒng)計的【數(shù)據(jù)探查】系統(tǒng)酵镜,基于統(tǒng)計信息與實體關系進行啟發(fā)式推斷的【數(shù)據(jù)防火墻】系統(tǒng)。
那么現(xiàn)在可以進入本文的正文:【數(shù)據(jù)模式】系統(tǒng)
4. avro構建強大的數(shù)據(jù)模式系統(tǒng)
由于大部分對于avro數(shù)據(jù)模式了解得不多柴钻,先給予一定的介紹
a. avro 歷史背景
對于數(shù)據(jù)模式來說笋婿,歷史上有兩個霸主,一個是google的protobuf顿颅,一個是facebook的thrift,它們主要用于rpc數(shù)據(jù)通訊的數(shù)據(jù)模式足丢,當然跨語言是必備條件粱腻。
但是它們有一個強大的致命弱點,不支持動態(tài)模式斩跌。也就是說它們的模式必須要生成代碼變成類或者語言的數(shù)據(jù)結構绍些。對于每一個數(shù)據(jù)模式都得生成相應的代碼進行規(guī)則約束。當然最新版本的protobuf提供了DynamicMessage動態(tài)反射耀鸦,但是avro已經(jīng)強大到不再是那個少年柬批。
這個時候hadoop之父迫切需要一種數(shù)據(jù)格式,能夠支持數(shù)據(jù)的【物理約束】與【邏輯約束】袖订,支持數(shù)據(jù)的【模式演化】氮帐,支持數(shù)據(jù)的【切塊壓縮】存儲。這個時候avro橫空出世洛姑,一統(tǒng)了大數(shù)據(jù)江湖上沐。
這個avro厲害到了什么程度了。
hive非常早期的版本就已經(jīng)核心支持avro楞艾,支持模式推斷高級功能参咙。
linkedin一直以avro作為核心,建立的kafka schema-registry, kafka connect, kafka sql更是以avro為基礎硫眯。由于hadoop之父不給力蕴侧,老是要搞兼容,不愿意引進其它庫的avro新特性两入,linkedin甚至自立門戶搞了一套閹割版本的Pegasus净宵,然后基于這玩意,搞了一套rest.li元數(shù)據(jù)驅動的微服務架構,以及datahub的元數(shù)據(jù)管理系統(tǒng)塘娶。
flink也是最優(yōu)先支持avro數(shù)據(jù)格式归斤。
什么,你說apache parquet, apache arrow文件格式更厲害刁岸?
avro有四種數(shù)據(jù)形式[json, datum, container, trevni]脏里。trevni就是parquet的前身,面向列存儲虹曙,也繼承了trevni的使命迫横。
如果說avro datum面向于通訊及實時, avro container面向于數(shù)據(jù)交換存儲, avro trevni就是面向于數(shù)據(jù)計算。
前面說過hadoop之父很墨跡酝碳,畢竟兼容性對他來說是頭等大事矾踱,所以apache parquet成功繼承avro trevni,致力于作為數(shù)據(jù)計算的標準存儲格式疏哗,目前也被apache flink/apache spark作為批量計算的核心格式呛讲,當然實時計算被avro牢牢把控。
既然apache parquet想做為標準數(shù)據(jù)計算格式返奉,所以它要無縫對接轉換所有的數(shù)據(jù)格式贝搁。前期它就這么干了,但是隨著google新一代的flatbuffer內存數(shù)據(jù)格式的出現(xiàn)芽偏,它的性能指票顯然不是特別友好的雷逆。
所以批量計算存儲分切成了兩塊,apache parquet與apache arrow污尉。apache parquet是物理存儲形式膀哲,apache arrow是基于flatbuffer的內存數(shù)據(jù)格式,無縫迅猛對接各大平臺的數(shù)據(jù)格式轉換器被碗。
為什么它快呢某宪?如果你讀過flatbuffer的文檔就會知道,它的解序列化開銷為零蛮放,當然apache arrow不是本文的重點缩抡,這里不作過多介紹。
所以包颁,目前大數(shù)據(jù)的生態(tài)瞻想,基本上就是: apache avro(實時,數(shù)據(jù)交換) + apache parquet(批量) + apache arrow(內存)的三大格局娩嚼。當然還有我沒有提到的ORC存儲蘑险,本質上是apache parquet的可選方案,發(fā)展似乎更加緩慢一點岳悟。
b. avro底層原理佃迄。
大部分人對json數(shù)據(jù)格式都有較強的認知泼差。但是json的缺點是很明顯的,它的schema每條記錄都要帶上呵俏,數(shù)據(jù)是文本形式很浪費空間堆缘,無法強制約束數(shù)據(jù)格式,數(shù)據(jù)類型擴展性較弱普碎,對于數(shù)據(jù)模式檢驗有一定的json schema標準支持吼肥。
那么,如果我們把schema單獨提出來麻车,對數(shù)據(jù)類型進行高效編碼缀皱,那么每條數(shù)據(jù)是不是空間最省性能最高呢?居然還真是动猬。啤斗。。
參考鏈接: https://github.com/mtth/avsc/wiki/Benchmarks
編碼規(guī)則在官方文檔里面寫得很清晰了:
https://avro.apache.org/docs/1.9.2/spec.html
我這里簡單介紹一下:
對于int, long其實本質上無差別赁咙,都是采用通用的zigzag變長編碼钮莲,比如如果你的整數(shù)數(shù)值范圍比較少,可能一個字節(jié)就夠存了彼水,不用搞int的四個字節(jié)的標準臂痕。
對于bytes跟string其實無差別,就是長度+內容猿涨。
null就是用單個零字節(jié)表示。
enum轉換成數(shù)字編碼姆怪。
record就是按記錄模式名稱依次按字段名稱順序一個個寫入值(無模式)
map, array就是先寫記錄條數(shù)叛赚,然后再寫內容。當然這里面有個高級用法稽揭“掣剑可以拆分成多個記錄條數(shù)+內容(即子map/array),最后以null零字節(jié)表示結束溪掀。map的key由于是動態(tài)的事镣,要同時寫入key(有模式)/value,適用于無法提前感知的擴展字段場景揪胃。
union就是最強大的類型了璃哟,就是表示可以有多個字段類型。
這里面有一點要注意的是喊递,union不允許相同類型出現(xiàn)随闪,除非是命名類型。命名類型有三種骚勘,record, enum, fixed铐伴。簡單來說撮奏,recordname_b是允許在union里面出現(xiàn)的。不同名稱的record認為是不同的類型当宴。
union是最強大的特性畜吊,也是各個庫實現(xiàn)不一致的地方。
union編碼邏輯非常簡單户矢,先寫入類型的索引值玲献,然后寫入具體編碼值即可。
對于hadoop早期版本來說逗嫡,每個union類型進行json編碼的時候都要加入類型前綴青自。默認每個字段類型是不能為null的,所以可以通過union類型來解決type: ["null", "string"]驱证。如果在java版本里面你必須要寫"field": {"string", "aaa"}或者"field": null延窜。注意"null"類型帶有引號, null值沒有引號。
但是后來大部分其它語言的庫抹锄,包括linkedin的改造版本逆瑞,覺得null是太常見且必要的特性了,如果有個null,就得套一層數(shù)據(jù)格式就顯得太麻煩了伙单。所以對于一個值如果是null或者本身兩個元素的時候做了優(yōu)化获高,可以直接寫{"field":null}, {"field": "aaa"}了。吻育。念秧。
一些java第三方庫也做了增強。
當然布疼,就算加了null類型支持摊趾,僅僅是說這個值可以為null, 也是一定要填的游两。如果想讓這個值可以missing砾层,那么就得給default值,當然這里關聯(lián)到模式演化的內容贱案,將于后續(xù)介紹肛炮。
c. avro的文件格式類型及應用場景。
上一節(jié)講了宝踪,我把schema提取出來侨糟,接著對單條記錄整個數(shù)據(jù)結構按照schema進行編碼,然后就得到了datum瘩燥,有著強大的效率與size縮減效果粟害。
所以,我們認識了第一種數(shù)據(jù)格式datum(在avro-tools里面叫做frag颤芬,有些庫叫做avro_value)悲幅。
這種格式不帶模式套鹅,并且是單條記錄。適用于數(shù)據(jù)量小的單條消息處理場景汰具。比如rpc通訊卓鹿,實時計算。對于rpc通訊留荔,模式是雙方約定好了的吟孙,對于實時計算模式需要單獨關聯(lián),kafka schema-registry是專門管理這個的聚蝶。對于kafka avro的每條消息杰妓,前面有五個字節(jié)表示對應于kafka schema-registry管理的schema id,然后本地有個緩存碘勉,每個schema id只需要去同步獲取一次即可巷挥。
當然對于大批量的數(shù)據(jù)格式,顯然是需要壓縮分塊的验靡,所以avro container文件格式出現(xiàn)了倍宾。
它的算法很簡單:
單個header(avro文件標識+壓縮編碼+數(shù)據(jù)模式) + [多個block(avro_datum記錄數(shù)+ avro_datum壓縮內容)],每個header及block后面接16位隨機生成sync mark用于hadoop分割文件使用胜嗓。hive中對應的avro格式就是avro container格式高职,它是包含了avro_datum頭部的,可以直接下載下來使用avro-tools工具查看辞州。
對于列式存儲avro trevni怔锌,主要由apache parquet接任了,后續(xù)可能會有專門的篇章進行介紹变过。
d. avro的類型約束以及idl模式
avro的類型分為物理類型产禾,邏輯類型及引用類型。
先看物理類型約束:
默認對于每個字段來說是必填不可空的牵啦,如果需要為空,需要走union ["null", type]妄痪,如果需要可缺失, 則可加上default值哈雏。
所以這里嚴格定義了類型的可空性與可缺失性。對于字典值衫生,有enum類型裳瘪,對于每個enum類型會生成相應的整數(shù)值。這對于數(shù)據(jù)質量也是重大的好功能罪针。
對于一個數(shù)據(jù)可能存大多種格式的情況彭羹,比如同一個接口可能返回有不同的類型及值,那么就有union大法了泪酱,定義不同的named record就可以解決了派殷。
對于擴展字段來說还最,由于模式不可知,可采用map結構來處理毡惜。其它已知模式字段必需嚴格按照記錄類型處理拓轻。
邏輯類型約束:
邏輯類型約束是強大的功能,比如Decimal, uuid, date, time相關的類型经伙,都是建立在已有的物理類型上扶叉,建立自己的邏輯規(guī)則。通過添加logicalType屬生來分別帕膜。
對于每個企業(yè)都可以自己自己的邏輯類型枣氧,定制自己的業(yè)務值約束。而標準庫僅提供了上面的通用邏輯類型垮刹。
引用類型約束 :
對于每一個命名類型达吞,尤其是record類型,是可以引用的危纫。
也就是說宗挥,不可能存在兩個相同名稱的record類型,如果另一個地方有相同的record類型名稱种蝶,它就不需要再定義具體結構契耿,直接引用過來復用了結構定義。
如果確實想要相同名稱的record類型螃征,那么可以添加namespace進行區(qū)分搪桂。
在相同的namespace下面不能有相同的命名類型出現(xiàn)。如果需要復用盯滚,可以定義共用的namespace進行引用踢械,或者直接引用其它人的namespace。如果不需要復用魄藕,可以定義各自namespace下的數(shù)據(jù)結構内列。默認不定義都在相同的namespace下面。
IDL文件
avro雖然引入了引用數(shù)據(jù)類型背率,對于需要復用的類型可以引用過來话瞧,但是隨著模式的復雜度,json表達形式維護性會比較困難寝姿。這時候可以引用idl文件交排,進行拆解,idl接口格式可以進行import以及獨立的類型定義饵筑。然后組合轉換生成單個avsc模式文件
e. avro的模式演化
前面雖然講過json的很多壞話埃篓,但是json有很強的靈活性,比如值缺失根资,新增不影響代碼的正常運行架专。avro不止這些基礎功能同窘,它更加強大。
- 字段增刪改
avro可以用老的代碼讀新的數(shù)據(jù)胶征,也可以用新的代碼讀老的數(shù)據(jù)塞椎。
它是怎么做到的呢?
如果一個模式字段新增睛低,那么它必需要默認值案狠,如果一個字段刪除當然不受影響。
比如老的模式字段有a, b, c, 新的模式字段有a, c, d钱雷。
當新的模式依次按字段讀取老的數(shù)據(jù)的時候骂铁,發(fā)現(xiàn)沒有d,但是它有默府值它所以是沒有問題的罩抗。
當老的模式讀取新的數(shù)據(jù)的時候拉庵,發(fā)現(xiàn)沒有b淡溯,如果對于老的模式有b的默認值也是可以運行正常的铲掐。
所以理澎,老的模式如果想兼容新數(shù)據(jù)温亲,它就必須對它以后想要刪除數(shù)據(jù)提供默認值。新的模式想兼容老數(shù)據(jù)乒验,那么它就必須對新增的字段提供默認值挥转。
當然各種兼容模式可以按需選擇兜看。
-
值的類型轉換
除了字段的增刪骨坑,另一個問題就是字段的可空性問題了撼嗓。比如同樣的字段,在有的系統(tǒng)可以為空欢唾,有的系統(tǒng)不為空且警。我們可以分別讀取成各自特寫的外部表,也可以通過通用的行為讀取成通用的外部表礁遣。
當然空值是跟union的模式演化有關系的斑芜。
關于模式演化的規(guī)則有興趣可以參見問題進一步了解。
圖片.png 模式演化的過程祟霍。
對于一個已經(jīng)序列化過的數(shù)據(jù)杏头,新的模式是無非讀取的。所以模式演化分為兩部分浅碾,這也是avro重度依賴于schema的一個原因。首先reader通過writer schema(寫入時schema)讀取值出來续语,然后通過reader schema進行resolve轉換成新的數(shù)據(jù)格式垂谢。
f: avro的編碼格式及應用
前面所說的avro datum格式是binary編碼的,當然它也有對應的json編碼疮茄。json編碼一般用于轉換json數(shù)據(jù)至binary編碼滥朱,或者binary編碼轉換成外部json數(shù)據(jù)根暑。本質是就是根據(jù)schema進行遍歷,讀取或者輸出對應的json或者binary格式.
當然avro也可以把文本文件的每一行當作是bytes模式徙邻,進行切塊壓縮成container文件排嫌,便于可切割壓縮形式的文件處理格式。
那么我們來看一下avro-tools給我們提供的功能
源碼路徑:
https://github.com/apache/avro/tree/master/lang/java/tools
larry@larrys-MBP-2 ~ % avro-tools
Version 1.9.1
of Apache Avro
Copyright 2010-2015 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (https://www.apache.org/).
----------------
Available tools:
canonical Converts an Avro Schema to its canonical form
cat Extracts samples from files
compile Generates Java code for the given schema.
concat Concatenates avro files without re-compressing.
fingerprint Returns the fingerprint for the schemas.
fragtojson Renders a binary-encoded Avro datum as JSON.
fromjson Reads JSON records and writes an Avro data file.
fromtext Imports a text file into an avro data file.
getmeta Prints out the metadata of an Avro data file.
getschema Prints out schema of an Avro data file.
idl Generates a JSON schema from an Avro IDL file
idl2schemata Extract JSON schemata of the types from an Avro IDL file
induce Induce schema/protocol from Java class/interface via reflection.
jsontofrag Renders a JSON-encoded Avro datum as binary.
random Creates a file with randomly generated instances of a schema.
recodec Alters the codec of a data file.
repair Recovers data from a corrupt Avro Data file
rpcprotocol Output the protocol of a RPC service
rpcreceive Opens an RPC Server and listens for one message.
rpcsend Sends a single RPC message.
tether Run a tethered mapreduce job.
tojson Dumps an Avro data file as JSON, record per line or pretty.
totext Converts an Avro data file to a text file.
totrevni Converts an Avro data file to a Trevni file.
trevni_meta Dumps a Trevni file's metadata as JSON.
trevni_random Create a Trevni file filled with random instances of a schema.
trevni_tojson Dumps a Trevni file as JSON.
- 通過json與avro datum格式互轉
avro-tools jsontofrag --schema schema/XXX.avsc sample/XXX.json
cat xxx.avro | avro-tools fragtojson --schema-file schema/XXX.avsc -
- 通過json與avro container格式互轉
avro-tools fromjson --codec snappy --schema-file schema/XXX.avsc
avro-tools tojson xxx.avro
avro-tools getschema xxx.avro
- 編碼text文件轉換成avro壓縮格式
avro-tools fromtext ...
avro-tools totext ...
- avro idl生成avsc模式文件
avro-tools idl ...
g. avro的各個語言版本
官方版本清單:
https://github.com/apache/avro/tree/master/lang
rust版(本人參照改造增強缰犁,可交流):
https://github.com/flavray/avro-rs
java增強版(本人參照改造增強淳地,可交流):
https://github.com/Celos/avro-json-decoder
https://github.com/zolyfarkas/avro
js增強版:
https://github.com/flavray/avro-rs/
c擴展版(本人參照改造增強,可交流):
https://github.com/grisha/json2avro
avro手機版(本人參照改造增強帅容,可交流):
https://github.com/flurry/avro-mobile/