從單一WAR到多活, 記述一個創業公司的架構演變

轉自:http://blog.csdn.net/hopeztm/article/details/75201823


本故事純屬虛構,如有雷同,實屬巧合

 是一個愛折騰,喜歡交朋友的程序員。

某一天,程一個朋友介紹了另外一個朋友  給他,創說他有個點子,可以改變世界,現在就差一個程序員。程看了創的PPT,覺得還不錯,反正也沒妹子,平時下班回家或者週末也沒事幹,就答應創,做他的合夥人,給他開發網站。

單一垂直架構

程把他自己在大學的時候做的基於Java的考試管理系統,拿來改了改,又自學了一些前端,三個月後,第一個版本的網站上線了。這個東西的後臺大概這個樣子,所有的東西都部署在一臺服務器上。


負載+垂直架構

上線後的半年,爲了適應業務的變更,網站做了多次升級和新功能的研發。伴隨着代碼越來越龐大,註冊用戶越來越多,有時候要卡半天,才能刷出頁面。創又多花幾倍的預算在技術上,買了幾臺新服務器。然後這套系統變成了下面的樣子,MySQL終於可以單獨放在一臺服務器上了,使用負載均衡後,可以把服務器實例(war)拷貝後部署到幾臺機器上了。

升級後,瞬間快了很多。


分佈式服務架構

後來,這個公司拿到了天使投資,程也全職加入了,身份是CTO,而理所當然的,創做了CEO。陸續也有運營和市場的合夥人加入,日活有幾萬了。程也不用自己寫前端了,因爲招了2個專門的前端工程師,還有另外2個做服務器的小夥子。市場變化很多,每天都有新需求,每天都可能上線新功能。

但是,當前這樣的服務器代碼體系,讓他越來越力不從心。

1. 這麼一坨龐大的代碼融在一起,維護成本和新人學習成本都是特別高的。 2. 想招一個實習生,但是如果開放給他權限就是所有代碼,真擔心這個實習生把代碼拿去賣了。 3. 代碼構建的時間越來越長,程序員最不喜歡的就是等了。 4. 發佈成本也很高,因爲每次發佈都是全量發佈。有些核心功能,需要全天服務用戶,所以白天幾乎不可能發佈。即時發佈一個無關緊要的功能,也要等到晚上,出了Bug還要趕緊修復,長期熬夜,真是覺得這個世界充滿惡意。

不能再這樣下去了......

其實程很早就聽過分佈式架構(SOA),也知道主流的公司都在用這些。但是現在業務代碼已經十分龐大了,至少十幾萬,並且有大量重複和“不敢動的”代碼,重構成SOA,至少要兩個月,公司新需求不斷,怎麼可能。

經過一個月的掙扎,真心覺得不能忍了,決定升級架構成SOA,調研後發現阿里的開源框架Dubbo (dubbo.io) 好像使用的蠻多,文檔也挺全的,所以決定用它。

重構前,首先梳理了一下業務,按照業務相關性,拆分成若干的底層SOA服務和API層服務。這個重構大概進行了2個月,CEO沒技術背景,完全不知道他們提的SOA是個啥,新需求不能被滿足,已經處於崩潰邊緣。

終於,新架構上線了,它大概長成這個樣子。


這裏,每個服務包括API服務和基礎的SOA服務都可以部署在不同的機器上,他們之間的發現是通過Zookeeper集羣協調的。啓動一個服務後,它就會註冊自己到Zookeeper上,服務調用方被通知,新的服務實例上線。服務調用方持有一個服務的多個調用實例,採用某種策略進行負載。

可以按照業務需求,有選擇的擴容指定服務,舉個栗子,例如商城做雙十一活動,有很多秒殺商品,那麼只需要多部署幾個和商城相關的服務即可。如果按照之前的架構設計,所有功能都在一個war中,只能對所有功能擴容,浪費計算資源。

當然,還有一些任務被改造成定時任務,就是圖中的Scheduled模塊,例如結算等,這樣運營或者程序員就不用大半夜起來做事了。

分庫分表,讀寫分離

半年後,公司又融了幾千萬的A輪,用戶數進一步擴大。高峯時段越來越卡,各種Log分析系統時間和分析mysql慢日誌發現,因爲數據量越來越多,併發數越來越大,主存儲已經有點Hold不住了。並且程越來越擔心萬一哪天,那臺Mysql機器硬盤出故障,廢了,公司的所有的數據就都沒了。

後來無意見,程發現了Mycat(mycat.io) 這個數據庫中間件,原來還以利用它做分庫分表,讀寫分離這些自己實踐起來十分困難的高級Feature。

經過了差不多一個月的調研,實踐,測試,升級後的Mysql集羣變成了如下的樣子。


做了分庫分表後,再也不用擔心太多數據把單一Mysql服務器硬盤撐滿的問題了,並且也更方便了權限管理。啓用Slave從節點後,也不用擔心單一主節點硬盤故障後,數據的丟失問題了。讀寫分離後,前端訪問速度也快了很多,增刪改查被分散到不同的機器,單節點的效率瓶頸有了很明顯的緩解。

DRC(Data Replication Center)

伴隨着業務種類越來越多,數據越來越多,依賴Mysql的索引的搜索早就顯得力不從心。爲了性能,只能支持某個字段的StartWith搜索。包含和模糊搜索都不能做,所以就用了Elastic Search做通用搜索引擎。爲了進一步提升讀效率,也把很多登錄信息和用戶好友關係這些經常讀的數據,放入Redis中做緩存。

同一份數據,既要放入ES,還要放入redis,早期這個功能實現大概如下:


更新代碼往往要關心緩存,同步ES數據,如果同步間隙過長,會有數據延遲,如果同步間隙太短,還要增加DB負擔。並且伴隨這個業務變多,越來越多這樣的操作:從一個表中全量拉取更新數據,做進一步業務處理,給業務庫造成很多額外的壓力。

如果主數據變動,就把變動發送到一箇中心,感興趣的一·方只要訂閱這些消息,就可以實現自己的邏輯,實時性高的同時,不會給業務庫造成任何壓力。於是DRC誕生了:


可以理解DRC Replicator模擬了一個Mysql Slave,從主節點拉binlog,然後解析binlog,並將結果發送到消息隊列中。

而感興趣的程序,可以去訂閱消息,然後執行相應的更新,這樣就把更新緩存的事情和業務代碼解耦了,更新ES這種操作也可以做到既實時性高,也不用經常去Mysql庫中掃描表了。當然DRC還有一個重要的應用,它也是多活的核心組件之一。

多活

伴隨用戶體量進一步提高,交易量的暴增,簡單的數據備份,已經不能很好的滿足需求了。如果機房宕機,依然會導致服務不可用。

另外,所有的流量都打到機房的服務集羣,也會導致一定的系統瓶頸。可能更理想的方式是:一個北京的用戶下單,他的整個業務流都落在北京的機房;上海的用戶下單,也希望所有的數據落在上海的機房,兩個機房的主數據互備,同時滿足數據的一致性。其中某個機房掛掉後,所有的流量切到另外一個機房。


而對於強一致性的數據,例如用戶表存在用戶名的uniq索引,對於這類數據,可以放在一個倍成爲全局數據的機房,所有寫落在這裏,其他機房只是執行備份。

就這樣,隨着用戶的逐漸增多,融資一次一次到來,團隊越來越多,業務線越來越多,架構的也一次一次升級演化。路已經走了很遠,並且伴隨着越走越遠,未來可能還有更多的升級和演化。


這個架構演化的故事,講完了。如有陳述不當或錯誤,歡迎留言討論~

傳送門 : https://zhuanlan.zhihu.com/p/27903657


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