新東方APP技術架構演進, 分佈式系統架構經驗分享

今天的演講題目是「新東方APP技術架構演進, C端技術經驗分享」

做者:張建鑫, 曾任IBM高級軟件架構師, 滴滴高級技術專家, 現任新東方集團高級技術總監前端

古代東西方的思想家都產生過一個終極的追問,世界的本元究竟是什麼? 老子說,道生一,一輩子二,二生三,三生萬物,天道有常不以堯存不爲桀亡。孔子說朝聞道,夕死可矣,孔子把對道的研究從,對人與天然關係的天道,轉移到了研究君君臣臣父父子子的人道方向上。古希臘第一個哲學家泰勒斯說世界的本元是水,後來畢達哥拉斯回答說世界的本元是數字,古希臘哲人對道的研究始終聚焦在人與天然關係的天道方向上。對終極追問的不一樣思考和回答,衍生出了,東西方在文化價值觀,思考邏輯和作事方法等方面的巨大差別。mysql

咱們在企業裏工做,實際上也存在一個終極追問,就是你的終極用戶是誰?怎麼服務好終極用戶。我曾經在2B技術公司IBM工做過12年, 在2C技術公司滴滴工做過三年。 我深切感覺到,在這個問題上的不一樣回答,致使了傳統的IT技術公司和互聯網技術公司, 在工做價值觀,和工做方法等方面的不一樣。nginx

一般,B端技術重功能不重體驗,軟件客戶每一年續簽一次合同,軟件開發商能夠經過各類手段增長用戶遷移到其餘競爭對手的成本,深度綁架用戶,即便客戶對軟件有一些不滿意也會續簽合同。 而互聯網的C端我的用戶是典型的用腳投票,拋棄一個產品的時候,一聲再見都不會說。 所以互聯網產品技術的競爭是典型的贏者通吃,產品體驗稍有不一樣,短期內用戶就會流失到競爭對手那裏。因此互聯網產品技術極度關注用戶體驗,和用戶客訴。 IBM解決客戶的客訴流程冗長,有所謂的一線二線三線技術支持,解決一個客訴動輒數月之久。 可是互聯網C端技術須要時刻關注用戶客訴和線上事故,爭分奪秒的解決問題,甚至要求幾分鐘內就把問題解決掉。 因此如何避免和減小客訴, 如何快速處理線上故障,就成爲區別2B,2C技術公司不一樣點之一,對價值導向問題的不一樣回答,也產生了徹底不一樣的價值評估系,最簡單的就是如何去判斷一項具體工做的輕重緩急和重要程度。面試

我剛來新東方的時候, 個人團隊裏沒人關心客訴問題,沒有技術值班,上線流程很草率。 互聯網公司裏重要的技術方法到了IBM那裏,就可能變成過分設計,變成不重要的工做,但其實沒有毛病, 由於倆者的業務場景和最終用戶是徹底不一樣的。因此必定要認識清楚,咱們工做的end user是哪些人, 以及如何服務好最終用戶。 當最終用戶滿意時,咱們的工做天然就會被公司承認。因此我認爲不少事情不是技術問題,而是價值導向問題,價值導向對了,咱們的技術規劃,架構選型就天然作對了。我是被IBM培養出來的,但到了滴滴後,只要願意改變,同樣也能作好互聯網的技術工做。redis

在互聯網產生以前,最大的計算機系統就是銀行櫃員系統,用戶必須去銀行網點排隊辦業務,銀行網點人滿爲患,全部的交易都經過櫃員處理, 你們想一想看,這實際上就是經過人工排隊的消息隊列進行了削峯限流,最後全部交易都集中在一臺價值幾億人民幣的 IBM大型計算機裏, 在集中式的DB2或者Oracle數據庫裏完成交易。 今天互聯網電商的交易量要比銀行大的多,全部的系統都是分佈式系統了,與之前的集中式系統相比,分佈式系統最顯著的特色就是容易擴容,今天銀行的IT系統也都互聯網化了,大多數的銀行業務均可以足不出戶在家自助辦理了,因此咱們必須看一下什麼是分佈式系統算法

分佈式系統是由許多計算機集羣組成的,但對用戶而言,就像一臺計算機同樣,用戶感知不到背後的邏輯。分佈式系統最重要的理論是2002年被科學家證實的CAP理論
C是數據一致性, A是可用性, P是分區容錯性。 CAP三者之間是互相矛盾,互相影響的關係。sql

其中,最好理解的是A,A是可用性。 可用性存在兩個關鍵指標。
首先是「有限的時間內」,其次是「返回正常的結果」,若是用戶的操做請求返回的是400或者500錯誤,或者規定時間內沒有返回結果發生了超時,那就算是發生了一次不可用。因此並非說,只有發生了線上大規模事故,所有服務不可用纔是不可用,發生400,500錯誤或者請求超時都屬於不可用。數據庫

P是分區容錯性:當系統發生消息丟失或局部故障時,仍然能夠運行
在分佈式系統中,當一項數據只在一個節點中保存時,萬一放生故障,訪問不到該節點的數據,整個系統就是沒法容忍的。
若是這項數據複製到多個節點上,某個節點數據訪問不了時,系統仍然能夠從其餘節點上讀到數據,系統的容忍性就提升了。
可是多個數據副本又會帶來一致性問題。要保證一致性,每次寫操做就都要等待所有數據副本寫成功,而這種等待會損害系統的可用性。
總的來講就是,數據副本越多,分區容忍性就越高,但要複製更新的數據就越多,一致性就越差。因此CAP就是一種按下葫蘆,就起了瓢的感受。後端

C是數據一致性, 分佈式系統的數據一致,是指全部服務器節點在同一時間看到的數據是徹底同樣的。 若是成功更新一個數據項後,全部的服務器節點都能讀取到最新值,那麼這樣的系統就被認爲是強一致性的。系統若是不能在規定時間內達成數據一致,就必須在C和A之間作出選擇。注意規定時間內是很重要的。緩存

如今的系統都是分佈式系統了,P是不可能放棄的,但通常來說,架構設計要儘可能減小依賴,系統依賴的基礎架構組件和第三方系統越多,若是P太強了,整個系統的C和A,可能都會受到損害。 架構取捨更多的是在C和A之間作出選擇。而沒有分佈式的CA系統就是關係型數據庫,就是放棄了分佈式,放棄了分佈式的擴容能力。 
有些場景要求數據強一致,例如與錢有關的與訂單有關的系統,這種場景下,或者捨棄A,或者捨棄P。 關係型數據庫是強一致的CA系統, 
但若是mysql引入了從庫,就會在必定程度上損害數據一致性, 但同時換來了A可用性或者讀寫性能的提高。
而TIDB採用raft協議,數據保存在至少三個副本里,同時它要兼容mysql,實現數據的強一致性, 因此既然,TIDB引入了P,就只能在必定程度上要捨棄A,讀寫性能會相應下降。可是加強了分佈式的擴容能力,包括了存儲和算力的擴容。 因此CAP理論告訴咱們,全部便宜都想佔到是不可能的, 只能根據實際業務需求和價值判斷體系,作出取捨。

BASE理論是對CAP理論的延伸,是指基本可用、軟狀態、和最終一致性。基本可用, 好比在規定的1秒內熔斷了,沒有返回結果, 那咱們又重試了兩次,結果返回告終果,這個就是基本可用。 假如我重試了兩次後,仍是失敗了, 咱們作了一個降級處理,讓用戶仍然能夠繼續使用服務,這個也叫作基本可用。

最終一致性是指系統中的全部數據副本通過必定時間後,最終可以達到一致的狀態。最終一致性是弱一致性的特殊狀況。
新東方不一樣業務系統對數據一致性的要求都不同, 本質區別就是具體的業務能夠容忍在多長的時間限制內,達到最終的一致性。

FLP不可能原理, 請自行查找解釋,此定理告訴咱們,不要試圖設計一個可以容忍各類故障並保持一致的分佈式系統, 這是不可能的. 分佈式事務也永遠沒法實現單體應用級別的一致性。即便如paxos協議和raft協議也會出現沒法達成共識的狀況,只不過出現的可能性很低。因此說paxos是有效的一致性算法,但也不可能作到天衣無縫。

集團首席架構師 幺敬國老師在極客時間上作過zookeeper的系列專題講座, 對raft協議是專家,我純屬外行,你們有任何問題能夠請教他。

 

 

 

若是剝離掉具體的業務目標和產品目標,那咱們就會發現, 咱們C端技術工做的目標,其實正好就是分別對應前面講的CAP。可是同時知足三個要求是很是難的,只能根據具體業務場景進行取捨。 Tidb的開發商的名字叫PingCap就是一個頗有雄心壯志的名字,意在無限的同時逼近這三個目標。

如今C端系統都是分佈式的,捨棄P是不可能的,並且業務又會要求咱們必須保證系統的可用性,所以事實上咱們C端技術能捨棄的也只有規定時間內的數據一致性。
一般只要在數秒鐘甚至數分鐘,甚至1天后,能夠達到最終一致就是能夠接受的。 咱們犧牲了一致性,換來的就是A的大幅度提高,和性能的提高。

 

接下來咱們,結合APP的工做實踐分別講一下分佈式系統經常使用的基礎架構組件 

 

 

 

首先講一下緩存。剛纔講過了,數據拷貝越多, 數據一致性就越差,引入緩存必然會損害規定時間內的數據一致性,所以數據緩存時間一般不宜過久,持久化的緩存數據更是荒唐。Redis對外提供集中式的緩存服務, 只增長了一份臨時數據副本。 但Guavar是基於JAVA的本地緩存,每臺JAVA服務器在本地保存一份數據副本,會顯著損害整個分佈式系統的數據一致性,而且形成相關客訴。

除了數據一致性, 使用redis也會涉及到系統可用性問題。 Redis其實是一個CP系統。對於Redis, value越大,讀寫訪問的延遲就越大。使用緩存時,要避免使用大Value和大Key,不然會下降可用性。大值能夠採用序列化後壓縮的方法。 與大值相反的另外一個應用極端是, 大Key小Value,這種Key能夠經過MD5壓縮來避免。 一般來說redis的平均get請求應該是數十微秒級別的,這種高速緩存部署時要和應用服務在統一的IDC, 避免跨機房部署,由於跨IDC一般會有毫秒級的延遲,從而損害系統可用性,使用緩存的意義就不大了。

此外,Redis可使用pipeline提升批量訪問性能,能夠想見網絡請求數量會所以大幅度減小。

 

 

使用緩存時要思考如何提升緩存命中率,對應的就是如何減小緩存穿透率, 減小對第三方系統或者對數據庫的壓力。
理想狀態下,系統中的熱數據應該都存在緩存裏。 一個極端是壓測, 很差的壓測設計是,不停地,頻繁地,重複地,請求相同的測試用例,其實第一次就是預取, 數據變熱後, 壓測快的飛起,可是一到線上真實環境, 可能就不行了,由於線上沒有那麼多重複請求。但在真實業務場景下,能夠跟據用戶的真實的操做序列, 預測出來哪些數據將會很快會被用戶訪問到, 此時,咱們就能夠採用預先計算和預取數據的方法,在用戶後續操做發生時直接從緩存裏讀取數據。

此外,剛剛發生讀寫操做的數據,能夠認爲都是熱數據,均可以考慮預取到緩存。

下面這張圖是在剝離掉具體業務後的,APP使用緩存的架構方法。

首先講主動更新緩存,
首先第一個操做是須要更新數據的事務操做,能夠考慮主動更新緩存。對一致性要求高的業務,事務主動更新緩存時必須從數據庫主庫讀取數據,不然會由於數據庫主從延遲致使緩存數據和數據庫裏的不一致。 還有一種狀況,緩存的值是一個集合set,須要一次更新不少數據項,這種操做沒有原子性保障,就必須用事務保障,須要加鎖。因此主動更新緩存的方案是不夠嚴謹的,容易致使數據不一致。還有就是發數據更新消息,這時候數據變動MQ必須把全部信息都帶上, 典型的如binlog。 若是隻是通知一個變動事件,可能就會致使緩存數據和數據庫不一致。因此binglog多是最不容易致使一致性問題的方案。 但有時候我就是拿不到binlog怎麼辦, 並且嚴謹的方案顯然在技術上會更復雜,落地成本會更高。

我想說,不嚴謹的方式不必定就不能用, 時刻記住業務場景能夠彌補技術上的不足,架構設計時實用主義比完美主義更適用, 更能多快好省地解決業務問題。採用什麼方案,首先是要考慮業務場景是啥, 其次是要考慮,萬一出問題了後果是否可控,不要追求完美。特別強調,報名續班優惠的同窗,千萬不要這麼玩,若是非要這麼玩,出問題後果自負。

第6個操做是主動更新緩存, 緩存快過時時,發生讀操做,能夠考慮要主動讀取源數據,更新緩存,當第三方故障,致使數據源沒法讀取時,能夠主動延長緩存時間。 作一個降級處理,提升系統的可用性。

 

 

 

再講一下本地緩存Guava。比起集中式的redis緩存,本地緩存的副本更多了,數據一致性也就更差了。若是網關不採用特別的分發策略, 本地緩存時間建議要設置的很短,爲的是縮短各節點數據最終一致達成時間。

下面這張圖的右邊採用了一致性hash的負載均衡策略, 根據用戶請求散列,保證各個服務器上的緩存數據沒有交集,這樣就提高了數據一致性。但這樣作等於本身作了一個分佈式的redis,嚴格講,不可能比redis搞得好,可是好處就是,架構上減小了一層對redis的依賴,系統可用性提升,性能提升。

具體怎麼取捨,仍是要看業務的實際需求。不少數據庫調優的工做,最終變成了玄學。就是由於系統參數太多了。 基於CAP定理,你不可能什麼好處都獲得,顧此必然失彼。

 

 

 

其餘使用緩存的小竅門還有設置緩存時間時加一個隨機值,避免緩存集中過時帶來的問題。剩下幾個前面都涉及到了,就再也不講了

接下來,快速講一下消息隊列。 消息隊列能夠應用到分佈式事務,分段式提交裏。 也能夠幫助系統架構解耦。 能夠用來作削峯限流,既不超過系統承載能力,同時又不丟失用戶消息。消息隊列服務的SLA是保證消息不丟,但犧牲掉了消息不重。會重複發送同一個消息。因此就要求消費者保證操做的冪等性。

消費者的拉消息模型, 好處是消費者不會過載,超過最大處理能力。壞處是消費者須要專門引入一個單獨的服務進程或者線程。
消費者的推模型,消費者構型簡單,跟開發一個用戶接口同樣。壞處是可能會過載。

常見消息隊列如kafka和rabbitMQ的特色,我就很少講了。

 

 

 

下面這張圖,我快速講一下數據庫。
數據庫的主庫從庫讀寫分離,通常會形成規定時間內的數據不一致現象,所以在須要強一致的狀況下, 能夠先讀從庫, 若是讀不到,再去讀主庫,必定程度上能夠減小主庫的壓力。 犧牲了一點兒數據一致性,提高了系統的可用性。

分庫或者分表能夠顯著提高數據庫的讀寫性能。 定時歸檔和分表同樣,是減小單表的數據量,提高讀寫性能。 減小沒必要要的索引,任何數據庫的讀寫操做,即便沒有使用事務, 對數據庫而言也都是一個事務。 爲了保障數據庫的ACID屬性, Insert操做必須在全部索引創建完成後才能返回,所以單表創建過多的索引會拖累數據庫的性能。

分佈式系統裏,要儘可能避免耗時的數據庫操做, 好比數據庫事務操做, 聯表查詢等操做, 由於這些耗時操做,就是讓系統在規定時間內的A達不到了。根據業務特色能夠採起最終一致性的概念,結合消息隊列,使用分段事務提交的方法,適當延長達到一致性的時間,來換取系統可用性的提高。

在新東方APP的做業系統裏, 發做業就是一個典型的分佈式事務。 此外,因爲學生的報、轉、退,和插班動做,產生了不少學生收不到做業,做業錯亂的客訴。 所以結合消息隊列,分段提交。 而且用定時任務掃表,作各類補償操做,解決了大部分的客訴問題。

結合CAP定理,再說一句, MYSQL是CA系統, 若是mysql增長了從庫,也就是引入了CAP裏的P, 可是mysql主從分離的分佈式屬性,比起tidb的分佈式屬性要差一些,由於這樣只是擴容了算力,而不是擴容了存儲。數據庫主從分離,是引入P,犧牲了C,加強了A,SQL查詢變快了。 可是對於很短的,規定時間裏, 要達到數據強一致的業務場景, 讀寫必須都走主庫,但還好,這種業務場景是比較少的, 新東方的報名續班業務是一個。

結合CAP定理, Tidb是一個典型的CP系統,至少有三個數據副本,經過raft協議實現三副本數據的強一致。由於引入了P,TIDB的分佈式擴展能力比mysql好,不管是存儲擴容仍是算力擴容都比mysql好。並且tidb兼容mysql,保證數據的強一致性,因此tidb對於訂單交易業務,是一個很好的選擇。 這些年銀行大大小小的不可用事故,發生了不下10起,但沒據說誰的錢丟了。 因此涉及到錢和優惠券的場景, 寧肯發生服務不可用事故,也不能發生數據一致性事故, 所以CP系統保證了錢不丟,又保證了分佈式擴容能力,是一個互聯網時代下的很不錯的選擇,但規定時間內的可用性就會差一點兒。

 

 

新東方APP由我學APP發展而來, 目前也支持新東方的所有業務線的搜課服務,以及K12的學生端與教師端服務

 

 

新東方APP2019年之前的架構能夠用一團亂麻來形容,架構沒有分層,並且亂拉電線。主要的問題有

一、前端不止作了展示交互, 也作了各個後端系統的數據聚合工做, 前端計算聚合完的數據,還要寫到後端。這其實就是10幾年前遊戲的作法, 黑客能夠經過改動魔獸世界的客戶端, 就讓金幣增長,或者得到特殊裝備,那就是由於把不少關鍵的業務計算邏輯放到的客戶端完成。整個架構沒有符合單一職責,和開閉原則的設計規範,最後就是用APP包了一層皮出來。

二、先後端都沒有熔斷、降級限流等穩定性設計,聽雲監控看到一個請求耗時幾分鐘, 其實用戶早都殺掉APP了。

三、沒有業務上監控報警, 被動等客訴,代碼裏基本不寫錯誤日誌。先後端都應該有監控報警。前端頁面加載失敗, JS錯誤這些都應該上報錯誤日誌。

四、服務器性能不好,單節點只能承載15個併發請求。不是全部問題均可以經過加機器來解決,這麼差的性能已經不是加機器能夠解決的了。

五、數據不一致現象嚴重,同一份業務數據, 在多個系統,甚至端上重複計算,分別存儲,沒有事務保證,不考慮併發設計,致使數據不一致的客訴不少。
系統裏存在太多的單點故障。 MQ, NFS存儲、定時任務。都曾經爆雷

六、研發效率低,代碼裏不少地方的註釋寫着, 此處有巨坑, 很差改, 先這樣吧, 之後再說。。。這也說明,之前多是沒有代碼review流程,技術方案review流程的。

七、數據庫處處是JOIN操做,性能極差,多表寫入,併發寫入都不考慮事務保護,形成數據不一致現象廣泛發生,該用冪等操做設計的地方也沒有用。緩存的使用也存在問題。

以上就是新東方APP架構2019年之前的樣子。

 

 

 

新東方APP最核心的功能是學生作做業。這張圖是之前,新東方APP裏趣配音的做業架構,這個架構發生過不少次服務不可用事故。

你們還記得前面的定理描述, 可用性是在規定的時間內要返回正常的應答。而400應答,500應答增多就是系統服務的可用性下降了。不是非要等整個系統已經ping不到纔算不可用。
因爲做業,不管是上傳仍是下載,都佔用鏈接池的時間過長,因此致使其餘服務都受到了影響, 下降了整個系統的可用性。

用戶中心頭像服務超時嚴重, 分析緣由也都是由於NFS存儲致使的。因此爲了保障做業穩定性,提高學生作做業的體驗,必須拆除掉對NFS存儲的嚴重依賴

 

 

 

下面這張圖是目前新東方APP的趣味配音做業的架構,這個架構比較複雜,第一次分享,沒有潤色,稍微有點亂。
這個圖裏的綠色文字步驟都是降級操做。新的架構設計應用了BASE定理, 經過基本可用,最終一致等概念,顯著提高了整個做業系統的可用性。

和舊的架構相比,新的架構拆除了整個用戶交互過程對NFS存儲的的依賴, 使用騰訊對象存儲做業主力存儲, NFS降級爲備份。這個方案還抵擋住了好幾回騰訊雲的線上事故。
當騰訊雲對象存儲發生了故障時, NFS會被啓用, 短期內會有必定的數據不一致,但因爲NFS被設置成對象存儲的回源地址, 所以兩邊存儲最終仍是會一致的。

騰訊雲CDN和對象存儲發生過屢次故障, 持續時間從數分鐘到10分鐘左右不等, 咱們的新架構都抗過去了,沒有發生任何穩定性問題和客訴, 曾經有一次, 新東方到騰訊雲的專線流量激增, 就是由於騰訊雲的CDN出了問題,沒法訪問,APP端發生大面積降級,帶附件上傳做業的比例顯著增長, 查看做業結果視頻的降級也同時顯著增長。

除了混合雲存儲, 咱們作了自動彈性到騰訊雲的混合雲計算。 當咱們本地的視頻合成服務過載時,計算任務會自動彈性到騰訊雲的FAAS計算。沒有發生彈性時,咱們不須要給騰訊雲付錢, 發生彈性時, 每月100萬次如下的計算是免費的。因此能夠說, 咱們以這種方式,基本沒花錢,就增強整個系統的可用性。

做業是APP最重要的功能,從咱們的價值導向判斷,做業穩定性投入再多時間和精力,都是值得的。目前新東方APP的做業系統已經被改形成一個打不死的小強。

 

 

 

 

快速說一下,熔斷降級限流, 前面的PPT都提到了。
這裏再說一個APP熔斷重試的bad case,APP團隊之前的系統裏,把Redis配成默認1秒熔斷,20次重試。 結果有一次,redis發生故障時,拖累整個APP服務故障,全都不可用。你們記住redis是CP系統。

關於限流, 有一次,由於外部的爬蟲致使APP對教務的訪問增長,流量激增,最後爲了系統穩定,在nginx上增長了限流處理, 保護了內部ERP系統的穩定。

 

 

 

快速過一下JVM優化
這一頁是APP作JVM優化的實際案例。 我抽象總結一下,就是要儘可能避免,一次申請很是大的內存, 例如打開一個10幾兆的圖片, 例如,不分頁,一次查詢10幾萬條數據庫記錄。
當年輕代內存不夠用的時候,這些內存會直接進入老年代,若是這些操做是比較頻繁的,就會致使頻繁的Full GC,損害整個系統的可用性。 優化以後,full GC頻率就明顯降低了

再說一下咱們作的題庫改造工做,
因爲B/C兩端對產品技術能力模型要求不同,之前題庫跟APP的技術模塊是混在一塊兒分不清的,致使工做效率下降, 部門合做成本提升:
C端: 大用戶量, 高併發, 影響大, 直接承接外部用戶流量
B端: 用戶量少, 併發低,如內容系統,題庫等, 承接內部用戶流量
因爲B/C兩端支持的用戶類型不一樣, 面對的問題域不一樣,應該拆開,提升各個部門的研發效率,和跨部門的協同效率

除了研發效率, 之前有些數據好比測評結果數據,學情數據在TPS和泡泡服務器上多處存儲, 數據不一致現象很是嚴重, 由此發生不少很是難解決的客訴,不下定決心作B/C服務拆分,就沒法完全解決相關客訴,和提高整個做業系統的穩定性。

這裏說一下去年咱們的數據庫遷移工做。
咱們把數據庫從tidb遷移到了mysql,同時作了分庫分表,和索引優化,刪除了大量沒有必要的索引, 查詢寫入性能提高了十倍以上。
這麼作的緣由是,咱們APP業務尤爲做業, 對數據強一致性沒那麼高的要求,咱們須要的就是高可用性。 TIDB是很好, 但它是一個CP系統用到這裏,是場景不對。

這頁PPT是聽雲的監控數據。APP團隊技術優化工做讓用戶的體驗更流暢,系統更穩定。

經過聽雲監控的圖表能夠看到,99百分位的請求應答性能累計提高了163倍。

 

 

 

經過APP客訴統計分析, 能夠看到,APP用戶量增長一半以上的狀況下, 客訴率降低了一倍多。

 

 

 

這個圖上是咱們本身開發了一套,APP和H5的監控告警機制,當APP的加載超時,訪問錯誤直接上報。
經過APP向H5注入代碼, 也實現了對APP上全部的H5頁面的監控, H5頁面中的JS錯誤,請求錯誤,均可以即時上報。

再結合公司的聽雲監控,運維的監控系統,咱們的監控就能夠在客訴發生以前發現很多問題,也能夠經過監控,發現不少系統穩定性的地雷,即時拆除。

目前APP這邊日誌都加了TraceID,在必定程度上能夠幫助研發快速定位分佈式系統的問題緣由。

但也有問題,前端後端的traceID沒有打通,APP和其餘系統的TraceID沒有打通,須要公司級的日誌監控告警的基礎架構組件支持。

 

 

 

下圖是,聚合監控告警服務實時分析日誌數據,發現預警後, 告警被打倒釘釘羣裏, 技術值班人員能夠經過密切關注釘釘告警,提前發現問題。

 

 

根據APP業務特色, 還作了一些服務化的改造。 對一些業務作了抽象剝離與解耦重構 

 

 

 在新的架構裏,咱們清晰的引入了服務接入層, 後臺作服務化改造。作各類服務拆分與解耦,重構的工做。讓整個架構更清晰, 各個模塊的職責更明確, 系統的穩定性更高。

 

 

 

新東方集團的主數據的問題有一點相似數據庫從庫或者是本地緩存帶來的的問題,數據副本太多, 數據不一致,數據質量很是差。

各個使用主數據的系統彼此之間調用和對比數據時,也會發現數據不一致。 主數據帶來的客訴,和線上故障不少。所以吳強老師下令拆除主數據服務

 

 

 

 爲此, 咱們啓動了C端數據中臺OnePiece項目的開發建設工做。

 

 

 

先說一下用戶中心的頭像服務。請求失敗率長期超過50%

在老用戶中心的頭像服務裏, 即便是查詢頭像URL這種輕量操做,代碼裏也要用fexist fopen這種很重的IO操做去驗證頭像圖片上,IO耗時不比下載頭像少。 此外因爲頭像沒有放到CDN上,所以全部的頭像圖片下載請求都回源到應用服務器上,應用服務器又是訪問本地NFS存儲。因此整個系統的可用性極差。

 

 

 

開閉原則你們自行查找, 在這個具體案例裏
符合開閉原則,就是當你採用新的數據接口的時候,你也要能夠保持老接口繼續可用, 同時提供新的數據服務接口
我剛接手用戶中心改造工做時,就馬上發現其實只要把新用戶中心的數據打平, 就是老用戶中心的數據接口,老用戶中心的服務不使用stuID數據字段就能夠了。

 

 

   

接着上一頁PPT講, 咱們在新用戶中內心徹底接管了對老用戶心中的訪問。經過打平新用戶中心的數據庫結構實現對老用戶中心服務用戶的平滑遷移。
在遷移期間, 數據寫入是雙寫的,爲的是出現故障時,快速止損,快速回滾服務,快速回滾數據。遷移期間, 數據查詢請求也是兩邊都請求。 由Apollo作一個開關,決定用那邊的請求應答響應用戶。 同時也是爲了作一個數據對比,及時發現和修復BUG。

數據庫主從分離, 自己也是犧牲了數據一致性,換取可用性。但數據庫寫入操做通常都是強一致的,因此在寫入數據以前若是須要讀取任何數據庫數據,應該是強制讀主庫(甚至要用事務或鎖包讀寫過程保護起來),而不能讀從庫,更不能去讀緩存。

前面緩存那一頁PPT講了不少了這邊就再也不贅述。我想強調一下, 咱們作老系統的改造和遷移時, 必定要設計好上線計劃和回滾計劃,在開始動手寫代碼以前,就寫進技術方案裏面。 上線以前首先就考慮,上線後出現故障怎麼辦? 出現故障時,是否會產生髒數據和數據丟失,發生故障時, 及時止損, 不只僅是服務的回滾恢復, 還有數據的回滾恢復。以及如何快速回滾。

用戶中心更新緩存時,因爲數據結構很是複雜,有多級列表,所以爲了減小代碼複雜性,必需要先刪除緩存,再從新加載,這期間必需要加鎖,有事務性保障。減小數據不一致發生的可能性。但須要數據強一致的操做仍是要強制讀數據庫主庫。

用戶中心在測試期間要用線上真實流量的回放作一次壓測。 多啦A夢,這個是咱們團隊的測試專家吳興微老師開發的測試工具。 具體你們能夠問他怎麼作的。我不作解釋

 

 

 

此次咱們也重構了教務中心的C端服務。目前教務中心提供的查詢服務都是經過ES實現的,C端可用性不高。 此次咱們拉了教務的從庫來保證C端數據查詢的高可用。
因爲教務的數據結構複雜,僅僅APP業務須要的查詢操做就涉及到20幾張表, 所以爲了消滅和減小這些耗時的JOIN操做,提升系統可用性, 咱們把幾個大的維表(最多有12萬條記錄的)加載到本地緩存裏,在服務器的內存裏實現JOIN操做。 由於維表數據量大,所以大批量加載數據進redis是不現實的,並且列表的聚合若是走redis,也會增長請求數量,損害redis的可用性。

交易表的聚合依然是在數據庫裏完成的,根據目前的業務特色聚合結果也是能夠短期緩存的。在引入本地緩存組件後,請求路由上就必須使用一致性Hash,把服務器的本地緩存數據進行分區處理。這裏的hash key目前肯定是校區ID,班課ID,用戶ID等, 之後可能還須要持續優化策略。

 

 

 

最後數據中臺Onepiece項目的測試方法,仍是準備用吳興微開發的多啦A流量回放工具,用線上真實流量作測試。 
測試完畢後,準備採用灰度發佈加藍綠髮布的方式上線。

OnePiece也是對MDM服務的平滑遷移, 所以兼容主數據服務接口, 在遷移上線期間, 能夠用Apollo開關, 一個接口一個接口的, 先10%小流量。 沒有問題主鍵放量到100%。 全量發佈後能夠經過日誌繼續對比數據, 及時發現罕見場景下的問題。

整個系統的上線過程持續三週以上,天天都發布上線幾個接口,期間研發密切觀察監控和客訴,一旦發現問題, 就能夠經過apollo開關, 一鍵快速回滾。有效地,把線上問題和風險控制在很小的範圍裏。

 

 

 

前面講的東西其實沒有什麼技術含量,都是能夠快速習得的經驗。 咱們團隊面試時,最看重的是邏輯思惟能力,寫代碼能力,和學習能力等硬核素質。 

 

 

感謝你們! 新東方教育科技集團公司正在加速推進互聯網產品技術佈局,組建徹底互聯網化的技術團隊,很是歡迎加入, 爲中國的教育發展貢獻本身的一份力量。

相關文章
相關標籤/搜索