我在阿里的第一年

寫在前面

  從2018年5月開始收到菜鳥offer實習到本科畢業,我不小心實習了一年。這一年get到了很多東西,也有一些想法,這篇文章本來早就該寫了,因爲自己“忙”,就一直沒去把這篇總結落實下來。今天實在忍不住了,開始動身欲寫在菜鳥實習一年的所思所得。

  在我實習的時候,我的老闆就問過我實習了這麼久覺得自己得到了哪些東西,自己還欠缺哪些東西,有沒有認真去思考過。當時的我支支吾吾也沒能對這位負責的老闆說上個所以然。這篇文章主要就談一談我做了些什麼,得到了些什麼,還欠缺些什麼。

 

做了什麼

  說來慚愧,感覺自己實習的一年時間還是很鬆散的,這個鬆散不是說自己做的事情少,而是做的事沒有去積極思考爲什麼去做,帶來的價值是什麼,不做可能會導致什麼後果。更多時候自己只是一個任務的執行者,關注了太多如何去執行,視野比較窄。先來簡單羅列下做了哪些項目(已脫敏處理):

  某項目1(脫敏)

  剛入職的時候,團隊在做一個已經做了兩年的to B項目,給我們的合作伙伴進行賦能,爲了數據安全此處這個項目名稱不表了。某次有幸能和團隊年輕有爲的大老闆在一起溝通,問到這個項目到底作用是什麼,我們這樣做下去的意義的時候,大老闆說了很多這個項目的重要意義。比較遺憾的是後來組織架構調整,我們這一塊不再做to B業務,轉向做to C業務,這個項目就轉交給其他團隊了。以自己的一點愚見,當時公司的方針一直都是儘可能好地去賦能我們的合作伙伴。然而我們做什麼,合作伙伴抄什麼。我們產出的很多東西合作伙伴也不去用,轉而自己去開發一套自己的東西。當時我們和合作伙伴合作,他們的數據都不怎麼想給我們。可以看出合作伙伴不想依託我們,我們也很難建立自己在行業的壁壘,更別提在這上面進行盈利了。現在團隊開始做起了to C業務,也不知道之前那些東西咋樣了。

  在這個項目中,我們的目標根本上是爲了讓合作伙伴提效降本,因此需要利用離線計算/實時計算產出大量的報表頁面,供合作伙伴進行監控,同時提供這些數據的明細下載和彙總下載。

  自己作爲一個實習生,是沒有數據權限的,劃了一段時間水之後,只能開始寫一些react頁面。當時團隊有數據下載並且生成excel的需求,但是大家各用各的解決方案,比較不統一。另一方面,我大致算了一下,一個excel會在內存中佔用幾十M乃至上百M,而且這樣的excel生成並且寫入OSS雲端磁盤之後就再也用不到了。《深入理解java虛擬機》中有一句話,大致意思是JVM不喜歡朝生夕拾的大對象。因爲大對象會直接進入JVM的老年代,使得JVM的Full GC會很頻繁,讓應用性能變得很糟。之後我開始查找excel相關的文檔,嘗試解決這個問題。後來我把這個問題解決了,並且抽象了一套異步從離線表裏多線程讀取數據,然後在內存中生成excel,寫入到OSS提供下載的組件。使得團隊之前寫異步生成excel的代碼行從數百行降到了幾十行,並且生成excel的過程中佔用的內存大小從幾十M上百M降爲了固定的2M。

  某項目2(脫敏)

  大約在八月左右,我迎來了我參與的第一個雙十一項目。沒錯,這個項目還是給合作伙伴賦能,一個偏監控的項目,感謝前端夥伴,這個項目看起來非常非常炫酷。最終這個項目出現在了上海國際進口博覽會上,受到了國家領導人的參觀。

  前面提到了,這是一個偏監控的項目,在雙十一場景下,數據量必然會非常的大。數據量大怎麼辦?第一反應肯定是分庫分表啊,按照一個列進行分庫分表,把請求打散到不同庫的不同表上。但是這種方案有一個問題,需要有一個合理的分庫分表鍵,這個分庫分表鍵一般是userId。很遺憾,我們沒有合適的分庫分表鍵,這種方案不適用,但是又必須保證查詢的實時性。然而這個問題在阿里強大的技術生態面前不是問題,阿里雲對外提供了一個支持海量數據實時高併發的在線分析型數據庫ads(也叫garuda),能提供千億數據規模的查詢和亞秒級別的響應。像mysql這樣的OLTP系統一般是行存儲,同時加上了B-tree索引,在select多列的情況下很很好。而OLAP系統一般是列存儲,在select列比較少的時候優勢就體現出來了,因爲基於列存會使得數據有更高的壓縮比。ads則是將兩者進行了混合,採用了行列混存,在列存的基礎上,將關係比較緊密的列放在一起,構成了行組。我們最終採用了ads來進行這種場景的數據存儲。

  這是我的第一個用Spring boot寫的項目...之前沒接觸過這個東西,當時經常弄得自己一臉蒙圈。不過自己負責那部分邏輯比較簡單,也算是按時完成了這個項目。

  自助取數工具

  前面提到了,我們經常在做一些產出數據/產出報表的事情,我們就在想能不能把這件事讓運營去做,讓開發去做一些對系統建設更重要的事情。於是這個項目產生了,讓運營去自助取數據,自助去產出報表。

  這是我第一個從0開始使用阿里技術棧搭建前端+後端的一個項目,當時我負責的一塊遇到了一個問題。我們既然要讓運營去取數,我們不可能把我們的所有數據模型都暴露在運營面前。因此我們要先把數據模型進行一次封裝,當時師兄是想提供使用sql去產出一層數據,然後讓運營去基於這層數據取數的能力。那這樣就出現了一個問題,比如我的sql是select a.c1, a.c2, a.c3, b.c4, b.c5 from ((select * from table1 where c6 > 1) as a join (select * from table2 where c7 > 2) as b),我該如何解析出我最外層select出來的數據來源於table1還是table2?這還只是一個基礎的場景,如果這個sql還有多層join關係,帶上錯綜複雜的where關係和group by操作,那將會更噁心。

  當時我調研了阿里鏈接池druid中的sql parser模塊,理解了druid中將sql拆分出來的抽象語法樹每一塊的含義。有了druid的sql parser解析出了sql對應的抽象語法樹,我就不用去涉及編譯原理了(本科的編譯原理簡直是我的痛)。但是這裏還有一個問題,druid的sql parser解析出來的是靜態的抽象語法樹,也就是對於sql:select c1, c2, c3, c4, c5 from ((select * from table1) as a join (select * from table2) as b) 我不知道c1、c2、c3、c4、c5各自來自於哪一張表,還需要通過元數據去看table1和table2有哪些列,然後通過動態規劃去計算列和表之間的關係。

  很開心這個問題最終自己解決了,但是一方面當時那版代碼寫得很爛,師兄幫我review了一遍又一遍;另一方面,我當時爲解決這個動態解析sql的問題花了挺大精力,師兄也在引導我如果開發成本比較高,應該反過來去思考,這樣花大精力去做這件事是不是真的有價值,有沒有一些替代方案,而不是低着頭去把它硬搞完。

  規則引擎

  阿里有一個價值觀叫做“擁抱變化”  ,是的,我體驗到了。我們團隊從to B業務調整到了to C業務,開始接手別人之前的一塊老系統,當起了有緣人。爲了系統穩定性和可維護性,我們開始進行了老系統重構。我們做的業務域偏平臺方向,更多的是提供一個底層能力,給業務賦能好。這就涉及到一個問題,很多時候我們根據不同的業務場景需要調其他團隊不同的接口來判斷要不要執行一些邏輯、執行什麼邏輯。這種判斷邏輯不可能寫在我們的平臺系統裏面,因爲那樣的話我們的平臺系統會包含大量的臨時代碼,代碼腐化速度會很快,又得等待下一位有緣人來重構我們的代碼了。即使是寫在業務團隊的系統裏,他們每有一個新邏輯就需要新寫代碼、部署系統,這是比較不合理的,對業務團隊而言也是不易於去維護的。於是我們準備開放一個平臺,讓其他團隊能可視化地配置要執行哪些邏輯,調用哪些其他團隊的接口,這就是規則引擎。

  這裏規則引擎的本質就是可視化拖拽式編程,將可視化拖拽式編程的結果生成一個groovy腳本,將groovy腳本動態編譯爲class字節碼,在系統當前的JVM中進行執行。

  過期積分定時清理

  這個應該是我實習離職前做的最後一個事了。在所做的to C平臺中,有一塊積分相關的業務,這個積分對應了一個積分變更的明細表。這個域的積分是會過期的,如果這個積分明細中過期數據不刪除的話後續庫表數據量會越來越大,容易產生一些滿sql,因此需要進行定時積分清理。

  我在清理前大概算了下需要清理的數據量,高達8億行數據。要刪除這些數據的第一個問題在於如何去找到哪些數據該刪除;第二個問題在於刪除的時候由於涉及到數據庫磁盤IO的資源、數據庫鏈接、行鎖等的數據庫資源的限制,需要給刪除操作進行限速;第三個問題在於我們的系統都是分佈式的,如何去進行任務拆分使得所有機器都能參與進這個刪除任務,而不會出現單點問題。

  最後通過這個事利用公司的分佈式定時任務框架沉澱了一套從離線數據裏取數,進行任務拆分,分發給不同機器,然後按照一定邏輯在mysql中按照一定速率上限執行的邏輯框架。

  RPC

  是的,這個項目是離職後寫的...在職的時候看到公司的微服務觸動很大,對模塊之間的RPC很感興趣,很想知道他是如何實現的,於是一時衝動把擼一個簡易的RPC框架作爲了自己的畢設題目。

  當時抽空看了看公司低版本的RPC框架HSF(之所以是低版本,是因爲我忘記從git主幹拉最新代碼了...),那個版本的HSF實現比較簡單,自己又在那版HSF的基礎上再進行了簡化,但還是大致實現了數據接入、負載均衡、選址、序列化、協議編碼、數據傳輸、協議解碼、線程池調用、限流、反序列化、反射調用的一套RPC流程。

  當時簡單用2核的mac測了一下這一套流程的TPS,大約在35K左右,公司最新的RPC框架我沒記錯的話TPS大約在120K左右。因爲我看的是很老的代碼,後面還得看一下最新的代碼做了哪些優化。

  但是其實分析一下這一套RPC流程的耗時點就可以發現,其實耗時主要是發生在序列化和反序列化、網絡IO上。對於序列化和反序列化,hessian2、protobuf、kryo等序列化和反序列化方式都已經做得很好了;對於網絡IO,也有著名的異步的、事件驅動的網絡IO框架netty。其實用堆積木的方法來寫一個RPC也很簡單,而且也能提供不錯的TPS了。

得到了什麼

  技術

  說出來不怕笑話,自己一年前是一個連git、maven都不會用的人,也沒有一點安全生產的概念。當時git只會add、commit、push三連,要是什麼時候出現問題就開始犯懵。師兄第一次給我一個小需求的時候,我拿着git一頓操作,把遠程庫分支搞得一團亂。當時也不知道本地項目怎麼去啓動,好不容易push成功了,就開始往線上發代碼,想在線上搞測試。還好當時沒編譯通過,線上不讓發,不然完蛋了...後來自己針對性地學習了一下這些基本的工具,才慢慢開始真正上手。

  入職前自己可能計算機基礎理論體系還可以,對java也比較熟悉,分佈式理論也能說一點,但是感覺自己是開始工作挺長時間之後才把這些東西串起來,構建成一個體系:

  比如爲什麼使用緩存、爲什麼分庫分表、如何保證分佈式事務、爲什麼要用消息、爲什麼消息會出現重複、使用消息和RPC的區別等等這種問題都是在工作中才慢慢深入理解的。

  心態

  在入職菜鳥前,我以爲阿里系的都是在做純技術,挑戰很大。之後發現這的確是一家業務驅動的公司,大部分時候都是在寫業務代碼,會有種用技術做業務,都是CRUD,隨便cover的錯覺。後來自己的心態開始有了一些變化,發現想做好業務也很複雜,業務代碼面對的場景會更加多變、複雜性也會更高。軟件工程領域的六字真言,“低耦合,高內聚”,真的能做好嗎?進行領域劃分的時候真的能想清楚邊界嗎?設計數據庫字段的時候能做到考慮到所有場景的同時又不會讓數據庫字段看起來很臃腫嗎?寫業務代碼和寫技術代碼可能只是面對的問題不一樣,他們都需要學會分解問題、抽象問題、多維度思考問題。可能大多數時候只是自己把業務問題想的太簡單了。

欠缺些什麼

  技術深度

  感覺自己目前的技術深度還是欠缺很多,比如自己經常用的spring boot怎麼跑的,pandora boot怎麼利用不同類加載器來解決包衝突的,mybatis怎麼把接口映射爲對象的,保證數據強一致性的paxos是怎麼工作怎麼工程化的等等之類的問題,連着追問可能能問出很多相關的問題。

  作爲一個應屆生可能首先技術需要有一定的廣度,能夠解決需求,之後便是技術深度,能夠解決問題。

  業務思考

  自己實習的一年期間,大部分時候都只是一個執行者,去執行一件事情,大多數時候沒有想爲什麼要做這件事,不做這件事會怎麼樣。開發是寶貴的資源,不應該浪費在無意義的需求上,做的東西一定要有價值,不是爲了寫代碼而寫代碼。記得行易老師說過一句話,業務方想要給你提需求的時候一定要問他們,我晚上線一個月會怎樣,或者我不做這件事會怎樣。是的,應該推動業務方去思考業務的價值,同時自己也要明白一件事的價值,把有限的資源和精力進行最大化投資。

  看待問題的多面性

  某些時候自己拿到一個問題,需要去解決。可能自己沒有想清楚就直接上手做了,這就是沒想清楚這件事情,或者說沒有看清這件事的多面性。一個問題通常會有一個出現原因、一個解決之後的預期、以及一個外部環境。可能我強行把這個問題轉化爲解決後的預期,這個問題之後還是會出現。

  比如現在服務器磁盤滿了,我把老日誌刪掉,但是過個幾天服務器磁盤又滿了。這個時候就需要去看到這個問題出現的原因,是不是打印了一些不應該打印的東西,如果是,我把這些不應該打印的日誌去掉;如果不是,日誌沒有出現問題,那說明我預期的磁盤佔用增長速度不對,我的服務器磁盤太小的,光刪日誌解決不了問題,應該申請更大的了。又或者說,磁盤大小和日誌打印都沒問題,只是運營突然推了一個push消息,太多用戶突然涌進來了,把我們機器打滿了。這就是外部環境的問題,應該讓他下次推push和我們說一聲,我們好準備。

  這一點不只是一個方法論,更多的還需要靠積累的知識來進行實踐,瞭解得越多,看問題越透徹。

  做事的條理性

  在阿里很有很多事情同時在push你,有時候需要一件一件去close,有時候被其他人block住了,需要切換到去做其他事情。但無論如何,做這些事都一定要有條理性,有時需要列一個list,哪些事情close了,哪些還沒有,哪些被block住了,我可以去做一些其他的事。

  溝通能力

  首先,能不能把這件事情和別人說清楚直接取決於你對這件事到底理解得透徹不透徹,如果自己都理解不透徹,那就更不用談溝通了。第二,嘗試用一些結構化的語言,因果關係、遞進關係、承接關係等要用好。第三,和別人溝通的心態要放端正,我是來溝通的,不是來吵架的,不是來賣萌的,應該把自己的位置放得和對面一樣,哪怕自己被懟,也應該把自己的思路清晰地說出來。

  在大學的時候感覺自己做presentation也好,和別人扯淡也好,覺得自己還是可以講清楚一些事的。入職之後可能感覺周圍人title也好,年齡也好都完全碾壓我,溝通以及presentation都變得不那麼自信,生怕被懟。但是其實把自己的理念想清楚,講清楚,哪怕被懟了也不應該慌,努力好好溝通。當然,問題的關鍵在於把自己想表達的理念想清楚,將清楚。

 

2018/5/7 - 2019/5/10

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章