七牛李道兵談“架構壞味道”

wjaning發表於2021-09-09

軟體架構在成功的軟體交付中扮演著重要角色,好的架構可以相容不同型別的業務和演算法,並且相安無事,而架構設計不當就需要不斷地進行整體的更替,以適應業務的變化和新演算法的需求,甚至影響最後架構整體的穩定性、容量等。事實上,架構的很多方向性問題是可以在設計初期就避免的。因此,七牛首席架構師李道兵結合多年的實踐經驗,在本文中詳細總結出了以下七類具有明顯“壞味道”的架構影響因素。

架構對容量資料不敏感

設計架構時對於常規的一些基礎架構元素容量不清晰,比如前端的Nginx、後端標準的業務伺服器、資料庫及快取的容量等方面。Nginx整體容量比較大,一般不需要擔心。如果是下載型別的需求,那麼需要注意機器的網路卡。到業務邏輯這一段,每種語言、每個併發連線都有記憶體消耗,會導致單臺伺服器能支撐的併發數目是有限的。在資料庫領域,系統容量跟磁碟的IOPS相關,因此最好知道普通的SATA盤和SSD盤的IOPS是多少?做RAID10或者是RAID5對IOPS的影響究竟是怎樣的(因為IOPS對資料庫的效能影響很大)。還有快取層,但快取層更重要的是容量的設計(即記憶體總量),因此,要對各個架構元素容量的資料有一定了解,才能保證構造出的架構在容量上不會出問題。

未考慮高可用

如果架構設計的時侯只想著怎樣實現業務邏輯,完全沒有考慮主機當機了怎麼解決,那麼遲早會遇到事故。因此,架構需要從入口層、業務層、快取層和資料庫層構建高可用和可伸縮系統。例如,在入口層使用Keepalived;業務層不要有狀態,將狀態儲存到快取層或資料庫;快取層考慮擋住絕大部分服務請求以提升系統整體容量,但同時也要考慮高可用的問題;資料庫層做一個主從模式 一文有詳細講述。架構設計重要的是有考慮高可用的意識,有意識以後再考慮如何實現就會比較容易。

用Hash來避免機器當機時影響到所有使用者

這個問題主要由於想做高可用,但卻用了錯誤的方法。比如有很多使用者,根據使用者的Hash把它們分到不同的伺服器,這樣單臺伺服器宕掉的時侯就不會影響到所有的業務。但這種方法並不夠好,因為即使小部分使用者的體驗受到了影響,也已經構成事故。另外,如果服務分很多層,這層做高可用漏掉一部分客戶,另一層漏掉另外一部分客戶,那麼整體的可用性會變得很差,出故障的機率就是各層出故障機率之和。目前有很多更簡單的方式來做高可用,所以沒有必要使用Hash這種方式。另外,用Hash來分散請求比較容易導致壓力不均,反而降低了整個系統的容量。

快取節點數太少

很多人認為快取是一個可選的環節,在設計上就比較隨意,但這會帶來一定的問題。比如一個快取節點宕掉,將導致這個快取節點的壓力壓到資料庫上面。如果系統的容量原本就是靠快取支撐,快取又只分布在兩臺機器上,那麼宕掉一臺對後面的資料庫的壓力很大,資料庫響應變差,那麼宕掉快取節點也就意味著服務真的當機。因此,建議將快取儘量分開,比如和業務伺服器混合部署,當業務伺服器在增長時,快取也在增長,這時保證快取節點多一點,單臺快取機當機了壓力到了資料庫也不會導致資料庫當機。當然,Codis這類自帶高可用的快取系統也是一個很好的選擇。

有容災無容錯

首先,應分清容災和容錯的差別。容災指,出了事故(如單磁碟故障、單資料故障、機櫃故障或者機房故障)時的保障措施。容錯則指,操作失誤(如運維的錯誤操作),這種錯誤操作導致了資料丟失,或者別人透過SQL隱碼攻擊的方法刪除了資料庫。身邊有一個真實的例子,一家公司用MongoDB資料庫,由於MongoDB的ReplicaSet機制,所以覺得不用做備份了,就未做備份。但這裡他們沒有考慮到,如果有人失手刪除了資料庫該怎麼辦,這時所有資料都丟掉了,是一件非常恐怖的事情。

架構失配的問題

MongoDB支援檔案儲存,但它並不擅長,容量會受到很大的限制,一旦上傳量增大就可能會引發事故。因此,最好在各個環節找一些最恰當的方式。例如,Redis擅長的是快取而不是資料庫,那麼用Redis做資料庫就必然會出現架構失配的問題;而MongoDB擅長的是OLTP,用MongoDB去支撐資料倉儲就不太合適;像MySQL這類事務型資料庫也可以去做一些離線計算,但如果要做很多離線計算的工作,就需要用最好的工具去做(如Hadoop、Hive、Spark等),在每一個架構環節都要有最合適的架構元件,避免出現一些架構失配的問題。

資料流太長

這種情況常出現於儲存領域。資料流太長就很難保證響應,如果一份資料中轉了10次,與中轉3次相比,內網的頻寬需求相差好幾倍,整個系統的容量明顯下降,更容易出現內網阻塞。在這種情況下,將資料流縮短,就可以得到比較顯著的效能提升。縮減資料流長度的方式非常有效,值得考慮。此外,還可以利用一些資料流最佳化方法。例如,一份資料需要寫三份,一種做法是由發起機器併發地發三份資料到三臺對應的機器上,但是這種方法對發起機器來講,流量壓力比較大。反之,如果要將資料發到A、B、C三臺機器,先發給A,然後由A轉發給B,再由B轉發給C,雖然架構上會複雜一些,但是效能和容量提升也都很可觀。

以上是架構設計時常出現的一些問題,關於“架構壞味道”還有更多細節的點和總結值得探討,希望此文能給開發者們帶來一定的幫助,也望以後能與大家做更充分的交流。

原文連結:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2983/viewspace-2811237/,如需轉載,請註明出處,否則將追究法律責任。

相關文章