網(wǎng)絡(luò)工程技術(shù)主要學(xué)什么網(wǎng)站優(yōu)化培訓(xùn)班
背景
故事的起源來源于這樣一篇關(guān)于序列化/反序列化優(yōu)化的文章https://www.ververica.com/blog/a-journey-to-beating-flinks-sql-performance,當(dāng)把傳輸?shù)膶ο髲腟tring變成byte[]數(shù)組后,QPS直接提升了50%
flink的網(wǎng)絡(luò)數(shù)據(jù)交換優(yōu)化
在flink中對于每個(gè)算子之間的跨網(wǎng)絡(luò)數(shù)據(jù)交換,序列化和反序列化都是不可以避免的一環(huán),上游算子需要把對象序列化成字節(jié)數(shù)組后通過網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)傳輸,而下游算子收到字節(jié)數(shù)組的數(shù)據(jù)后對字節(jié)數(shù)組進(jìn)行反序列化操作,當(dāng)有多個(gè)這樣的shuffle算子操作后,序列化和反序列化占用的cpu就會非常大,對程序性能造成極大的影響,所以問題就變成了如何最大化的減少序列化和反序列化的開銷?
我們這里只是用Tuple類型序列化器作為例子,假設(shè)都是Tuple1類型,其泛型類型分別為String和byte[],可以在本地使用jmh對于這兩者的序列化反序列化性能進(jìn)行測試,你會發(fā)現(xiàn)巨大的性能差距,差異的來源在于對于String,序列化時(shí)需要先把String轉(zhuǎn)成byte[],然后反序列化又要再把byte[]轉(zhuǎn)成String,這樣當(dāng)有幾千萬的String要處理時(shí),這是一批很大的開銷.相反,對于byte[]來說,它可以作為字節(jié)數(shù)組進(jìn)行網(wǎng)絡(luò)傳輸,序列化和反序列化的開銷幾乎沒有,所以可以節(jié)省大量的cpu資源
總結(jié):
當(dāng)有一條消息經(jīng)過很多個(gè)算子才到達(dá)最終的sink算子時(shí),如果這個(gè)消息里面的類型是String,每經(jīng)過一個(gè)算子就有一次String–>byte[]的序列化和byte[]–>String反序列化的開銷,N個(gè)算子就會有N次這樣的序列化/反序列化操作,可想而知,這是一個(gè)非常低效的操作,我們可以這樣優(yōu)化:在消息進(jìn)來之后新增一個(gè)map操作,先把String轉(zhuǎn)成byte[]數(shù)組,后面?zhèn)鬟f的時(shí)候一直是傳遞的byte[]字節(jié)數(shù)組,這樣通過每一個(gè)算子時(shí)就幾乎沒有序列化和反序列化的開銷了,可以極大提高性能