億級流量架構之伺服器擴容思路及問題分析

等不到的口琴發表於2021-02-21

為什麼要擴容

說人話就是, 無論如何優化效能,能達到的最大值是一定的,對於一個使用者量大的應用,可以對伺服器進行各種優化,諸如限流資源隔離,但是上限還是在那裡,這時候就應該改變我們的硬體,例如使用更強的CPU、更大的記憶體,在前文中舉了一個學生食堂打飯的例子,如果學生多了,可以通過令牌桶演算法優先給高三學生令牌打飯,但是如果高三的學生還是很多呢?那就只有增加視窗或者食堂的數量,也就是硬體上的擴容。

擴容策略

擴容策略可以分為兩種, 一種是對單機整體擴容,也就是機器內部包含CPU、記憶體、儲存裝置等,另一種是擴容對應的元件,例如擴記憶體、擴磁碟、擴CPU。

整機硬體

整機擴容的好處是,有很多專業的伺服器硬體供應商,例如IBM、浪潮、DELL、HP等,專業的硬體供應商,他們組裝以及搭配方面可能經驗更加豐富,另外有些公司會對元件進行一些優化,從而伺服器更加穩定,可以類比為買電腦,有的人可能選擇買淘寶賣家已經組裝好的臺式,有的人可能自己買各種硬體自己回家組裝,對於一般人而言,選擇前者是較為靠譜的選擇,因為你即使懂硬體的一些引數,也難保自己搭配的機器是否能發揮各個部件最大效能。

元件

對於一些技術能力強悍的公司,更多的是自己買各種元件組裝,這樣成本更低,因為節省了組裝等費用,並且可以根據業務個性化定製,例如有的公司是計算密集型的,那麼主要是更換更強的CPU,有的IO密集型,那麼擴容的應該是記憶體等,有的公司需要儲存大量的資料,那麼可能擴容的是硬碟等儲存裝置。

元件包含:

cpu

Intel、Amd ,參考頻率、執行緒數等

網路卡

百兆->千兆 -> 萬兆

記憶體

ECC校驗

磁碟

SCSI HDD(機械)、HHD(混合)、SATA SSD、PCI-e SSD、 MVMe SSD

AKF拆分原則

Redis叢集拆分原則之AKF中,詳細介紹了AKF拆分原則的詳情,這兒簡單回顧一下:

對於一個應用,如果單機不足以支撐服務請求,那麼可以建立諸如主主、主從等模式的叢集:

這個叫AKF原則X軸擴充套件,目的是將請求分流在多臺機器上,但是多臺機器中間要解決資料同步性的問題,越多的機器資料不同步的可能性越大,這也就意味著沒法無限整體複製擴容。所以可以整理蒐集伺服器內熱點的業務請求,將業務分離出來,只對熱點業務進行擴容,這就是AKF原則的Y軸拆分:

對業務拆分之後,某個業務還可能太熱點,也就是Y軸拆分後水平復制還是不足以支撐資料請求,那麼可以將業務的資料進行拆分, 具體來說就是,某個業務的資料,可以放在多個地方,例如在湖北、北京、上海部署機房,各地的人們需要請求資料時,由離得近的伺服器提供服務。

拆分擴容後存在的問題

隨著業務的增長,系統變得越來越龐大, 根據系統功能拆分成獨立而又互通的專案, 比如交易系統、財務系統、生產流程系統、物流系統、網站系統等等,但是分散式結構會存在很多問題。對於這些問題每一個都值得深入探討,這兒簡單的提一下,後面再開篇幅。

  1. 資料共享問題
    所有的服務之間資料如何共享同步,這是一個需要考慮的問題,微服務架構中,資料不可能只有一份,沒法避免機器損壞等原因造成的資料丟失,多份資料之間如何同步?目前可供參考的解決思路是建立資料中心、搭建資料庫叢集。

  2. 介面呼叫問題
    不同的伺服器之間進行呼叫遵循遠端呼叫協議RPC

    JAVA RMI:Java遠端方法呼叫,即Java RMI(Java Remote Method Invocation)是Java程式語言裡,一種用於實現遠端過程呼叫的應用程式程式設計介面。 它使客戶機上執行的程式可以呼叫遠端伺服器上的物件。

    dubbo:提供了面向介面代理的高效能RPC呼叫

  3. 持久化資料雪崩問題
    資料庫分庫分表,參考:MySQL調優之分割槽表
    資源隔離,參考:億級流量架構之資源隔離思路與方法
    快取設定資料持久化策略:Redis持久化之RDB和AOF

  4. 高併發問題

    快取:諸如快取擊穿、穿透、雪崩等,參考Redis擊穿、穿透、雪崩產生原因以及解決思路

    資料閉環:為了便於理解,舉個例子,對於淘寶而言,有網頁版、IOS版、安卓版、還有什麼一淘等等,雖然客戶端不一樣,但是展示的商品資訊是相同的,也就是一件商品,無論是哪個端用的資料是一樣的,需要一套方案來解決併發下根據相同資料在不同端進行不同展示的問題,這就叫資料閉環。

  5. 資料一致性問題

    這是一個難點,大意就是多個伺服器之間資料如何保證一致性,同樣的商品在不同客戶端服務端端價格應該是一樣的, 通常使用分散式鎖。

資料庫擴容:叢集

先簡單說一下分散式與叢集的區別,這兩個詞兒經常一起出現,但是意義卻有所不同,分散式會縮短單個任務的執行時間來提升工作效率,而叢集強調的是提高單位時間內執行運算元的增加來提高效率。更簡單的來說,分散式是將步驟分到每臺電腦上,不考慮依賴關係,叢集方案是指幾個任務同時在處理。

單一資料庫儲存難以滿足業務需求時,採取叢集的方式,將資料儲存在不同的伺服器,這可以是主主或者主從,主從中主負責寫,從負責讀,將與資料庫有關的壓力進行分解到多臺機器上。

分散式ID

在複雜分散式系統中,往往需要對大量的資料和訊息進行唯一標識。很容易想到的是利用自增,但是自增有很多問題,例如ID有太強的規律,可能會被惡意查詢蒐集,面對資料日漸增長,對資料分庫分表後需要有一個唯一ID來標識一條資料或訊息,這樣資料庫的自增ID顯然不能滿足需求;特別一點的如商品、訂單、使用者也都需要有唯一ID做標識。此時一個能夠生成全域性唯一ID的系統是非常必要的。概括下來,那業務系統對ID號的要求有哪些呢?

分散式ID要求

面對分散式ID,需要滿足下面的要求:

  1. 全域性唯一性:不能出現重複的ID號,既然是唯一標識,這是最基本的要求。
  2. 趨勢遞增:在MySQL InnoDB引擎中使用的是聚集索引,由於多數RDBMS使用B-tree的資料結構來儲存索引資料,在主鍵的選擇上面我們應該儘量使用有序的主鍵保證寫入效能。
  3. 單調遞增:保證下一個ID一定大於上一個ID,例如事務版本號、IM增量訊息、排序等特殊需求。
  4. 資訊保安:如果ID是連續的,惡意使用者的扒取工作就非常容易做了,直接按照順序下載指定URL即可;如果是訂單號就更危險了,競對可以直接知道我們一天的單量。所以在一些應用場景下,會需要ID無規則、不規則。

上述123對應三類不同的場景,但是3和4的需求是互斥的,也就是無法使用同一個方案滿足。除了對ID號碼自身的要求,業務還對ID號生成系統的可用性要求極高,想象一下,如果ID生成系統癱瘓,整個與資料有關的動作都無法執行,會帶來一場災難。由此總結下一個ID生成系統最少應該做到如下幾點:

  1. 平均延遲和TP999延遲都要儘可能低;
  2. 可用性5個9(這是美團的要求,有些企業例如阿里要求6個9);
  3. 高QPS。

分散式ID生成策略

目前業界常用的ID生成策略有很多,例如UUID、雪花生成演算法、Redis、Zookeeper等,這兒只簡單講講UUID以及Snowflake,後面要開篇詳談。

UUID生成演算法

UUID(Universally Unique Identifier)的標準型式包含32個16進位制數字,以連字號分為五段,形式為8-4-4-4-12的36個字元,示例:550e8400-e29b-41d4-a716-446655440000,到目前為止業界一共有5種方式生成UUID,詳情見IETF釋出的UUID規範 A Universally Unique IDentifier (UUID) URN Namespace

優點:

  • 效能非常高:本地生成,沒有網路消耗。

缺點:

  • 不易於儲存:UUID太長,16位元組128位,通常以36長度的字串表示,很多場景不適用。

  • 資訊不安全:基於MAC地址生成UUID的演算法可能會造成MAC地址洩露,這個漏洞曾被用於尋找梅麗莎病毒的製作者位置。

  • ID作為主鍵時在特定的環境會存在一些問題,比如做DB主鍵的場景下,UUID就非常不適用:

    ① MySQL官方有明確的建議主鍵要儘量越短越好[4],36個字元長度的UUID不符合要求。

    All indexes other than the clustered index are known as secondary indexes. In InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index. InnoDB uses this primary key value to search for the row in the clustered index.If the primary key is long, the secondary indexes use more space, so it is advantageous to have a short primary key.

​ ② 對MySQL索引不利:如果作為資料庫主鍵,在InnoDB引擎下,UUID的無序性可能會引起資料位置頻繁變 動,嚴重影響效能。

雪花生成演算法

這種方案大致來說是一種以劃分名稱空間(UUID也算,由於比較常見,所以單獨分析)來生成ID的一種演算法,這種方案把64-bit分別劃分成多段,分開來標示機器、時間等,比如在snowflake中的64-bit分別表示如下圖(圖片來自網路)所示:



41-bit的時間可以表示(1L<<41)/(1000L360024*365)=69年的時間,10-bit機器可以分別表示1024臺機器。如果我們對IDC劃分有需求,還可以將10-bit分5-bit給IDC,分5-bit給工作機器。這樣就可以表示32個IDC,每個IDC下可以有32臺機器,可以根據自身需求定義。12個自增序列號可以表示\(2^{12}\)個ID,理論上snowflake方案的QPS約為409.6w/s,這種分配方式可以保證在任何一個IDC的任何一臺機器在任意毫秒內生成的ID都是不同的。

這種方式的優缺點是:

優點:

  • 毫秒數在高位,自增序列在低位,整個ID都是趨勢遞增的。
  • 不依賴資料庫等第三方系統,以服務的方式部署,穩定性更高,生成ID的效能也是非常高的。
  • 可以根據自身業務特性分配bit位,非常靈活。

缺點:

  • 強依賴機器時鐘,如果機器上時鐘回撥,會導致發號重複或者服務會處於不可用狀態。

彈性擴容

說人話,就是讓叢集根據計劃在某一段時間自動對資源進行擴容,並在設定的計劃還原時間時釋放資源。這樣能解決規律性的資源峰谷需求,達到充分合理利用資源的目的。
但是彈性擴容有一些問題:

第一,虛擬機器彈效能力較弱。使用虛擬機器部署業務,在彈性擴容時,需要經過申請虛擬機器、建立和部署虛擬機器、配置業務環境、啟動業務例項這幾個步驟。前面的幾個步驟屬於私有云平臺,後面的步驟屬於業務工程師。一次擴容需要多部門配合完成,擴容時間以小時計,過程難以實現自動化。如果可以實現自動化“一鍵快速擴容”,將極大地提高業務彈性效率,釋放更多的人力,同時也消除了人工操作導致事故的隱患。

第二,IT成本高。由於虛擬機器彈效能力較弱,業務部門為了應對流量高峰和突發流量,普遍採用預留大量機器和服務例項的做法。即先部署好大量的虛擬機器或物理機,按照業務高峰時所需資源做預留,一般是非高峰時段資源需求的兩倍。資源預留的辦法帶來非常高的IT成本,在非高峰時段,這些機器資源處於空閒狀態,也是巨大的浪費。

相關文章