恭喜你成爲了政府網站的後端工程師,你的第一份工作很簡單
明天有 2300 萬人要同時進去普發 1 萬網站,不要讓網站掛掉
先不要急得辭職,我們可以先分析一些簡單的方法
分析問題
寫任何程式的第一步就是分析你要解決什麼問題,在你眼前擺著三座大山
1. 瞬間流量峰值
當所有人在同一時間點湧入,伺服器的 CPU、記憶體、網路頻寬都會瞬間達到極限。
2. 資料庫瓶頸
無論你有多少台應用伺服器,最終所有請求都要訪問同一個資料庫。資料庫的讀寫速度成為整個系統的致命瓶頸。
3. 資料一致性問題
2300 萬人不只是查詢資料,還要登記、查詢餘額、確認資格。如何在高併發情況下保證資料的正確性?這是最困難的挑戰。
一、首先,分而治之「身分證尾碼分流」
我想大家都遇到過演唱會訂票、剛開學的搶課、電商促銷時
如果人流很大,那些網站很容易直接掛掉,那就不要讓他們同時進來
透過身份證尾號,把全國人口平均分成十組。尾碼 0 和 1 的人星期一進來,2 和 3 的星期二,以此類推。原本一天要承受 2300 萬人的壓力,現在分散到五天,每天只需要處理約 460 萬人。這個數字看起來還是很嚇人,但至少比一次處理全部要可行得多。
二、再來,不要讓單一伺服器累死「負載平衡」
我之前用我家的電腦開網站,人少的時候是沒什麼事情
但人一多,回頭一看你的電腦正在著火
該怎麼辦呢?多買兩塊電腦
今天有流量進來,我把它會交給比較閒的每台,大幅降低單台電腦的工作量
當然電腦再多,資料庫終就只有一個
聰明如你馬上想到用 Redis,做一個快取大大降低資料庫的壓力
但 2300萬人不是只看資料,他們還要寫進去登記、查詢餘額、確認資格,更不用說同時更改了,你要怎麼保證資料一致呢?
三、快取系統
開發快取系統,眼前又有三座大山需要解決
快取穿透:當有人一直查詢一個根本不存在的資料,比如身分證號碼「Z999999999」。因為資料不存在,快取裡當然也沒有,所以每次查詢都會直接打到資料庫。如果有惡意使用者不斷送出這種請求,資料庫就會被拖垮。解決方法是即使查詢結果是「不存在」,也在快取裡記錄這個結果,避免重複查詢。
快取擊穿:當一個超熱門的資料剛好過期時,會有大量請求同時發現快取沒有這個資料,於是全部衝向資料庫。這就像演唱會門票剛開賣的那一瞬間,所有人同時按下購買鍵。解決方法是使用「互斥鎖」機制,確保同一時間只有一個請求去資料庫更新快取。
快取雪崩:如果大量快取資料同時過期,就會造成資料庫瞬間被大量請求淹沒。解決方法是讓快取的過期時間隨機化,避免集體失效。
四、將整個資料庫切成10塊小倉庫,「資料庫分片」
即便有了快取系統,使用者還是需要寫入資料的。
這時候就需要資料庫分片技術了。簡單說,就是把一個大資料庫切成很多小資料庫。
還是用身分證尾碼來舉例。我們可以建立十個小資料庫,尾碼是 0 或 1 的人,資料存在第一個資料庫;2 或 3 的存在第二個;以此類推。原本 2300 萬筆資料擠在一個資料庫裡,現在分散到十個資料庫,每個只管理約 230 萬筆資料。
這樣做的好處是什麼?當尾碼 3 的使用者在查詢他的申請進度時,他只會去第二個資料庫查詢,不會跟尾碼 7 的使用者搶資源。
但分片也帶來了新的挑戰。比如說,如果政府想要統計「目前總共有多少人完成登記」,就必須去十個資料庫分別查詢,再把結果加總起來。這比從單一資料庫查詢複雜多了。
五、訊息佇列,創建緩衝區
想像一家熱門餐廳,如果同一大堆人點餐,廚房肯定會大亂。
聰明的做法是什麼?讓客人在櫃台點餐,服務生把訂單寫下來依序交給廚房,廚房按照順序一份一份做。這就是訊息佇列的概念,寫一堆「待處理的訂單」,慢慢處理。
對於普發現金網站,當使用者送出「我要登記領取現金」的請求時,系統不需要立刻完成所有處理。它可以先告訴使用者「收到了,請稍候」,然後把這個請求放進佇列裡,後端系統再慢慢處理。
這樣做有幾個好處:首先,使用者不用傻傻等待,提交完就可以關掉網頁去做別的事。其次,後端系統可以按照自己的節奏處理請求,不會因為瞬間湧入太多請求而崩潰。最後,如果處理過程中出現錯誤,系統可以重試,不會讓使用者的申請就這樣消失了。
訊息佇列就像是一個緩衝墊,把「瞬間的超大流量」轉換成「持續的穩定處理」。原本一秒鐘內湧入的一萬個請求,可能會讓系統直接掛掉;但如果用訊息佇列接住,系統可以用一分鐘甚至更長時間慢慢處理完這些請求。
恭喜你,你現在可以從從容容、游刃有餘的休息了,你用你聰明的大腦成功守住你的工作
你可以在我得部落格中看到這篇文章
https://blog.ray-realms.com/article/beginner-guide-high-traffic-website



















