從單體開始的架構演進

背景:因爲公司業務發展,銷售玩法已經不滿足於單純的下單平臺,玩起了“驚心動魄”的秒殺活動,然而服務端並不能承載這麼高的瞬時流量。表現在於數據庫意料之中的掛了,被打的起不來,於是部門同事說:“數據庫壓力太大,可能配置沒有整好,我們需要換阿里雲的!”

可能是我太年輕,見獵心喜,這不正好是《大型網站技術架構:核心原理與案例分析》中架構的演進嗎?爲了避免大家在錯誤的道路上越走越遠,於是我提出給大家做一次技術分享,幹活兒之前統一思想,我黨的優良傳統~

“架構是演進的”—這句話相信不少開發都聽過,但是究竟什麼是架構,很多人都沒法說明白。有幸在一家“大”公司的技術部做後端開發,更有幸經歷了從單體開始的一次架構演進,下文是我在公司部門技術分享的內容。

大綱:

  1. 什麼是架構?

  2. DB裸奔時代。

  3. 引入Cache扛讀。

  4. 引入MQ削峯填谷。

  5. 關於秒殺。

一、什麼是架構?

本文開始之前,我想問一下大家,你覺得什麼是架構?

(此處思考三秒鐘🤔)

先不急着回答,我們先看看考量一個架構好壞的五個指標:

  • 高性能

  • 高可用

  • 可伸縮

  • 可擴展

  • 安全

—《李智慧:大型網站技術架構:核心原理與案例分析》

  1. 高性能:有QPS和TPS很多指標,但我個人更傾向於從用戶角度去理解,也就是給用戶響應時間的快慢。

  2. 高可用:就是服務的可用性,我們常說的99%,99.9%,99.99%就是在一年的時間裏,停機的時間要分別低於3.65天,8.76小時,52.56分鐘。

  3. 可伸縮:一個架構師及格線就在於他實現的架構是否是可伸縮的,也就是當業務量突然爆發的時候,我們能不能通過簡單加機器的方式來保障服務性能和可用性。當然,不需要的時候直接撤掉機器即可。

  4. 可擴展:基礎設施不需要經常變更,松耦合,通俗的來講就是我現有的架構是一輛車,我在車上裝一些東西,不需要改造我的車就能完成。

  5. 安全:這個不用多說,但是常常被人所忽視~

看完以上五個衡量架構好壞的指標,你有沒有對“架構”這個詞有了新的理解?不急,我們繼續進行下一步,單體架構的演進!

二、DB裸奔時代

大部分公司都是從無到有,從小到大慢慢的做起來的,架構是不斷演進的,也就是說架構是符合當前業務實際需要的,太超前浪費資源,落後肯定完球唄~

場景:初創公司業務量小,用戶量也小,無需過於複雜,單體+DB直接扛就行了。

圖一·應用基本架構
圖一·應用基本架構

上圖是一個再簡單不過的基本架構圖,省略了web前端和移動端。一個Nginx做反向代理,單體server,MongoDB一主一副本一投票。這個架構對於一般的初創公司是毫無問題的,但是隨着業務量和用戶量的日益增多,對於一些熱點功能和突發情況,越來越力不從心。

大流量過來直接打在數據庫上,先掛的肯定是數據庫,一個正常的思路是DB不行了,咱們換一個DB嘛~然而這個思路真的可行嗎?

顯然不可能,就像我需要去摘二層樓高樹上果子,我不是要讓自己長得更高一點,而是需要一個梯子~

這個時候架構的演進就開始了~

三、引入Cache扛讀

**讀瓶頸:**據不完全調查統計,互聯網應用特性之一是讀高於寫,大概10:1?的比例,多少記不清了,反正大部分公司都是讀先於寫出現瓶頸。所以我們首先要解決的是讀的問題。

圖二·引入Cache後
圖二·引入Cache後

無論是Memcache還是Redis都是非常優秀的高性能內存型KV數據庫,官方數據表示Redis讀的速度是110000次/s,寫的速度是81000次/s。遠遠超過DB的讀寫性能,顯而易見,比起更換DB使用cache緩存扛讀纔是性價比最高的解決方案。(PS:比之MySQL的讀寫分離,MongoDB官方不建議使用讀寫分離,更建議使用分片技術。)

這裏注意幾個點:

  • **緩存穿透:**就是讀cache的時候沒有發現數據,轉而請求數據庫。這個叫緩存穿透,有個攻擊手段就是攻擊者故意請求一個根本不存在的數據,此時肯定要去DB中取數據,流量還是打在DB上,Cache沒有發揮作用,一旦併發量過大,DB壓力會很大,解決辦法之一就是一旦查詢DB沒有,就返回空值進行緩存。

  • **緩存雪崩:**是指大批量數據到過期時間,而此時查詢壓力過大,DB很可能會掛!解決辦法是緩存設置不同的過期時間,熱點數據不過期。

  • **緩存預熱:**在Redis剛啓動的時候裏面顯然沒有數據,這個時候需要緩存預熱,通過手動,或者程序腳本的方式,將數據預熱到緩存中。

四、引入MQ削峯填谷

隨着用戶量進一步增多,原來沒有壓力的寫也變得有問題了,這個時候就需要引入MQ—消息隊列,來削峯填谷,消息隊列的特性之一就是生產者生產消息,丟入消息隊列,消費者從消息隊列取消息,處理完了繼續取,不存在DB寫任務太多,被壓死的情況。
圖三·加入消息隊列
圖三·加入消息隊列

還有一個原因在於,在我司秒殺活動中,巨大的瞬時訂單寫入請求,用戶支付完成後,DB掛了訂單數據不一致怎麼辦?我覺得這是個致命的問題,但是我司沒有出現這樣的情況。

五、關於秒殺

關於秒殺活動設計網絡上帖子一抓一大把,在這裏我只挑重點說明,不再詳細贅述。

秒殺業務和高併發小異大同,都是高併發,但是秒殺活動是瞬時流量高,**最最關鍵的還是在於:秒殺活動,大部分流量都是無效流量。**因爲活動商品數遠遠小於參與活動的用戶數,搶不到很正常,弄明白了這一點就什麼都好辦了。

專業術語:隨機不請求

前端!

1. 動態頁面靜態化,善用CDN。

2. 隨機丟棄請求,取隨機數0-100,取在1-10的請求提交服務器,剩下的告訴用戶“秒殺中···請等待”,實則秒殺失敗,這樣就過濾掉了90%的流量,我們的server 非常安全!

但是!我們要做的還有很多:

  1. 活動開始前跟市場運營人員預估參與活動人數,大概過濾多少比較合適,知彼。

  2. 進行壓力測試,看看自己系統能夠扛住多少的併發量,找出系統的薄弱環節,進行優化,知己。

  3. 無他,加機器。

子曰:知己知彼,百戰而不怠。

尾聲:

非常有幸能夠見證一家公司架構上的演進,也非常榮幸能夠參與到這個過程中,貢獻自己力量,這是一個後端工程師莫大的榮幸。

因爲公司業務的不斷髮展,需求部門涉及市場,供應鏈等多部門,項目功能重合,不斷開發已有業務而不能很好的整合。

對此,雖然我才疏學淺,但是於上週還是爲部門同事做了一次有關於《SOA與微服務》的技術分享,講明我司技術部遇到的問題,應該如何解決。後文我將繼續寫文分享出來,供大家參考。

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