1、當前,常見的系統架構設計有以下幾種:
- 單庫單應用架構:這種架構在系統開發規范雛形初期,很多系統就有使用,相對是最簡單的,小企業小系統就會用采用,尤其是做項目的公司;
- 內容分發架構:目前前端網頁、圖片、CSS、JS等這些靜態資源用的相對較多;
- 讀寫分離架構:對於高並發的查詢業務;
- 微服務架構:適用於把復雜的業務模式進行拆解;
- 多級緩存架構:利用緩存做出各種設計;
- 分庫分表架構:解決單級數據庫的瓶頸。
一、單庫單應用架構
這種架構是最簡單,我們在學習階段,基本都會采取這種模式,除了專門針對各種架構的學習。
這種模式的設計圖一般如下,
這種設計一般只有一個數據庫,一個業務應用層,一個后台管理系統,所有的業務都是用業務層完成的,所有的數據也都是存儲在一個數據庫中,好一點會由數據庫的同步,雖然比較簡單,但是還是很實用的。
優點:結構簡單、開發速度快、實現簡單,用於產品的第一版等有原型驗證需求。
缺點:性能較差、基本沒有高可用、擴展性差,不適用於大規模部署、應用等生產環境。
二、內容分發架構
基本上所有的大型網站都或多或少地采用這種架構,常見的應用場景一般是采用CDN技術把網頁、圖片、css、js 等這些靜態資源分發到離用戶最近的服務器。
這種模式的設計一般如下。
這種模式跟單庫單應用的模式多了一個CDN、一個雲存儲OSS(如阿里雲OSS)。
流程一般如下:
1、上傳的時候,用戶選擇本地機器上的一個圖片進行上傳;
2、程序把這個圖片上傳到雲存儲OSS上,並返回該圖片的一個URL;
3、程序把這個URL字符串存儲在業務數據庫中,上傳完成;
4、查看的時候,程序從業務數據庫得到該圖片的URL;
5、程序通過DNS查詢到這個URL的圖片服務器;
6、智能DNS會解析這個URL,得到於用戶最近的服務器(或集群)的地址A;
7、然后把服務器上的圖片返回給程序;
8、程序顯示該圖片,查看完成。
由上可知,這個模式的關鍵是智能DNS,他能夠解析出離用戶最近的服務器,運行原理大致是:根據請求者的IP得到請求地點B,然后通過計算或者配置得到與B最近或通訊時間最短的服務器C,然后把C的IP地址返回給請求者。這種模式的優缺點如下:
優點:資源下載快,無需過多的開發與配置,同時也減輕了后端服務器對資源的存儲壓力,減少帶寬的使用。
缺點:目前來說OSS、CDN的加個還是稍微優點貴的,只適用於中小規模的應用,另外由於網絡傳輸延遲、CDN的同步策略等,會有一些一致性、更新慢方面的問題。
三、讀寫分離架構
這種模式主要解決單機數據庫壓力過大,從而導致業務緩慢甚至超時,查詢影響時間變長的問題,也包括需要大量數據庫服務器計算資源的查詢請求,這個可以說是單庫應用模式的升級版本,也是技術架構迭代演進過程中的必經之路。
設計圖如下:
這種模式相比較單庫應用模式來說,多了幾個部分,一個是業務數據庫的主從分離,一個是引入ES。
場景一:全文關鍵字檢索
如果使用傳統的數據庫技術,大部分會使用like這種sql語句,高級一點的是先分詞,然后通過分詞index相關的記錄。SQL語句的性能問題與全表掃描機制導致了非常嚴重的性能問題,現在基本上很少見到。
ES較Solr配置簡單、使用方便,所以選用他。另外,ES支持橫向擴展,理論上沒有這個性能的瓶頸。同時,還支持各種插件、自定義分詞器等,可擴展性較強。而且ES還能實現分頁、排序、分組、頁面等功能。
一般的流程如下:
- 服務端把一條業務數據落庫;
- 服務器異步把該條數據發送到ES;
- ES把該條記錄按照規則、配置放入自己的索引庫;
- 客戶端查詢的時候,由服務端把這個請求發送到ES,得到數據后,根據需求拼接、組合數據,返回給客戶端。
場景二:大量的普通查詢
我們的業務中的大部分輔助性的查詢,如:取錢的時候,先查詢余額,根據用戶的ID查詢用戶的記錄,取得該用戶最新的一條取錢記錄,我們肯定是要天天用到的,而且用的還非常多。與此同時,我們的寫入請求也是非常多,導致大量 的寫入、查詢操作到同一數據庫,然后,數據庫掛了,系統掛了,這就很難受了。因此,要求我們必須分散數據庫的壓力,一個在業界較成熟的方案就是數據庫的讀寫分離,寫的時候入主庫,讀的時候讀分庫。這樣就把壓力分散到不同 的數據庫了,如果一個讀庫性能不行,扛不住的話,可以一主多從,橫向擴展。
一般的流程如下:
- 服務端把一條業務數據落庫;
- 服務器同步或異步半同步把該條數據復制到從庫;
- 服務端讀取數據的時候直接去從庫讀相應的數據。
優點:減少數據庫的壓力,理論上提供無限高的讀性能,簡介提高業務(寫)的性能,專用的查詢、索引、全文(分詞)解決方案。
缺點:數據延遲,數據一致性的保證。
四、微服務架構
傳統的軟件開發到一定階段,經常會遇到以下問題:
- 單級數據庫請求量大量增加,導致數據庫壓力變大;
- 數據庫一旦掛了,那么整個業務就都掛了;
- 業務代碼越來越多,都在一個git里,越來越難以維護;
- 代碼腐化嚴重,臭味越來越濃;
- 上線越來越頻繁,經常是一個小功能的修改,就要整個大項目重新編譯;
- 部門越來越多,該哪個部門改動大項目中的哪個東西,容易發生分歧;
- 其他一些外圍系統直接連數據庫。導致一旦數據庫結構發生變化,所有相關系統都要通知,甚至對修改不敏感的系統也要通知;
- 每個應用服務器需要開通所有權限、網絡、FTP、各種各樣的,因為每個服務器部署的應用都是一樣的;
- 作為架構師,無法把控這個系統了。
微服務模式的設計一般如下:
如圖所示,把業務分塊,做了垂直切分,切成了一個個獨立的系統,每個系統各自衍化,有自己的庫、緩存、ES等腐竹系統,系統之間的實時交互通過RPC,異步交互通過MQ,通過這種組合,共同完成整個系統功能。
對於問題一:由於拆分成多個子系統,系統的壓力被分散了,而各個子系統都有自己的數據庫實例,所有數據庫的壓力變小;
對於問題二:一個子系統A的數據庫掛了,只是影響到系統A和使用系統A的那些功能,不會所有功能不可用,從而解決一個數據庫掛了,導致所有的功能都不可用的情況;
對於問題三、四:也因為拆分得到了解決,各個子系統都有自己獨立的git代碼庫,不會相互影響。通用的模塊可通過庫、服務、平台的形式解決;
對於問題五:子系統A發生改變,需要上線,那么我們只需要編譯A,然后上線就可以了,不需要其他系統做同樣的的事情;
對於問題六:順應了康威定律,我部門該干什么,輸出什么,也通過服務的形式暴露出來,我部門只管把我部的職責、軟件功能做好就可以了;
對於問題七:所有需要我部數據的需求,都通過接口的形式發布出去,客戶通過接口獲取數據,從而屏蔽了底層數據庫結構,甚至數據來源,我部只需保證我部的接口契約沒有發生變化,新的需求增加新的接口,不會影響老的接口;
對於問題八:不同的子系統需要不同的權限,這個問題也優雅的解決了;
對於問題九:暫時控制住復雜性,我只需要控制好大方面,定義好系統邊界、接口、大的流程,然后再分而治之、逐個擊破、合縱連橫。
在此,所有問題得到解決!
但是,副作用也隨之而來,如RPC、MQ的超高穩定性、超高性能,網絡延遲,數據一致性等問題,這個就不展開來講了。
所以說,在這個模式來說,最難把握的是度,切記不要切分過細,我見過一個功能一個子系統,上百個方法分成上百個子系統的,真的是太過度了。實踐中,一個比較可行的方法是:能不分就不分。
優點:相對高性能,可擴展性強,高可用,適用於中等以上規模公司架構。
缺點:復雜、度不好把握。指不僅需要一個能再高層把控大方向、大流程、總體技術的人,還需要能夠針對各個子系統有針對性的開發。把握不好度或者濫用的話,這個模式適得其反!
五、多級緩存架構
這種模式是應對超高查詢壓力的普遍采用的一種策略,基本的思想就是在所有鏈路的地方,能加緩存就加緩存,設計如下:
如圖所示,一般在三個地方加入緩存,一個是客戶端處,一個是API網關處,一個是具體的后端業務處。
客戶端處緩存:這個地方加緩存可以說是效果最好的一個,不會延遲。因為不用經過很長的網絡鏈條去后端業務處獲取數據,從而導致加載時間過長,客戶流失等損失,雖然有CDN的支持,但是從客戶端到CDN還是有網絡延遲的,雖然不大,具體的技術依據不同的客戶端而定,對於WEB來講,有瀏覽器本地的緩存、Cookie、Storage、緩存策略等技術;對於APP來講,有本地數據庫,本地文件,本地內存,進程內緩存支持,以上提到的各種技術有興趣的同學可以繼續開展學習,如果客戶端緩存沒有命中,那么會去后端業務拿數據,一般來講,就會有個API網關,在這里加緩存也是非常重要的。
后端業務處理:Redis、Jvm等等。
實踐中,要結合具體的實際情況,綜合利用各級緩存技術,使得各種請求最大程度的在到達后端業務之前就被解決掉,從而減少后端服務器壓力、減少占用帶寬、增強用戶體驗。
優點:抗住大量讀請求,減少后端壓力。
缺點:數據一致性問題較為突出,容易發生雪崩,即:如果客戶端緩存失效、API網關緩存失效,那么所有的大量請求瞬間壓向后端業務系統,后果可想而知。
六、分庫分表架構
這種模式主要解決單表寫入、讀取 、存儲壓力過大,從而導致業務緩慢甚至超時,交易失敗,容量不夠的問題。一般有水平切分和垂直切分兩種,這里主要介紹水平切分。這個模式也是技術架構迭代演進的必經之路。
設計如圖
如上圖,把一張表分到了幾個不同的庫中,從而分擔壓力。是不是很籠統?哈哈,那我們接下來就詳細的講解一下,首先澄清幾個概念,如下:
主機:硬件,指一台物理機,或虛擬機,有自己的CPU,內存,硬盤等。
實例:數據庫實例,如一個MySql服務進程,一個主機可以有多個實例,不同的實例有不同的進程,監聽不同的端口。
庫:指表的集合,如學校庫,可能包含教師表、學生表、食堂表等等,這些表在一個庫中。一個實例中可以有多個庫,庫與庫之間用庫名來區分。
表:庫中的表,不必多說,不懂的就不用往下看了,不解釋。
那么怎么把單表分散呢?到底怎么個分發呢?分發到哪里呢?以下是幾個工作中的實踐,分享一下:
主機:這是最主要的也是最重要的點,本質上分庫分表是因為計算與存儲資源不夠導致的,而這種資源主要由物理機,主機提供的,畢竟沒有可用的計算資源,怎么分效果都不是太好。