開發(fā)前的聲明
????? ? udf開發(fā)是在數(shù)據(jù)分析的時(shí)候如果內(nèi)置的函數(shù)解析不了的情況下去做的開發(fā),比方說(shuō)你只想拆分一個(gè)字段,拼接一個(gè)字段之類的,就不要去搞udf了,這種基本的需求自帶函數(shù)完全支持,具體參數(shù)可參考文檔:
????????http://spark.apache.org/docs/latest/api/sql/search.html?q=cast
?????? ?里面列舉了所有函數(shù)的介紹和使用,推薦優(yōu)先使用官方推出的,因?yàn)樽约簩懙膗df如果對(duì)一些異常處理不到位可能會(huì)導(dǎo)致數(shù)據(jù)分析的失敗或者意想不到的情況。但是內(nèi)置的函數(shù)真的滿足不了那就真的沒(méi)辦法了,比如在做數(shù)據(jù)分析的時(shí)候經(jīng)常使用的是ip解析,這個(gè)通常就需要自己開發(fā)udf了。
udf的分類
????? ? udf平常用的多的也就兩種,一種java寫的,一種python 所寫,下面對(duì)這兩種情況分別做個(gè)簡(jiǎn)單的demo供大家參考。
udf for java(idea)
????? ? 1.創(chuàng)建maven工程
????????? ? file->project structure->modules->點(diǎn)擊+號(hào)->new module->選擇maven
?
? ? ? ? ? ? 點(diǎn)擊next,填寫groupid(對(duì)應(yīng)包結(jié)構(gòu))、artifactid(maven倉(cāng)庫(kù)對(duì)應(yīng)的坐標(biāo))
? ? ? ? ? ??source java 代碼,操作如下圖file->project structure,
?
? ? ? ? ? ? 點(diǎn)擊apply,
? 2.開始寫java代碼
????????? ? pom文件添加依賴
org.apache.hive
hive-exec
0.13.1
?
import org.apache.hadoop.hive.ql.exec.UDF;
public class HelloUdf? extends UDF {
public String evaluate(String ip) {
return ip+ip;
}
public int evaluate(int ip) {
return ip+ip;
}
????????????}
3.編包上傳到hdfs
????????? 在此項(xiàng)目pom文件的路徑下執(zhí)行mvn clean install
? ? ? ? ? 將target文件中生成的jar文件上傳到hdfs上,路徑自己自定義,我直接上傳到/。
? ? ? ? ??sudo -u hdfs hdfs dfs -put testudf-1.0-SNAPSHOT.jar /
? ? ? 4.使用hivesql或者sparksql加載自定義函數(shù)
????????? ?beeline -u jdbc:hive2://node113.leap.com:10000 -n hive
? ? ? ? ? ?create function test.iptonum as 'com.liubl.HelloUdf' using jar 'hdfs:///testudf-1.0-SNAPSHOT.jar';
? ? ? ? ? ?(com.liubl.HelloUdf為代碼類的全路徑自己去粘貼一下)
? ? ? ? ? ?(測(cè)試sql見(jiàn)圖)
?
udf for python
????? ? python udf入門我就不重新闡述了,我看到有一位同學(xué)的博客寫的很清晰,推薦博客
? ? ? ? https://blog.csdn.net/qq_26937525/article/details/54136317
? ? ? ? 存在的問(wèn)題:? ?
在數(shù)據(jù)清洗過(guò)程中,如果使用的是TransForm而不是UDF的話,因?yàn)镻ython是直接向系統(tǒng)申請(qǐng)資源的,而不是像ResourceManager申請(qǐng)資源,故會(huì)導(dǎo)致啟動(dòng)的Python腳本對(duì)內(nèi)存和CPU的使用不可控,尤其是當(dāng)啟動(dòng)多個(gè)Map時(shí),因?yàn)橐粋€(gè)map將啟動(dòng)一個(gè)Python因此,當(dāng)同時(shí)運(yùn)行的map有幾十個(gè)時(shí)(測(cè)試集群較?。?,同時(shí)將嘗試啟動(dòng)相同個(gè)數(shù)的python(資源夠用的話仍然會(huì)啟動(dòng)幾十個(gè)),且此時(shí)Map占用的內(nèi)存是不會(huì)釋放掉的他在一直等待Python的結(jié)果,這將導(dǎo)致python可用的資源僅僅是原本分配給系統(tǒng)的很少的資源(注:在安裝Hadoop時(shí),對(duì)于單個(gè)節(jié)點(diǎn),一般僅僅給系統(tǒng)留出很少的內(nèi)存,其他的內(nèi)存全部分給了集群。例如32G物理內(nèi)存的節(jié)點(diǎn)給系統(tǒng)和dataNode+nodeManager的內(nèi)存就4-8個(gè)G,同時(shí)CPU核數(shù)也不足節(jié)點(diǎn)的一半,剩余的內(nèi)存和cpu核數(shù)全部劃分給集群使用。需要注意的是,這里雖然說(shuō)是劃分給集群使用,僅僅是邏輯上的劃分,即規(guī)定集群可以使用的最大的物理內(nèi)存,超過(guò)該內(nèi)存時(shí)MR可以認(rèn)為是不會(huì)搶占分配給系統(tǒng)+DataNode+nodeManager的內(nèi)存的,但是當(dāng)集群中沒(méi)有MR在執(zhí)行,即沒(méi)有map或者reduce在執(zhí)行時(shí),劃分給集群的這部分資源是可以被系統(tǒng)使用的。而若有map和Reduce在執(zhí)行時(shí),運(yùn)行map和reduce的JVM的資源不會(huì)因?yàn)橄到y(tǒng)進(jìn)程需要使用而被釋放掉)所以,所有正在執(zhí)行的Map一直在等待python的運(yùn)行結(jié)果而沒(méi)有釋放掉其自身占用的資源,故python無(wú)法使用分配給集群的資源而只能使用預(yù)留給系統(tǒng)+nodeManager+DataNode的4-8G的內(nèi)存和很少的cpu核數(shù)。因此會(huì)導(dǎo)致集群的資源無(wú)法被高效利用。
綜上,使用Transform(Python)執(zhí)行效率低的根本原因在于Python是直接向操作系統(tǒng)申請(qǐng)資源,而不是向YARN的ResourceManager申請(qǐng)資源,故而導(dǎo)致節(jié)點(diǎn)的資源無(wú)法高效組織和被利用。此外,不要輕易使用transform!不要輕易使用transform!不要輕易使用transform