從高維度出發,從總體上思考問題。秒殺其實主要解決兩個問題,一個是併發讀,一個是併發寫。數據庫
併發讀的核心優化理念是儘可能減小用戶到服務端來讀數據,或者讓他們讀更少的數據;瀏覽器
併發寫的處理原則頁同樣,它要求咱們在數據庫層面獨立出來一個庫,作特殊的處理。緩存
咱們還要針對秒殺系統作一些保護,針對意料以外的狀況設計兜底方案,以防止最壞的狀況發生。性能優化
要打造並維護一個超大流量併發讀寫、高性能、高可用的系統,在整個用戶請求路徑上從瀏覽器到服務端咱們要遵循幾個原則,就是要保證用戶請求的數據儘可能少,請求數儘可能少,路徑儘可能端,依賴儘可能少,而且不要有單點。服務器
秒殺的總體架構能夠歸納爲"穩、準、快"幾個關鍵字。網絡
技術角度地看"穩、準、快",就對應了咱們架構上地高可用、一致性和高性能地要求。架構
首先是指用戶請求的數據能少就少。由於這些數據傳輸需喲啊事件,服務器在寫網絡時要作壓縮和字符編碼,很是消耗CPU。其次,系統依賴的數據能少就少,包括系統完成某些業務邏輯須要讀取和保存的數據,調用其餘服務會設計數據的序列化和反序列化,會很是消耗cpu,與數據庫打交道越少越好,數據越簡單,越小則越好。併發
所謂"路徑",就是用戶發出請求到返回數據這個過程當中,需求通過的中間節點數。一般,這些節點能夠表示爲一個系統或者一個新的socket連接。每通過一個幾點,通常都會產生一個新的Socket連接。每增長一個連接都會增長新的不肯定性。縮短請求路徑不只能夠增長可用性,一樣能夠有效提高性能(減小數據的序列化與反序列化),並減小延時(能夠減小網絡傳輸耗時)。socket
縮短訪問路徑有一種辦法,就是多個相互強依賴的應用合併部署在一塊兒,把遠程過程調用變成JVM內部之間的方法調用。分佈式
所謂依賴,指的是要完成一次用戶請求必須依賴的系統或者服務,這裏的依賴指的是強依賴。
舉個例子,好比說你要是展現秒殺頁面,而這個頁面必須強依賴商品信息、用戶信息,還有其餘如優惠券、成交列表等這些對秒殺不是非要不可的信息(弱依賴),這些弱依賴在緊急狀況下就能夠去掉。
要減小依賴,咱們能夠給系統進行分級,好比0級系統、1級系統、2級系統、3級系統,0級系統若是是最重要的系統,那麼0級系統強依賴的系統也一樣是最重要的系統,以此類推。
注意,0級系統要儘可能減小對1級系統的強依賴,防止重要的系統被不重要的系統拖垮。例如支付系統是0級系統,而優惠券是1級系統的話,在極端狀況下能夠把優惠券降級,防止支付系統被優惠券這個1級系統給拖垮。
設計分佈式系統最重要的原則就是"消除單點"。
如何避免單點,我認爲關鍵點是避免將服務的狀態和機器綁定,即把服務無狀態化,這樣服務就能夠在機器中隨意移動。
商品購買頁面增長一個"定時上架"功能,僅在秒殺開始時才讓用戶看到購買按鈕,當商品的庫存賣完了就結束了。
隨着請求量的加大,這個簡單的架構很快就遇到瓶頸。須要架構改造,包括:
當訪問量超百萬的併發,須要進一步提高秒殺系統的性能,進一步升級,好比:
在這裏,咱們對頁面進行了進一步的靜態化,秒殺過程當中不須要刷新整個頁面,而只須要服務端請求不多的動態數據。並且,最關鍵的詳情和交易系統都增長了本地緩存,來提早緩存秒殺商品的信息,熱點數據庫也作了獨立部署,等等。
每次升級都須要定製不少地方,也就是越"不通用"。例如,秒殺商品緩存在每臺機器的內存中,這種方式顯然不太適合太多商品同時進行秒殺的狀況,由於單機的內存始終有限。因此要取得極致的性能,就要在其餘地方(好比,通用性、易用性、成本等方面)有所犧牲。