假如說我們現(xiàn)在要做一個千萬級用戶量網(wǎng)站,你怎么設(shè)計高并發(fā)架構(gòu)?
文轉(zhuǎn)載自微信公眾號「Java極客技術(shù)」,作者鴨血粉絲 。轉(zhuǎn)載本文請聯(lián)系Java極客技術(shù)公眾號。
之前的時候,阿粉一直在看同事面試,但是呢,阿粉并沒有自己去面試,而無意間打開Boss的時候,發(fā)現(xiàn)一家公司私聊了我,我回復了一下之后,竟然說我可以去面試,不曾想,面試一個問題,讓我的薪資瞬間被砍掉了5K,你如果不想自己出去要的薪資被砍,那么你要會設(shè)計這個。
一般的普通項目架構(gòu)
像阿粉的朋友所在的公司屬于一個中小型的公司,公司的項目都是按照客戶的要求來定制進行開發(fā)的,而服務器的數(shù)量那是少的可憐,什么高并發(fā),不考慮,什么高可用,也不考慮,一臺服務器上面部署了自己的項目,有時候連個圖片服務器都沒有,他們的圖就是這個樣子的。
是不是看著很簡陋的樣子,直接瀏覽器客戶端和單一服務器之間進行交流了,如果訪問人數(shù)在千人以上,比如秒殺個限量款,那估計可能直接就涼了,“Boom”的一下就訪問失敗了。
稍微進階版本的項目架構(gòu)
這個時候一般網(wǎng)站架構(gòu)還是采用單體架構(gòu),但是服務器也相對的增加了,終于增加了數(shù)據(jù)庫服務器和應用類服務器在加上圖片服務器,算是組成了一個小小的進階版本的項目架構(gòu)。
也就是說我們在部署應用的時候,手動把應用服務器上的Tomcat給關(guān)掉,然后替換系統(tǒng)的代碼war包,接著重新啟動Tomcat。
這時候把數(shù)據(jù)單獨的部署在另外的一個服務器上面,存放網(wǎng)站的全部核心數(shù)據(jù)。
然后在另外一臺獨立的服務器上部署NFS作為圖片服務器,存放網(wǎng)站的全部圖片。
這時候呢,代碼執(zhí)行的是請求,數(shù)據(jù)訪問在另外一臺服務器,而圖片在另外一臺服務器上面,這樣就通過增加了服務器來部署的普通版本的項目架構(gòu)就完成了,而大部分的項目都是這個樣子的吧,畢竟小公司人力有限呀。
簡單的支持高并發(fā),高可用的項目架構(gòu)
不知道大家在面試的時候說這個的時候面試官有沒有問過,如果你們的應用服務器掛了,你們怎么處理?
是的,應用服務器真的會出事,那在項目的應用服務器真的出事之后,我們怎么處理,在換個服務器,那么你很多想對應的配置就要做出更改,需要更改一大堆的東西,那么你會有很長時間的維護期,維護代價很高了呀。
這時候我們就出現(xiàn)了這個:
如果說我們有一臺其中的應用服務器宕機了,不干活了,那么接下來,另外的一臺服務器就會正常的使用,并且,在同時使用的時候,我們還能夠把從瀏覽器來的大量的請求分發(fā)一下,直接對半劈成2份,如果說其中有一個服務器的配置“高的飛起”,那么我們還可以通過配置,給他的請求讓他多一點,“設(shè)置權(quán)重”,這樣讓他分擔更多的壓力,而那個比較 low 的服務器的話,承擔的相應的請求就會減少一點,畢竟性能比較低。
而在這個時候還會出現(xiàn)另外一種意外,那就是數(shù)據(jù)庫服務器宕機了,怎么辦?相同的原理,增加另外的一個數(shù)據(jù)庫服務器,也就是主從數(shù)據(jù)庫。
那么為什么要做主從復制,不單單是因為這一個服務器宕機的問題,還有如果對數(shù)據(jù)庫的讀和寫都在同一個數(shù)據(jù)庫服務器中操作,業(yè)務系統(tǒng)性能會降低。
而我們很多的項目在數(shù)據(jù)上面需要的就是比較重要的,就很多就是做讀寫分離,而為了提升業(yè)務系統(tǒng)性能,優(yōu)化用戶體驗,可以通過做主從復制(讀寫分離)來減輕主數(shù)據(jù)庫的負載。
一臺用于寫入數(shù)據(jù),一臺用于同步主的數(shù)據(jù)并用于數(shù)據(jù)查詢操作。
配置好主從復制之后,同一張表,只能對一個服務器寫操作。
業(yè)務分離
現(xiàn)在很多項目的架構(gòu)都是所有人的業(yè)務代碼都寫在了一起,亂七八糟的,好幾個人的代碼,維護起來那叫一個崩潰,當你看到這樣的項目的時候,你就會發(fā)現(xiàn),人都傻了,這是個什么鬼,改動一點,其他的不好用了,那叫一個崩潰呀。
這時候我們就需要把我們的業(yè)務徹底的做出分割,比如商城里面的,訂單屬于一塊的業(yè)務,積分屬于一部分的業(yè)務,物流屬于另外一部分的業(yè)務,這時候我們就需要分成三塊的業(yè)務模塊。
也就是相當于每一塊的內(nèi)容都屬于一個服務,而這些服務疊加起來可就不是1+1=2的問題了,這些業(yè)務服務相加起來,這時候完整的項目和你把所有的內(nèi)容同一寫到一個部分的內(nèi)容差距是非常大的,尤其是在代碼冗余方面,做的那是相當透徹的。
而說到這些內(nèi)容的話,其實已經(jīng)算差不多了,但是再更深的阿粉是真的沒有了解到那么多,而阿粉之前沒想過這些內(nèi)容會在你面試的時候問到,可能阿粉當時只是想自己做個咸魚,不去關(guān)心架構(gòu)方面的事情,而架構(gòu)方面的事情確實很多公司很看重的一點。
在這里阿粉給大家再次貢獻出此次面試的其他的問題,并且給出詳細的解答,并且阿粉也是很欣慰的,只是壓了工資,而沒有說直接拒絕。
1.Redis分區(qū)實現(xiàn)方案
- 客戶端分區(qū):
客戶端分區(qū)就是在客戶端就已經(jīng)決定數(shù)據(jù)會被存儲到哪個redis節(jié)點或者從哪個redis節(jié)點讀取。大多數(shù)客戶端已經(jīng)實現(xiàn)了客戶端分區(qū)。
- 代理分區(qū):
代理分區(qū) 意味著客戶端將請求發(fā)送給代理,然后代理決定去哪個節(jié)點寫數(shù)據(jù)或者讀數(shù)據(jù)。代理根據(jù)分區(qū)規(guī)則決定請求哪些Redis實例,然后根據(jù)Redis的響應結(jié)果返回給客戶端。
- 查詢路由:
查詢路由(Query routing) 的意思是客戶端隨機地請求任意一個redis實例,然后由Redis將請求轉(zhuǎn)發(fā)給正確的Redis節(jié)點。Redis Cluster實現(xiàn)了一種混合形式的查詢路由,但并不是直接將請求從一個redis節(jié)點轉(zhuǎn)發(fā)到另一個redis節(jié)點,而是在客戶端的幫助下直接redirected到正確的redis節(jié)點。
這些都是阿粉死記硬背背下來的,關(guān)于這種東西,沒有實際親身實踐過的,沒有遇到過的問題的,都是屬于被diss的,但是面試官好像理解也不是很深,也是知道,但是具體的也沒有仔細的深挖我這塊的內(nèi)容。
2.SpringBean的生命周期
說實話,這個問題,面試好像現(xiàn)在都是必問的知識點了,阿粉的同事面試也是被問,但是巧了,之前阿粉就寫過關(guān)于SpringBean的生命周期的,文章鏈接給大家送上,大家可以仔細查看,可以共同交流呦。
面試官:兄弟你來闡述一下Spring框架中Bean的生命周期?
所以大家一定要把這個準備好呦,SpringBean的生命周期,從初始化到最終的銷毀中間經(jīng)歷了什么,過程是什么,流程怎么理解。
3.HashMap 和 Hashtable
這個問題我在回答的時候我就分開了,分門別類的比較比如說:
- 線程安全
- 性能優(yōu)劣
- NULL
- 實現(xiàn)方式
- 容量擴容
我分成了五塊的內(nèi)容作答,如果說你只能夠剛剛想起來其中的三到四點也是不錯的,至少比你只會說他們的線程安全和是否允許鍵為空來的好很多,如果大家有興趣,請尋找集合系列文章,在過往的歷史當中尋找一下,有很多關(guān)于HashMap 和 Hashtable的面試點。
4.JVM內(nèi)存模型和優(yōu)化
這個我相信只要是工作了兩到三年的程序員肯定都會,我就給大家簡單說說,之前的文章圖解,
關(guān)于其他的問題,都不是比較經(jīng)典的,都是屬于項目業(yè)務中的了,阿粉就不再一一給大家介紹了,總結(jié)起來就一句話,基礎(chǔ)你要掌握,擴展你更要會,不然面試想要高工資?那是不可能的,畢竟不是每家公司都缺“大爺”,不是么?
阿粉在這里希望大家找到自己理想的工作,等疫情穩(wěn)定了,直接跳槽工資“Double”。