從2012-01-29開始提交到github開始算,現在phpHiveAdmin已經開發了接近兩個月。很多是業餘時間在寫,上班也會寫寫,但主要工作還是維護hadoop叢集,hive叢集,跟各部門的資料需求進行對接和偶爾編寫一些map/reduce指令碼,其實map/reduce指令碼寫的已經少了,大部分都是我的同事在寫。幫我分擔了不少工作壓力,很感謝他們,也很感謝我的上級,全力支援我做這麼一個公司專案外的破玩意。我真覺得我們資料組的人都是最棒的,無論從人品還是技術實力來說。
公司裡面已經將phpHiveAdmin內部版作為開放資料平臺專案的一部分,在公司各部門推廣使用了,以後資料組直接的任務壓力會減輕不少。很多工作可以分流給各個部門自己查詢使用了。
這兩天,查詢任務分流了,閒下來了,就記錄一下這個開發過程和架構構思和想法心態,以後回顧起來也是個樂子。
當初開發phpHiveAdmin說起來也偶然,也必然。在第一次easyhadoop開發者聚會上輪到我講解這個玩意,我是先這樣跟大家介紹自己的:“我是個很懶的人。”懶其實是一種慾望,慾望是我寫這個東西的主要動力。印象裡,在以前淘寶資料所做的報告中,淘寶有50%以上的資料查詢都是由hive完成的。最根本的原因,我認為,是hive滿足了懶人的需要,比如我以前是寫mysql的或者sql server的,或者oracle的,都可以很容易的上手轉向使用hive,因為hive就是個SQL語言的查詢器。我很懶,我不想再去學一個新的語言,pig,或者其他什麼東西。那麼hive拿過來稍微學一點點就可以快速的進行資料統計分析的工作,剩下的無非就是sql語言水平的差異了。另外,你教一個資料統計的新人用sql語言和教他用一個全新的語言,顯然sql語言的時間精力成本更低。
基於懶的激勵,我本來想找一個現成的開源來用,但搜遍了google,卻發現沒有hive最易配置和最易使用的開源周邊工具,我和我的同事們不得不面對一個SSH命令列。每天重複的敲use xxxx;select xxxx, use xxxx;select xxxx, use xxxx; create xxxx;use xxxx; alter xxxx……無休無止,暗無天日。hwi那個破玩意又那麼簡陋和難以使用。而且資料分析的sql也都知道,一寫就是十幾二十行,看的頭暈眼花。
為自己,保護視力,我決心改變這種窘境,自己寫一個東西,核心目標就是簡單,易用。沒有那麼多高尚的情操,什麼為中華民族偉大復興而努力程式設計之類的,完全沒有,就是為了自己省事,一方面省得寫sql語言了,一方面如果教會別人用,扔給別的部門自己查數,我連資料查詢任務都不用接了。於是某天下班後自願加班,寫了三個小時,用thrift寫出了一個簡單的查詢器。看能簡單查詢,就扔下回家了。
然後第二天我自己用的時候,立刻就遇到了第一個大問題:執行超時。
Hive由於是跑hadoop的map/reduce任務,所以通常查詢時間會很長,這就帶來一個web server超時和php程式執行超時的問題,改了相關的配置檔案還是不行,就懷疑是thrift的問題,仔細看了看機器生成的原始碼,讀得這叫一個費勁,還上網找了各種資料。於是後來就有了我那篇 php開發hive web查詢 的文章。
增加了一些新增刪除資料庫,表的功能,開始在資料組內部推廣使用。並且整理了一下程式碼,開始開源。不過一開始的情況並不理想,同事們覺得這個東西很方便,但是又都不愛用,究其原因,是一個執行狀態返回的問題。人的心理是個很微妙的東西,所謂眾口難調,有些人喜歡盯著程式一步步執行,有些人喜歡扔在那就出去玩了,一會兒回來看結果。
不過有狀態返回比沒有強。這就引出了第二個大問題:非阻塞和非同步執行。
這個問題其實也分成三個小問題,一個是從哪即時獲取map/reduce執行狀態,一個是如何非阻塞和非同步執行,還有一個就是環境變數的問題。
第一個小問題其實就困擾了一段時間,在命令列cli方式下執行hive查詢,看到的map/reduce進度和結果返回都是在一個螢幕輸出的,但是實際在hive內部執行是分兩個地方輸出的,map/reduce是執行狀態是輸出到stderr,而結果集是輸出到stdout。為了解決這個問題,又得閱讀,文件是很難發現的,都是洋文,看也瞎看(其實我自認為洋文不差,侃個大山,罵罵髒話不成問題,但是看時間長了眼花),看了一下原始碼,又結合shell的重定向操作,才發現如何分離這兩種輸出。其實在這個問題上我就已經糾結了,這期間我曾經想放棄用php,想轉用python或者java,shell結合起來開發。因為thrift是斷然獲取不到stderr的輸出,php又無法非阻塞的實時獲取shell指令碼的輸出流,所以就很頭疼。玩過php的都知道,php的非阻塞和非同步簡直就是噩夢,我為了這事連python的tornado都架上了。但是最終還是攻克了這個難題,非阻塞和非同步執行最核心思想就是多程式,幸好php裡有proc_open,至於我為什麼沒用pcntl開發多程式,其實也是我為什麼最終決定沒用python或java開發非同步的原因。很簡單,我就是想讓這個東西最簡化,讓使用者的部署難度降到最低。因為我就是使用者,我不想給自己找麻煩!!你只要配上預設配置的php就可以用,php的configure完全不需要加任何–enable或者–with。如果你不要meta資料,你安裝php甚至不需要配置mysql就可以用phpHiveAdmin!!
在解決這兩個小問題的同時,意外的解決了一個bug,就是記憶體溢位的問題,thrift是直接從hive的埠讀取資料,大多數情況下,hive返回的資料都會很大。thrift不管,一概全讀,很輕鬆就超過了php記憶體的限制,造成記憶體溢位。轉用多程式命令列方式以後,是stdout輸出,如果出問題了,那他媽一定是Linux Kernel的問題了,就只能找Linus解決了。意外解決了這個問題,是個出乎意料的收穫。
上面是前兩個問題,也是最困難的部分。第三個問題不難,但是挺混蛋的。為了獲取hive的map/reduce輸出,我把查詢部分改造成了命令列方式執行。但是這帶來一個問題,任何執行都會報HADOOP和JAVA環境變數找不到。原因是這樣,php的任何一個exec,或者system,或者passthru,或者proc_open。都相當於一個shell程式,或者相當於一個crt視窗,你用多個exec,其實就相當於開了多個SecureCRT或者putty的視窗,其實哪個之間的環境變數都跟其他的無關。所以儘管寫了好幾個exec,執行到hive的時候還是會報找不到環境變數。所以,沒辦法,只能全寫在一行裡了。這個是最簡單的一個小問題了。
於是這幾個問題都解決了,於是就有了里程碑版本,0.05 beta2。可以通過非阻塞和非同步實時的檢視map/reduce狀態,且不會記憶體溢位。說到這兒我也要感謝一個做php頁面開發的同事,他最近被土豆挖走了。我的前端水平很爛,非常爛,他幫我用ajax實現了頁面的非同步讀取檔案並重新整理,所以才能實時的檢視map/reduce的狀態,我真的一點不會現在的頁面技術,出去找工作肯定沒人要。
phpHiveAdmin的ETL功能我自己覺得還是比較有趣的事情,用ini檔案實現配置hive自動運算資料,並將結果匯入mysql資料庫,這是我目前能想到的最簡單和最方便的ETL配置方法了。目前還沒有著力研發,還屬於試驗階段,但其實已經可以用了。未來計劃會加入crontab版的ETL,那就齊活了,phpHiveAdmin除錯HQL語句,然後放到ETL裡面定時執行,完美的資料抽取和展現方案,我稱之為一攬子計劃,或者叫菜籃子計劃也可以。
還有就是我為什麼使用HQL自帶的查詢來獲取資料庫名,表名等等資料而不用metastore裡面的資料。因為這是最省事的辦法,而且無需關心hive的metastore用的是什麼儲存引擎。metastore目前我已知有兩種儲存方式,jdbc和odbc,用的最多可能就是mysql,pgsql和hive自帶的derby了。mysql, postgreSQL都需要jdbc,derby需要unixODBC,如果我拿出去部署,沒有jdbc,豈不就要在編譯php的時候安裝unixODBC嗎?太麻煩了,我不能給自己找麻煩。況且,後設資料太重要了,一旦隨意使用被破壞了,一切都完蛋。所以我就沒有用後設資料來獲取hive的資料庫結構,表結構等資訊,而都是用HQL來完成這些資訊獲取的。基於這種想法,也就沒有使用hive自帶的許可權控制,而是自己寫了一套許可權控制,雖然現在還很簡陋,我不希望任何複雜的東西成為phpHiveAdmin安裝部署的一個羈絆。
目前phpHiveAdmin更新到了0.06 beta2,正在努力實現partition的所有相關功能。版本庫在github,googlecode和sourceforge上都有同步更新,那個快訪問那個。
同時也歡迎更多愛好開源的人加入到這個專案,共同成長,進步,直接給我發短訊息就好了。
訪問http://www.phphiveadmin.net獲取更多資訊。