常常的,我會感恩于我所在的公司订框,讓自己經(jīng)歷了種種析苫。很多情況下,公司的成長帶動了自己的成長。完整的跟著公司經(jīng)歷大數(shù)據(jù)業(yè)務從無到有衩侥,從有到精国旷,這種歷程就像美味的食物,吃過了才能真正感覺茫死,而文字是不足以表達的跪但。
我走過了畢業(yè)季,創(chuàng)業(yè)征途峦萎,踏進開源之路屡久,轉(zhuǎn)型進入大數(shù)據(jù),到最后有緣接觸機器學習爱榔。每個章節(jié)被环,我都會提及對應那個階段對技術的感悟,自己做的一些具體事情详幽。
到寫這篇文章為止筛欢,我發(fā)現(xiàn)經(jīng)過這八年,我依然沒有懈怠下來唇聘,我依然在狂奔悴能。
畢業(yè)季
2008年12月,清晨的陽光有氣無力的鋪在了一片沒有經(jīng)過打理的草地上雳灾。有了陽光漠酿,沒了打理,自然成了雜草兒們的天堂谎亩,千奇百怪任性長著炒嘲。陽光順著草地,扶著墻翻過窗子匈庭,躍進了陽臺夫凸。陽臺左邊是洗手間,前方是一個虛掩著的門阱持,到了這夭拌,陽光止住了它慵懶的腳步。大學的宿舍是長方形的衷咽,四個邊角都放著寫字臺和床鸽扁。說是床,其實就是寫字臺上的一個擋板镶骗。海南蚊子多桶现,所以擋板上都是有蚊帳的,蚊帳帶來的壞處是鼎姊,如果蚊子進去了骡和,它除了煩你也別無出路相赁,好處是,可以形成自己的一個小牢籠慰于。我睡眼惺收钮科,散發(fā)著一絲頹廢的氣質(zhì)。頹廢在這是一種贊美的詞婆赠,只有藝術家才能配的上頹廢這個詞绵脯。當然,我不是藝術家页藻,所以放在我身上,也就是真實頹廢本意解釋了植兰。很快份帐,我會熱血的成為幾百萬即將畢業(yè)的學生,被學校撒豆成兵楣导,最后可能成為炮灰废境。
我確實成為了炮灰。
剛從深圳鎩羽而歸筒繁,原本希望能在深圳找份工作噩凹,但落了空,完全沒有門道毡咏,愣頭愣腦的去了驮宴,愣頭愣腦的回來。期間十幾天呕缭,一個面試的機會都沒有撈到堵泽,深圳現(xiàn)在也是完全不記得什么樣子了。
這種感覺恢总,想必和艾倫第一次去和巨人戰(zhàn)斗的情景是一樣的迎罗。
框框框,有人敲門片仿,我們沒搭理纹安,接著他在門外問:有個公司來學院招聘,是招計算機的砂豌,你們要不要去看下厢岂。
我餓了,真的餓了阳距,我沒做任何思考咪笑,便起床動身。原先困倦的大腦腦功率趨近于0,現(xiàn)在瞬間飆升娄涩。恩窗怒,是腦功率映跟,不是荷爾蒙。
那個時候自己就像一只農(nóng)村的土狗扬虚,只要有份工作就行努隙。而且如果純粹做個碼農(nóng),我還是很自信的辜昵。大學期間我就已經(jīng)定了方向荸镊,專攻Java,所以或多或少還是有些積累堪置,畢設的時候用Java寫了個程序躬存,給磁盤建索引,用的Lucene舀锨,順利過了畢設岭洲。沒想到的是,我竟然因此和搜索結(jié)緣坎匿,一直持續(xù)到今天盾剩。
創(chuàng)業(yè)征途
突然來的機遇就是這么神奇,也讓人感覺莫名其妙替蔬,說來就來了告私,你真的不知道為什么會來,但真的就是這么來了承桥。
當機遇來臨的時候驻粟,常常讓人懊悔的是抓不住。但抓住了凶异,也未必會讓你成功格嗅。但是,這是一個不管成功或者失敗唠帝,都讓你收獲滿滿的一次機遇屯掖。
這是一家創(chuàng)業(yè)公司。我去的時候一開始只有三個人襟衰,A君贴铜,B君,還有我瀑晒。
A君多才多藝绍坝,產(chǎn)品經(jīng)理+UI設計+投資人,B君和我則同為技術合伙人苔悦。
在找到我之前轩褐,A君和B君已經(jīng)在海南師范大學旁邊的一棟寫字樓租了一個辦公室。現(xiàn)在回想一下玖详,或許我們應該租個地下室把介,成功的概率可能會更高些(不過勤讽,如果去美國的車庫或者地下室,應該成功率又會提高)
就這樣拗踢,08年12月開始了我程序員脚牍,或者是創(chuàng)業(yè)的征程吧。
我們做的是一個原創(chuàng)音樂站點巢墅。
這期間我們常常每天工作13-14小時诸狭。要知道,那個時候我們沒做過任何項目啊君纫,只是大學看了幾本程序設計的書驯遇,而真正做出一個產(chǎn)品,需要掌握的東西卻是是非常多的蓄髓。
但是熱血和時間這東西叉庐,真的是有用的。就這么著双吆,基于熱血的推動眨唬,時間的磨礪会前,漸漸的好乐,一個原創(chuàng)音樂分享網(wǎng)站竟然慢慢開始開始有模有樣了,整個過程瓦宜,我們自己設計蔚万,開發(fā),購買服務器临庇,托管反璃,運維,運營假夺。
作為一個流媒體音樂站淮蜈,不同于一個簡單博客,尤其是對于我們幾個沒有什么技術積累的年輕人而言已卷,其挑戰(zhàn)是非常大的梧田。
流媒體服務器,Web端Mp3播放器侧蘸,音樂上傳裁眯,音樂轉(zhuǎn)碼,音樂下載讳癌,個性化主頁等等穿稳,挑戰(zhàn)非常多。B君后期專攻頁面和JS晌坤,我想逢艘,他現(xiàn)在能夠開發(fā)Web端操作系統(tǒng)旦袋,也得益于這次的挑戰(zhàn)的吧。
首先是站點搭建埋虹,沒有采用Worldpress之類的開源組件猜憎,真的是從零直接從頭開始做的。那個時候不知道原型設計工具Axure搔课,A君就直接用Photoshop把界面畫出來胰柑,然后把一些小ico切出來給我們用。A君雖然沒有做過產(chǎn)品經(jīng)理和UI設計師爬泥,但是他設計出來的界面真心大氣(08年的時候)柬讨,后續(xù)我們的對手,原創(chuàng)音樂中國袍啡,還有那有個因為涉黃被關閉的一個網(wǎng)站踩官,都在我們上線后不久改版,我們對比過境输,明顯借鑒了我們的設計元素蔗牡。
我和B君大學學的都是Java,于是采用了SSH2開發(fā)。從頭開始壘代碼嗅剖。還是那句話辩越,如果只是做個類似博客平臺的站點自然是不難,但我們做的是原創(chuàng)音樂分享網(wǎng)站信粮。這里面涉及到如下幾個難點:
首先我們是個音頻流媒體網(wǎng)站黔攒,需要搭建流媒體服務器,以及播放音頻的客戶端
接著這是針對音樂人的一個社交網(wǎng)站强缘,有點類似現(xiàn)在的微博督惰,音樂人上傳了大量自己的音頻,需要大量的粉絲以及與之互動旅掂。所以需要提供一個酷炫的個人主頁赏胚,QQ空間是一個標桿。
于是經(jīng)過仔細研究商虐,我們使用了Red5 搭建了音頻流媒體服務器觉阅,實現(xiàn)了一個簡易的 flash 音頻播放器,暴露js調(diào)用接口称龙,使用Js進行控制留拾。
個人主頁我們花費的精力非常多,09年時鲫尊,我們就已經(jīng)仿照QQ了痴柔,允許換膚,自定義布局,這個對前端以及后端要求都挺高的啤誊。后面B君在做后端服務的時候,也同時成了一個前端高手厢塘,我可以說谈火,他已經(jīng)精通CSS和JavaScript了侈询。(后來B君來了北京,后續(xù)又去了香港糯耍,在香港時扔字,已經(jīng)可以用JS開發(fā)Web操作系統(tǒng)了,這是后話)温技。 整個頁面任何一個版塊革为,你都可以顯示,隱藏舵鳞,互換位置震檩,設置不同模板。
作為一個流媒體網(wǎng)站蜓堕,上傳音頻是個很重要的東西抛虏,為了顯示上傳進度,我們當時就折騰了好一會套才,接著遇到轉(zhuǎn)碼問題迂猴,使用了ffmpeg,設置要把轉(zhuǎn)碼進度也顯示給用戶看。
到后來霜旧,我們已經(jīng)做了一個類似蝦米這種音樂類的網(wǎng)站很多功能了错忱,比如給出音樂列表儡率,自動播放挂据,直接在title上顯示播放進度等等。
SSH2 給我的感覺就是慢儿普,調(diào)用棧太深了崎逃。作為一個互聯(lián)網(wǎng)應用來說,真的不適合眉孩。但是架構(gòu)已經(jīng)選定个绍,也沒辦法。于是我們通過大量添加緩存的方式解決性能問題浪汪。
有大量的資源巴柿,自然就需要搜索了。為了方便查找歌曲死遭,我們引入了基于Lucene的Compass广恢。可以直接基于數(shù)據(jù)庫建立lucene的索引文件呀潭。一般這種東西钉迷,很難用好至非,或多或少都有問題。我期間就經(jīng)常各種錯誤糠聪,各種問題荒椭,不堪其擾。
到10年的時候舰蟆,我們的歌手用戶只有幾千趣惠。但是歌曲數(shù)量以及總文件大小已經(jīng)相當可觀了。我們在各個細節(jié)進行了非常大的努力身害,比如歌曲信卡,用戶評論,可見不可見题造,上傳進度傍菇,頁面設計等等。
產(chǎn)品我們覺得問題不大了界赔,可是丢习,可是我們該怎么推廣運營呢?完全沒有門道淮悼。而且從08年到10年咐低,差不多一年半,我們是完全沒有盈利的袜腥,只是在燒A君的錢见擦。
如果有了一定的用戶量和活躍度,其實關于盈利的形態(tài)我們都是想好了的羹令,當然這個也是借鑒國外的模式鲤屡。而且我到現(xiàn)在都認為是一個好的模式。
但是我們感覺我們快撐不到那個時候了福侈。我們那時候也沒有投資人的概念酒来。在海口肪凛,互聯(lián)網(wǎng)行業(yè)是相當不發(fā)達的堰汉。不像現(xiàn)在,你拿個想法伟墙,跑到咖啡廳翘鸭,就有人會聽你講。
于是我們展開了自救行動戳葵。10年團購很火就乓,于是,我們打算先暫時放下手中的主業(yè),做起了團購档址。但是后面我們才知道盹兢,團購初期是很燒錢的,不是我們能玩的起的守伸。
海南是個旅游大省绎秒,于是我們開始做旅游站,但是啊尼摹,旅游要有線下資源见芹。
急了就什么都嘗試了。
2010年10月國慶期間蠢涝,基本上宣告了創(chuàng)業(yè)的失敗玄呛。海口有個奇特的天文現(xiàn)象和二,就是凡是國慶七天徘铝,那是必然下雨的。這個國慶也不例外惯吕,整整七天都是雨惕它。我當時是個E站的一個老用戶(只是看文章的老用戶),看到了E站正好招人废登,但那個時候招的是Ruby程序員淹魄。于是十一前的一個禮拜,我弄了一本敏捷開發(fā)的書堡距,然后把58同城的UI扒下來甲锡,然后用ruby on rails 寫了站點,包括抓取羽戒,包括顯示等缤沦。當然,沒有后臺半醉。整整做了一個禮拜疚俱,然后把它作為示例代碼打包劝术,發(fā)給了E站缩多。 后面就接到了E站老大的面試電話。
E站的老大看了我的代碼后养晋,讓我很順利通過了電面衬吆,問我是否可以直接去北京。我當時心想绳泉,偶像就是偶像逊抡,看代碼就能看到我的能力以及誠意,沒有N輪面試的折騰。
走的那天冒嫡,好像還是下著雨拇勃。當時我的生活已經(jīng)非常窘迫了,一個好朋友贊助了我機票錢孝凌,我也在沒有找到北京住處的情況下方咆,就踏上了北京的航班(臨走的那天,B君說他也在北京蟀架,可以給我落腳瓣赂,當時那個感動),開始了我現(xiàn)在的工作片拍。
北京的旅程-開源之路
起源
2010年10月15日煌集,我正式在C公司入職。E站是C公司的一個子站點捌省,用RubyOnRails 開發(fā)的苫纤。我一開始基于其上做開發(fā)。就這么做了一個月Ruby程序員纲缓,有一個事情就第一次改變了我的職業(yè)方向方面。
某天老大突然說,你不是以前用Java做過搜索么色徘,公司主站點的搜索就交由你做吧恭金。當時公司的搜索是外包給一家專門的公司做的。我自然很樂意的接受了褂策。
后面經(jīng)過一個月的開發(fā)横腿,也就是2010年12月中旬時候,第一個版本上線了斤寂。當然這個版本可以說超級簡單耿焊,就是用Lucene搭建了一個單機版本的搜索服務。老大很開心遍搞,還請我們?nèi)タ戳俗屪訌楋w罗侯。
Web/ORM/ODM 一站式開發(fā)框架
因為我之前做過一段時間的Ruby程序員,一對比溪猿,我發(fā)現(xiàn)钩杰,Java的Web框架都太不好用了,Java的ORM框架也不好用诊县,Java 的MongoDB Client 也不好用讲弄。于是我決定開發(fā)一套一站式Web框架。
正好除了搜索的任務以外依痊,公司希望做一個全站通用的標簽系統(tǒng)避除。當時在選型上,老大說用Spring,我當時說瓶摆,給我點時間凉逛,我自己開發(fā)一套開發(fā)框架出來,老大說群井,你有信心做好么鱼炒,我說有。老大給予了肯定的答案蝌借。
于是昔瞧,2011年的有一段時間,每天早上六點我準時起來菩佑,光著膀子開始寫代碼(這個可以推測是夏天了)自晰。寫了一個Web框架,一個ORM框架稍坯,一個MongoDB的 ODM酬荞。 后面我問老大,名字叫什么好瞧哟,老大說混巧,就叫ServiceFramework。于是我便把Web框架叫做 ServiceFramework,ORM框架叫做 ActiveORM,MongoDB的 ODM叫MongoMongo勤揩。經(jīng)過公司許可開源了出去咧党。
相關介紹參考:
http://allwefantasy.iteye.com/blog/1631522
http://www.iteye.com/news/25793
項目地址:https://github.com/allwefantasy/ServiceFramework
從2011年開始,我一直在優(yōu)化這個項目,到現(xiàn)在已經(jīng)四年了陨亡。不過開源版本因為工作緣故傍衡,一直沒有更多精力維護,并且無法進行推廣负蠕。但是內(nèi)部版本卻獲得長了長足的發(fā)展蛙埂,作為一個針對API服務開發(fā)的框架,除了易用性以外遮糖,我一直重點做的是可運維绣的。目前我所在的數(shù)據(jù)部門,已經(jīng)完全使用了這套框架欲账。
關于可運維屡江,框架自身可以做到的:
- 接口 QPS 監(jiān)控
- 接口平均響應耗時監(jiān)控
- 接口調(diào)用量(如果是http的話,則是各種狀態(tài)碼統(tǒng)計)
- 內(nèi)置HTTP接口敬惦,外部可通過該接口獲取以上的數(shù)據(jù)
同時盼理,框架日志信息輸出默認包括:
- http請求url
- 整個請求耗時
- 數(shù)據(jù)庫耗時(如果有)
- 響應狀態(tài)碼
還有一個比較核心的功能是,服務降級限流俄删。
ServiceFramework主要面向后端服務,如果沒有自我保護機制,系統(tǒng)很容易過載而不可用畴椰。經(jīng)過一定的容量規(guī)劃臊诊,或者通過對接口調(diào)用平均響應耗時的監(jiān)控, 我們可以動態(tài)調(diào)整 ServiceFramework 的QPS限制斜脂,從而達到保護系統(tǒng)的目的抓艳。
這里其實還有一個重點是,傳統(tǒng)的方式是帚戳,容器包含應用玷或,比如開發(fā)好的代碼打成war包放到tomcat等容器中。新框架的方式是應用包含容器(內(nèi)嵌jetty),一個應用服務就是一個純粹的java application.
開發(fā)完這個框架后片任,我花了半個月時間完成了公司標簽系統(tǒng)的開發(fā)偏友。
索引系統(tǒng) (暫時未開源)
當時老大看上了一個叫ElasticSearch的搜索項目,類似Solr对供。不過那個時候ES還非常的初級位他,我當時年少氣盛,沒經(jīng)過任何測試就上線了产场,但是對其了解有限鹅髓,上線后問題不斷,當時索引量已經(jīng)頗大京景,光索引文件就達到百G窿冯。一開始我將原始數(shù)據(jù)也store進了索引,瞬間IO飆升确徙,服務直接掛掉了靡菇。接著我講原始文件剝離,只存儲索引文件米愿,但是發(fā)現(xiàn)也扛不住厦凤,服務經(jīng)常因為壓力大而沒有響應,因為ES有Failover功能育苟,如果發(fā)現(xiàn)有服務當?shù)袅私瞎模瓦M行分片副本遷移,直接把網(wǎng)絡帶寬占滿(那個時候路由器都是百M的)违柏。我就開始看代碼博烂,改代碼,但是不得要領漱竖。當時ES的社區(qū)遠不如現(xiàn)在活躍和成熟禽篱。
我后悔了,不應該沒有調(diào)研測試清楚就上線馍惹。而且當時一直困擾我的就是數(shù)據(jù)更新問題躺率。索引了后玛界,數(shù)據(jù)很快變更,我這邊必須想辦法得到通知悼吱。
于是我決定另起爐灶慎框,開發(fā)一個簡化版本的ES,使其完全能被自己掌控后添。經(jīng)過一個月的開發(fā)笨枯,第一個版本的我們稱之為CS的項目完成了。后面使用CS替換掉了ES遇西。服務再也不會輕易當?shù)袅恕?/p>
在一次ES的分享會上馅精,我分享了CS。蠻多人還是感興趣的粱檀。
CS作為一個分布式索引服務洲敢,特點有:
- 分布式架構(gòu)
- 支持索引數(shù)據(jù)分片
- 支持構(gòu)建離線全量索引過程中合并線上新增數(shù)據(jù)的機制
- 支持數(shù)據(jù)熱備
- 擁有一個剝離配套的統(tǒng)一查詢引擎
- 支持模塊化,組件化
關于這個項目的一些簡單介紹梧税,可參看:
http://pan.baidu.com/s/1i3qsoBF#path=%252FESCC%25233&render-type=list-view
中的 ES分享.pptx 文件
CS的核心是是查詢引擎和索引存儲剝離沦疾。一些高級功能,比如跨索引檢索第队,結(jié)果二次排序哮塞,摘要提取,獲取詳細內(nèi)容展示凳谦,都是作為模塊放在查詢引擎中忆畅。當然統(tǒng)一查詢引擎最核心的意義還是在于可以快速更新二次排序的引擎。當然這還需要有一些其他架構(gòu)做支撐尸执。
有新的模塊添加家凯,只需重啟查詢引擎,而不需要重啟索引存儲服務如失。索引文件重新打開是非常消耗CPU,IO的,常常會造成機器負載瞬間飆升绊诲,導致很多搜索維護人員輕易不敢重啟服務。在CS不存在這個問題褪贵。
12年的時候掂之,我終于有伙伴了,以前一直都是一個人孤軍奮戰(zhàn)脆丁。我稱為C君世舰。C君后來參與搜索的優(yōu)化。之前我因為對Lucene的一個誤解槽卫,導致排序效果一直很爛跟压,我一直不得要領。C君發(fā)現(xiàn)了這個問題歼培,瞬間搜索排序就正常了震蒋。后來C君開發(fā)了一套新的分詞引擎茸塞,現(xiàn)在已經(jīng)是一個知名的分詞套件了(可參考:https://github.com/NLPchina/ansj_seg)∨绾茫基于這套分詞引擎我們做了很多分析方面的工作翔横。
索引服務這個項目前前后后花了我四年多的時間《刘危現(xiàn)在策略層公用的組件已經(jīng)包括 SQL,JSON,URL params,Mutil-Index,數(shù)據(jù)網(wǎng)關等梗搅。后面我一直從事數(shù)據(jù)架構(gòu)和算法方面的專研時,索引服務也成為架構(gòu)中非常核心的一個服務效览。
北京的旅程-大數(shù)據(jù)架構(gòu)之路
到12年年末為止无切,應該說我做的大部分是項目層級的工作。13年年初丐枉,公司突然開始重視大數(shù)據(jù)了哆键。于是我們部門人員由原來的兩個人變成了五個人。加了兩個剛畢業(yè)的學生D君和E君以及一個算法工程師F君瘦锹。
F君也是對我影響很大的一個人籍嘹,讓我從此了解了機器學習,算法方面的東西弯院。我是一個比較容易受我認為優(yōu)秀的人影響的辱士,我會去學習他的思維,他的做事風格听绳。
C君則對大數(shù)據(jù)平臺有推動的作用颂碘。當時公司還沒有數(shù)據(jù)平臺,C君推動公司購買了五臺配置很低的服務器椅挣,直接放在了辦公地點头岔。然后我們一起搭建一個簡單的Hadoop集群。
關于大數(shù)據(jù)平臺鼠证,因為我經(jīng)歷過從無到有峡竣,到最后離不開它的整個過程,我形成了一套自己的觀點量九。而這些觀點适掰,我放在了一次PPT分享里。這里可以提兩點:
大數(shù)據(jù)平臺(hadoop/spark)娩鹉,真的不要被‘大數(shù)據(jù)’這個詞給嚇到了攻谁。它大數(shù)據(jù)都可以處理,小數(shù)據(jù)當然是小菜一碟弯予。本質(zhì)上大數(shù)據(jù)平臺是一種解決問題的范式戚宦,一個通用的分布式計算存儲平臺。想象一下锈嫩,把一個文件丟進平臺里受楼,然后在Web上寫個SQL就可以從各個維度分析這個文件里的數(shù)據(jù)了垦搬。整個過程可能只要花你幾分鐘,這比你花半天寫個單機程序統(tǒng)計來的快吧艳汽。SQL一不小心寫多了猴贰,設置成定時,就成BI報表了河狐。
大數(shù)據(jù)平臺搭建維護很貴吧米绕?真不貴。大數(shù)據(jù)平臺誰說了一定要大馋艺?一定要幾百上千臺機器了栅干?沒人說一定要這樣子吧。我們當時5臺機器捐祠,在百萬數(shù)據(jù)集就能運行的很好了碱鳞。什么樣的數(shù)據(jù)量,使用什么規(guī)模的集群踱蛀。當你的價值體現(xiàn)出來了窿给,公司自然也會毫不猶豫的給你加機器了。
我們當時完成的第一個項目是EDM率拒,郵件精準投遞崩泡。當然這個項目的前提是需要對人有一個畫像。于是我們幾個人加上產(chǎn)品頭腦風暴了好長一段時間俏橘,人工定義了上百個屬性允华,加上一個由詞構(gòu)成的屬性集合(14000維度),得到了對人的維度表征寥掐。郵件的話則直接使用14000維的詞特征表示靴寂。
假設人的特征集合是A,郵件的特征集合是B,目標值為0或者1
0 表示不會打開郵件
-
1 表示會打開郵件
f(A,B) => 0|1
典型的一個二元分類或者邏輯回歸問題。
做完后郵件打開率提升還是很顯著的召耘。當時我們想盡辦法推測出用戶的年齡百炬,技能,職位等各種信息污它。有一些屬性的預測取得了相當不錯的效果剖踊,比如用戶年齡,我們拿同事的賬號進行年齡預測衫贬,上下浮動不超過2歲德澈。
但做完這項目后C君,F君相繼離開了,但這個是我數(shù)據(jù)道路上的一個開端固惯。13年年中梆造,來了K君。K君之前是某大型視頻網(wǎng)站的數(shù)據(jù)部門負責人葬毫。應該說镇辉,通往數(shù)據(jù)道路康莊大道由此完全打開屡穗。此時公司戰(zhàn)略上也開始支持數(shù)據(jù)部門,人員迅速擴充到15人左右忽肛,包括數(shù)據(jù)分析村砂,開發(fā),算法屹逛。不過實習生占了很大一部分础废,服務器方面,新采購的單臺都至少24+核煎源,32+G 內(nèi)存色迂。
13年到14年是一段非常辛苦的路香缺。在這兩年我實現(xiàn)了快速的成長手销,開始了大數(shù)據(jù)平臺架構(gòu)之路,同時也投入了相當一部分時間在機器學習和數(shù)據(jù)研究之上图张。
應該說锋拖,公司的數(shù)據(jù)平臺是完全從0開始的,我和K君對整個平臺做了比較詳細的規(guī)劃祸轮。
第一步推動公司進一步擴充了集群兽埃。我們也開始了自己的第一個目標,構(gòu)建公司自己的BI系統(tǒng)适袜。
K君親自制定了數(shù)據(jù)上報格式規(guī)范柄错。我則基于Hive使用其SerDer機制開發(fā)了一套數(shù)據(jù)格式解析器。支持通過JSon格式文本描述日志格式苦酱,然后自動映射到Hive表中售貌。這樣新來一個格式的數(shù)據(jù),你只要填寫一個json格式的描述文件疫萤,就能使用Hive直接進行SQL查詢颂跨。
另外指導一個實習生開發(fā)了日志接受服務。同時L君則改寫了阿里開源的一個宙斯平臺扯饶『阆鳎基于該平臺,可以直接在Web界面管理和調(diào)試Hive/MapReduce任務尾序,并且設置調(diào)度任務钓丰。
完成了這些工作,我們構(gòu)建起了數(shù)據(jù)分析平臺的雛形每币。在宙斯添加大量的SQL統(tǒng)計腳本携丁,計算結(jié)果導入到MySQL中,然后在Web端展示脯爪,完成了BI報表的任務则北。當然這只是一個離線計算平臺矿微,真正和應用平臺打通,形成完善的數(shù)據(jù)流入流出尚揣,需要做的工作還太多涌矢。
從那個時候起,一直到2014年11月快骗,我們終于完整的構(gòu)建了一個數(shù)據(jù)支撐平臺娜庇。
Hadoop/Spark/HBase 體系,支撐BI,數(shù)據(jù)離線分析方篮,推薦協(xié)同計算等
分布式索引服務名秀,支撐搜索,數(shù)據(jù)平臺供查詢數(shù)據(jù)的存儲
統(tǒng)一查詢引擎藕溅,為數(shù)據(jù)產(chǎn)品提供統(tǒng)一的查詢接口
內(nèi)容網(wǎng)關+數(shù)據(jù)網(wǎng)關+上報匕得,打通產(chǎn)品到數(shù)據(jù)平臺的入口。
分布式緩存體系(Redis) 巾表,可支持推薦系統(tǒng)汁掠,數(shù)據(jù)網(wǎng)關等產(chǎn)品
初步的服務監(jiān)控體系 (參看:https://code.csdn.net/allwefantasy/platform 的介紹)
推薦系統(tǒng),支持相關內(nèi)容推薦集币,用戶個性化推薦考阱,公共隊列展示,底層完全基于Redis實現(xiàn)鞠苟。這里有個給兄弟公司介紹的一個PPT(http://vdisk.weibo.com/s/HZFjdG-haPc)
配置與發(fā)布系統(tǒng)(運維相關)
基本上在這個過程中是去數(shù)據(jù)庫化的乞榨。HBase做數(shù)據(jù)存儲,分布式索引服務則將數(shù)據(jù)進行索引当娱,支撐復雜查詢吃既,統(tǒng)一查詢引擎則以一致的接口對外提供查詢服務。
關于這兩年做的架構(gòu)趾访,我未來專門寫了一篇文章進行解析态秧。
平臺是你順利開張其他工作一個很重要的基礎設施。當你有了一個完善扼鞋,易于擴展的平臺申鱼,你的工作會越來越少,新添加的東西會越來越輕量云头。你會發(fā)現(xiàn)捐友,啊,原來這個都已經(jīng)是被平臺囊括了溃槐,啊匣砖,只是加個模塊嵌入進去就完事了。
后續(xù)談到的機器學習,很早之前其實我也接觸過猴鲫,搞個SVM lib弄弄对人,都是C的,單機的拂共,生成個個是數(shù)據(jù)都費事牺弄,更別說后面的訓練跑了。有了平臺后宜狐,真的就看你的自己的聰明才智了势告,你更容易獲得你想要的數(shù)據(jù),你更方便將數(shù)據(jù)轉(zhuǎn)化為你需要的格式抚恒,你更容易快速看到你的算法在實際數(shù)據(jù)集上的效果咱台。
舉個簡單例子,我們做了一個智能問答的項目俭驮,在現(xiàn)有平臺上做回溺,只花了兩天多時間。如果沒有平臺表鳍,我智能呵呵了馅而,一個禮拜都不一定能做順暢了。
北京的旅程-機器學習之路
2014年開始基于Yarn平臺引入Spark譬圣。因為內(nèi)部使用的是CDH4.4.0 版本的Yarn,Spark默認支持有點問題雄坪,所以必須自己下載源碼厘熟,修改一些地方才能編譯通過。Spark 平臺是對數(shù)據(jù)分析師维哈,算法工程師們的恩賜绳姨。我之前做一個數(shù)據(jù)調(diào)查,或者是為了產(chǎn)生一個訓練文件給算法用阔挠,可是頗費周折飘庄。Hadoop的開發(fā)部署發(fā)展了這么多年,其實還都是挺麻煩的购撼。用Spark幾行代碼就可以搞定跪削,而且本地IDE寫好,直接黏貼到spark-shell交互式運行迂求。
對于算法工程師而言碾盐,原先比如使用貝葉斯之類的,測試只能跑個小數(shù)據(jù)集揩局,不然很久都跑不完啊毫玖,跑一個禮拜沒出結(jié)果也是常事。有了Spark之后,測試的時候就直接在一定規(guī)模的數(shù)據(jù)上跑了付枫。真實的數(shù)據(jù)都在集群上烹玉,省去了要下載數(shù)據(jù)到本地的問題。要知道阐滩,目前大部分算法本質(zhì)上是通過大量的數(shù)據(jù)通過一些優(yōu)化算法提取出目標函數(shù)的參數(shù)春霍,算法的這種形態(tài)決定過了只有在一定規(guī)模的結(jié)果集上才能如實得到實際數(shù)據(jù)集上的效果。而Spark則很好的滿足了這種需求叶眉。
Scala 是我比較愿意接受的第三個語言址儒。第一個是Java,從大學開始就一直用著,第二個是Ruby衅疙,有過一段短暫Rails程序員的經(jīng)歷莲趣,也從中得到很多靈感。現(xiàn)在的話饱溢,基本是Scala,Java混合編程喧伞。Scala 確實能夠有效的提高編程效率,而且可以和Java無縫操作绩郎。在公司內(nèi)部系統(tǒng)中潘鲫,基本上都是混合著用的。
程序員再也不應該僅僅是寫代碼讓服務跑起來或者設計一個架構(gòu)做到良好的擴展性肋杖,這些工作本質(zhì)上是重復性的工作溉仑,你很難做到和別人不一樣,所以才會有碼農(nóng)状植,你只是壘代碼浊竟。隨著計算能力的提高,以及機器學習的發(fā)展津畸,程序員的目標應該更加高尚振定,我怎么才能讓你在茫茫人海中找到多看了你一眼的人?
前面我提到肉拓,在做架構(gòu)的過程中后频,我對數(shù)據(jù)分析和機器學習也非常感興趣,期間也做了一些成果暖途。雖然主要精力還是在架構(gòu)上卑惜,但經(jīng)常會抽出時間做相關的研究。
新詞發(fā)現(xiàn)是一個非常有意思的領域丧肴,用途非常多残揉。譬如可以構(gòu)建垂直領域詞庫,自動發(fā)現(xiàn)新熱門詞匯芋浮。詞庫的重要性我不用強調(diào)了抱环】强欤基于Spark強大的計算能力,我直接對200萬+ 的博文進行了分析镇草,得到大概八萬詞眶痰,包含 中文,英文梯啤,中英文混合詞竖伯。通過凝固度,自由度因宇,詞頻七婴,idf,以及重合子串(比如 c1c2c3..cN c2c3..cN-1 這種形態(tài)的 我們認為是重合子串,如果詞頻一樣察滑,則都過濾掉打厘,否則留詞頻高的)五個維度進行閾值設置和過濾。事實上贺辰,中間結(jié)果可以到幾百億户盯,一個不小心就可以把Spark跑死,但是也在這個過程中慢慢對Spark有了更深的理解饲化。 最終效果還是不錯的莽鸭,現(xiàn)在它已經(jīng)作為我們的基礎詞庫了。
算法自然是參考論文的吃靠,但我感觸比較深的是硫眨,通常某篇論文只會在一個視角去focus 某件事情,所以你需要參考多篇撩笆,從不同角度去理解這件事情的解決方式捺球,最后通過實驗綜合,得到一個更好解決方案夕冲。我參考了兩篇論文,比如凝固度裂逐,自由度是出自一篇論文歹鱼,而重合子串則來自另外一篇論文,然后自己觀察實際數(shù)據(jù)卜高,添加了很多規(guī)則弥姻,才得到最后的結(jié)果。
新詞發(fā)現(xiàn)這個我足足做了兩到三個禮拜掺涛,能有這么多時間focus在這件事情確實不容易庭敦。在公司,有太多的工作和新的想法需要去實施薪缆,尤其是公司在快速的轉(zhuǎn)型或者上升期。我業(yè)余時間雖然不加班荠雕,但是我常常會在腦海里把系統(tǒng)架構(gòu)方面的東西不斷排練驾中,就像大腦是個虛擬機,模擬器嚼锄,一整套處理流程都會在大腦里事先跑起來,這對自己掌握某個系統(tǒng)蔽豺,或者是對全局的掌控非常重要区丑。
一說到算法,大概很多人心里就是想著修陡,恩沧侥,我把數(shù)據(jù)轉(zhuǎn)化為算法需要的格式,然后丟給現(xiàn)成的算法跑魄鸦,跑著就出結(jié)果宴杀,或者出模型,然后反復嘗試号杏,直到得到你認為能接受的或者最優(yōu)的結(jié)果婴氮。我一開始也是這么想的,可是如果你真的做這件事情盾致,就發(fā)現(xiàn)完全不是那樣子啊主经,需要注意的細節(jié)太多了。
新詞發(fā)現(xiàn)沒有現(xiàn)成的工具包庭惜,所以完全自己寫了罩驻。第一步,你要獲取語料护赊。這容易惠遏,基于現(xiàn)有的平臺,我從我們資源中心挑出了200萬篇文章id骏啰,然后根據(jù)id到數(shù)據(jù)網(wǎng)關獲取title,body字段节吮。這個基于現(xiàn)有的平臺,也就一個SQL + 幾行Scala代碼就搞定的事情判耕。
SQL 其實就是用Hive 生成一個200萬博文id列表透绩。 Scala 代碼看起來像這個樣子
sc.textFile("/hdfs-upload-dir/20140904-114357-result.txt",30).flatMap{f=>
val Array(id,name,skill) = f.split("\t")
getFromUrl(id,"blog","title,body")
}.filter(f=> f.length > 100 ).saveAsTextFile("/output/william/newwords/articles")
因為我們的新詞發(fā)現(xiàn)是沒有詞典的,需要枚舉所有組合壁熄,然后通過一定的規(guī)則判定這是不是一個詞帚豪。比如 ‘我是天才’,就這四個字草丧,
組合有狸臣,‘我是’,‘我是天’昌执,‘我是天才’烛亦,‘是天’诈泼,‘是天才’,‘天才’ 此洲。你想想厂汗,200萬篇文章,這種組合得多夸張呜师,問題是你還要接著給這些組合做計算呢娶桦。這個算法可沒告訴你怎么處理的,你只能自己去想辦法汁汗≈云瑁看到了,真正你做算法的過程中知牌,不只是實現(xiàn)祈争,你需要面對的問題特別多,我是怎么做的呢角寸?
- 將所有html標簽替換成空格菩混,通過小空格切分后我們就能得到無數(shù)的小文本塊,然后我們就能做詞枚舉了
- 一個詞最長不能超過5個字
- 將中文扁藕,中英文沮峡,英文分開來做
- 將一些特殊字符 類似‘!¥……()+{}【】的呀啊阿哎吧和與兮呃唄咚咦喏啐喔唷嗬嗯噯你們我他她這是由于’ 這些不可能成詞的字符先去掉
這樣亿柑,詞集合就小多了邢疙。 接著就是按論文里的規(guī)則做計算了,比如算詞的凝固度望薄,算重合子串疟游。這里面還會遇到很多性能,或者內(nèi)存的坑痕支,比如Spark里的groupByKey,reduceByKey颁虐。 我一開始省事,用了groupByKey,歇菜了卧须,內(nèi)存直接爆了聪廉,為啥,你要去研究groupByKey到底是怎么實現(xiàn)的故慈,一個詞出現(xiàn)幾十萬次,幾百萬次都很正常啊框全,groupByKey受不了這種情況察绷。所以你得用reduceByKey。
很好津辩,實現(xiàn)了算法后得到了結(jié)果拆撼,可人家沒告訴你容劳,他貼出來的結(jié)果都是好看的,那是因為他是按頻次排的闸度,但如果你拉到最后看竭贩,結(jié)果就不太好看了。這個時候你就需要觀察數(shù)據(jù)了莺禁,然后提出新的規(guī)則留量,比如最后得到的中文詞結(jié)果,我用了下面的規(guī)則過濾了下
f._1.contains("和")||
f._1.contains("或")||
f._1.contains("就")||
f._1.contains("將")||
f._1.contains("是")||
f._1.contains("的")||
f._1.contains("為")||
f._1.contains("個")||
f._1.contains("到")||
f._1.contains("來")||
f._1.contains("種")||
f._1.contains("中")||
f._1.contains("length")||
f._1.contains("tmp")||
f._1.contains("void")||
f._1.contains("如")||
f._1.endsWith(":")||
f._1.endsWith("amp")||
f._1.endsWith("[")||
f._1.endsWith("]")||
f._1.endsWith("’")||
f._1.split("\\s+")(0) == "if" ||
f._1.split("\\s+")(0) == "for"||
上面的規(guī)則是什么意思呢哟冬?凡是詞里面包含‘或’的楼熄,或者'就'的或者上面羅列的,我都認為這個詞是沒有意義的浩峡,經(jīng)過這個簡單規(guī)則一過濾可岂,效果好非常多,很多沒什么意義的生活詞翰灾,或者不成詞的詞就被去掉了缕粹。中文,英文纸淮,中英文混合平斩,我都加了很多這種規(guī)則,最終才過濾出了八萬計算機詞匯萎馅。
在多分類的算法中双戳,貝葉斯和SVM的效果是相當不錯的,Spark中樸素貝葉斯的實現(xiàn)基于該論文: http://t.cn/RPkPkJq 糜芳,我看了一遍飒货,在我的數(shù)據(jù)集上跑的效果并不好。我修改了論文中 p(t|c) 的公式 為 p(t|c) = 出現(xiàn)t的c分類下的文章數(shù)/c分類下得所有文章數(shù) 對于t|d=0的情況不參與計算峭竣。然后舍棄采用Log將乘除轉(zhuǎn)化為加減塘辅。分類效果得到明顯提高。
我把它應用在了代碼篇的語言判斷上皆撩。給我一段代碼扣墩,我告訴你這是什么語言寫的。一開始識別率就達到70%左右扛吞,后面通過提高維度呻惕,將代碼片高維表示后(65萬),準確率提升到了85%滥比⊙谴啵總體而言,貝葉斯和SVM后面有人提出了各種改良盲泛,但是最后是改良了還是改差了濒持,還得看具體數(shù)據(jù)键耕,你需要有調(diào)整他們的能力。
再說一個應該說非常具有實際意義的一個算法:職位和簡歷匹配度算法柑营。當然設計的是為了招聘研發(fā)屈雄,所以基調(diào)就是以技能模型為主,提出一套完整匹配度算法官套。效果不錯酒奶。之后的研究人員基于我的算法,添加了職位方向等因子虏杰,使得效果更進一步讥蟆。這套系統(tǒng)會成為后續(xù)招聘領域比較重要的基礎。
人生第一次跳槽
在上一家公司工作了五年之后(2015年8月)纺阔,我終于跳槽了瘸彤。當時老板(我們老板是一個非常優(yōu)秀的老板)請我吃飯的時候,問我為啥跳槽笛钝,我說我想開始做些事業(yè)质况。我能呆一家公司呆五年,說明老東家是真好玻靡。
我到了L公司之后结榄,初期主要是實時計算這塊。實時計算能做的事情還是非常多的囤捻。這讓我后續(xù)以Spark Streaming 為起點臼朗,深入研究Spark 內(nèi)部源碼做好了鋪墊。
此時我除了負責一個應用開發(fā)團隊蝎土,同時還負責內(nèi)部的機器學習團隊视哑。然而我是一個很懶的人,不太適合帶團隊誊涯,我覺得我需要太多的時間投入到技術上去挡毅,去專研。所以團隊發(fā)展不足暴构,這也讓自己很愧疚跪呈。然而只要和我工作過的人,我一定會讓他們有技術上的收獲取逾。和我一起共事的同事有的去了百度耗绿,有的去了滴滴,大部分都還在互聯(lián)網(wǎng)公司砾隅。有一次吃飯的時候缭乘,他們有人說,雖然我很嚴苛,但是確實給他帶來了收獲堕绩。聽到這一點,我還是很開心的邑时。技術人員應該以技術為紐帶奴紧,互相幫助對方去提升。
這次跳槽唯一的遺憾之處在于晶丘,8月3號辦完離職黍氮,8月4號就開工上班,當天就加班了浅浮,ORZ沫浆。
Spark 的再相會
經(jīng)過八個月業(yè)余時間(周末加上工作日夜晚)的努力,我想要的產(chǎn)品原型終于做成了滚秩。然而終究是計劃有調(diào)整专执,在主動和一些CTO,資深技術人員,業(yè)已創(chuàng)業(yè)成功的人聊郁油,加上碰了一些壁之后本股,我打算放慢些節(jié)奏。似乎光有個原型是不足以打動投資人的桐腌。
這個時候拄显,Spark 對我的吸引力突然無限超越了事業(yè)對我的吸引力,所以三個月時間我寫了20幾篇Spark相關的文章案站,并且推動部門上了很多Spark Streaming相關的應用躬审。
在此期間,我大量閱讀源碼蟆盐,并且修正了不少在特地情況下Spark會工作不正常的錯誤承边,同時做了一些增強。這些工作在Spark Streaming 的玫瑰與刺 有所提及舱禽。同時還提出了一個 流式計算動態(tài)資源調(diào)整算法
2016年3月份開始炒刁,我慢慢將工作重心放在多維查詢上,大體朝著SparkES 多維分析引擎設計 努力誊稚。5月份左右開源了StreamingPro項目翔始,涵蓋了批處理,流式計算里伯,交互式查詢等多項功能城瞎。其實原理也簡單,基于之前開源的ServiceframeworkDispatcher 實現(xiàn)配置化疾瓮,使用以前開發(fā)的Serviceframework框架嵌入到Spark Driver 中脖镀,這樣就可以接管Spark UI的工作,提供新的交互接口狼电。
技術的輪回
最近基于Spark Streaming + ElasticSearch 做數(shù)據(jù)的日志分析蜒灰。還記得我12年(也可能是11年)引入ES做搜索弦蹂,那個時候簡直被虐死,所以開發(fā)了一套自己的索引系統(tǒng)强窖。沒想到四年后又遇到它了凸椿,而這個時候不在是在搜索領域,而是在大數(shù)據(jù)日志分析領域翅溺。人和技術脑漫,都存在某種輪回。