一篇帶給你架構師常用術語梳理
大家好,歡迎來到Tlog4J課堂,我是Jensen。
大家或許會很好奇——架構師關注的點到底在哪里?平時具體應用到的“術語”有哪些?
在這里,我整理一份架構師技術語言,希望大家看完以后可以逆向推導出架構師需要關注的重點,掌握了這些技術語言,咱們可以在技術交流中,把它們作為有力的理論支撐依據。
架構技術的思維與衡量指標
一、ROI
ROI一般指投資回報率,投資回報率=年利潤或年均利潤/投資總額×100%,比如投入100元,獲得利潤10,000元,那ROI就是10,000/100*100%=10,000%,如果ROI小于100%,那意味著投入100元,獲得的利潤少于100元,大家都知道,這是一個不劃算的買賣。
此外,ROI可以作為企業生產的一個基礎指標,我們可以把ROI理解為投入產出比——在做任何決策之前,先考慮清楚這件事值不值得去做,我們可以通過經驗預判或數據分析得出結論,前輩告訴我們:在錯誤的方向上努力只會讓你輸得更慘,所以為什么說選擇比努力更重要,其中就是這個道理。
比如說,如果花費一個月時間去優化一個簡單的客服系統,只是為了讓客服體驗更好,并沒有對客戶留存、轉化交易起任何效果,也沒有大幅提升客服效率,那做這個事情就不劃算,ROI小于1,價值點不高。
當然,ROI指標的不足之處是缺乏全局觀念,因為我們還需要考慮投資的隱性回報,比如營銷部門在一次營銷活動中投放CPS信息流,投入總成本10萬元,共賺取利潤10萬元,并獲客1萬,單從金錢成本上看是沒有任何效益的,但這次營銷活動相當于免費獲客1萬,這些客戶后續是可以在商城內二次交易的,那么從全局上看,總的ROI就大于100%。
ROI在架構上常用于判斷技術決策、項目決策等等在當前階段值不值得投入人力、時間成本去執行。
二、SOLID
SOLID原則包括以下五個:
1、單一職責原則(SRP)
表明一個類有且只有一個職責。一個類就像容器一樣,它能添加任意數量的屬性、方法等。
2、開放封閉原則(OCP)
一個類應該對擴展開放,對修改關閉。這意味一旦創建了一個類并且應用程序的其他部分開始使用它,就不應該修改它。簡單地說:就是當別人要修改軟件功能的時候,使得他不能修改我們原有代碼,只能新增代碼實現軟件功能修改的目的。
3、里氏替換原則(LSP)
派生的子類應該是可替換基類的,也就是說任何基類可以出現的地方,子類一定可以出現。值得注意的是,當通過繼承實現多態行為時,如果派生類沒有遵守LSP,可能會讓系統引發異常。
4、接口隔離原則(ISP)
表明類不應該被迫依賴他們不使用的方法,也就是說一個接口應該擁有盡可能少的行為,它是精簡的,也是單一的。
5、依賴倒置原則(DIP)
表明高層模塊不應該依賴低層模塊,相反,他們應該依賴抽象類或者接口。這意味著不應該在高層模塊中使用具體的低層模塊。
我們就來盤一盤他們之間的關系:
- 單一職責是所有設計原則的基礎,開閉原則是設計的終極目標。
- 里氏替換原則強調的是子類替換父類后程序運行時的正確性,它用來幫助實現開閉原則。
- 而接口隔離原則用來幫助實現里氏替換原則,同時它也體現了單一職責。
- 依賴倒置原則是過程式編程與面向對象編程的分水嶺,同時它也被用來指導接口隔離原則。
簡單來說,就是——
依賴倒置原則告訴我們要面向接口編程;當我們面向接口編程之后,接口隔離原則和單一職責原則又告訴我們要注意職責的劃分,不要什么東西都塞在一起;當我們職責捋得差不多的時候,里氏替換原則告訴我們在使用繼承的時候,要注意遵守父類的約定;而上面說的這四個原則,它們的最終目標都是為了實現開閉原則。
三、拆分/解耦思維
拆分常用于描述組織拆分、業務拆分、數據拆分、服務拆分等,其中的拆分依據和拆分粒度是我們需要關注的重點,也就是說——為什么這么拆?要拆成什么樣才算合理?
“合起來不是挺好的嗎,為什么要拆?拆了還會有一堆問題,整體復雜度還變高了!”
乍一聽覺得這么質疑挺合理的,但咱們從整體上考慮,或許就變得不那么合理了。
我們從團隊、產品、交付、技術以及業務方面分析一下系統拆分的需求:
1、組織結構變化
從最初的一個團隊逐漸成長并拆分為幾個團隊,團隊按照業務線不同進行劃分,為了減少各個業務系統和代碼間的關聯和耦合,幾個團隊不再可能共同向一個代碼庫中提交代碼,必須對原有系統進行拆分,以減少團隊間的干擾。
2、安全性
這里所指的安全不是系統級別的安全,而是指代碼或成果的安全,尤其是對于很多具有核心算法的系統,為了代碼不被泄露,需要對相關系統進行模塊化拆分,隔離核心功能,保護知識產權。
3、替換性
有些產品為了提供差異化的服務,需要產品具有可定制功能,根據用戶的選擇自由組合為一個完整的系統,比如一些模塊,免費用戶使用的功能與收費用戶使用的功能肯定是不一樣的,這就需要這些模塊具有替換性,判斷是免費用戶還是收費用戶使用不同的模塊組裝,這也需要對系統進行模塊化拆分。
4、交付速度
單體程序最大的問題在于系統錯綜復雜,牽一發而動全身,也許一個小的改動就造成很多功能沒辦法正常工作,極大的降低了軟件的交付速度,因為每次改動都需要大量的回歸測試確保每個模塊都能正確工作,因為我們不清楚改動會影響到什么,所以需要做大量重復工作,增加了測試成本,這時候就需要對系統進行拆分,理清各個功能間的關系并解耦。
5、技術需求
1)單體應用由于技術棧固定,尤其是比較龐大的系統,不能很方便地進行技術升級,或者說對引入新技術或框架等處于封閉狀態,而每種語言都有自己的特點,單體程序沒有辦法享受到其它語言帶來的便利,對應到團隊中,團隊技術相對比較單一。
2)相比于基于業務的垂直拆分,基于技術的橫向拆分也很重要,使用數據訪問層可以很好的隱藏對數據庫的直接訪問、減少數據庫連接數、增加數據使用效率等;橫向拆分可以極大地提高各個層級模塊的重用性。
6、業務需求
由于業務上的某些特殊要求,比如對某個功能或模塊的高可用性、高性能、可伸縮性等方面的要求,雖然也可以將單體整體部署到分布式環境中實現高可用、高性能等,但是從系統維護的角度來考慮,每次改動都要重新部署所有節點,顯然會增加很多潛在的風險和不確定性因素,所以有時候不得不選擇將那些有特殊要求的功能從系統中抽取出來,獨立部署和擴展。
從更大的范圍來看,拆分可以分為兩種:縱向和橫向。
縱向拆分主要從業務角度進行,根據業務分割為不同的子系統;而橫向拆分側重于技術的分層,每個層級的技術側重點不同,可以充分發揮和培養團隊中每個人的技術特長。
四、隔離思維
我們再來聊聊隔離思維,我們做技術的一定要有隔離思維,不要把多件事情混為一談,這樣我們才能聚焦重點。
隔離設置,源于輪船的設計,在輪船設計中,我們常常會設計多個船艙,每個船艙都是獨立的空間,這樣子,當輪船在行駛過程中,即便某個船艙遭受破壞進水,也有船艙能夠正常工作,從而保證整個輪船不會沉沒。
每一位架構師、程序員、運維工程師都必須懂得隔離設計,在分布式系統中,隔離設計的實現有兩種不同的方式,一是系統隔離,二是用戶隔離。
1、系統隔離
在分布式系統中,我們常常把不同的模塊部署到不同的機器上面,避免不同的模塊彼此之間受到影響(每臺計算機的資源都是有限的,特別是IO密集型、CPU密集型的模塊,容易拖垮其他業務)。
除此之外,我們還要對底層的存儲與上層的接入層進行分離。
在實際的應用中,我們通常會對不同的不同業務的存儲進行數據庫拆分,而在接入層,常常為了節約成本,而使用限流設計。
2、用戶隔離
另外一種方式,我們常常根據用戶進行隔離,不同的用戶訪問不同的運行實例,這種在大型互聯網公司也是非常常見的,例如阿里巴巴有北京、上海、杭州、深圳等多個不同的數據中心,不同的用戶訪問不同的系統實例。
不同的用戶群訪問不同的實例群,可以讓隔離做得更加徹底,但同時也是伴隨著非常大的挑戰,比如我們會面臨著存儲、不同實例間的通信等多種問題。
而隔離的底層邏輯,映射到計算機系統層面,都是對CPU、內存、網絡、IO或存儲層面的隔離,避免計算機資源互相干擾。
在我們日常的技術交流中,我們通過隔離性來判斷業務、系統以及代碼之間會不會互相產生影響、系統的邊界是否清晰,最終讓我們實現的系統更加穩定。
五、ACID
ACID指的是事務的四個特征,分別是原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation) 和持久性(Durability),簡稱為事務的ACID特性,狹義的ACID指的是數據庫事務的ACID。
1、原子性(Atomicity)
一個事務必須被視為一個不可分割的最小工作單元,整個事務中的所有操作要么全部提交成功,要么全部失敗回滾,不可能停滯在中間某個環節,對于一個事務來說,不可能只執行其中的一部分操作。
2、一致性(Consistency)
數據庫總是從一個一致性的狀態轉換到另一個一致性的狀態。
3、隔離性(Isolation)
通常來說,一個事務所做的修改在最終提交以前,對其他事務是不可見的(在并發環境中,并發的事務是相互隔離的,事務之間互不干擾),隔離性可以防止多個事務并發執行時由于交叉執行而導致數據的不一致。
針對不同的業務需求,隔離性分為4個級別:讀未提交、讀已提交、可重復讀、串行化。
這4個級別的隔離性依次增強,事務隔離級別越高,就越能保證數據的完整性和一致性,但同時對并發性能的影響也越大。
4、持久性(Durability)
通常來說,一旦事務提交,則其所做的修改會永久保存到數據庫,即使系統崩潰,修改的數據也不會丟失。
在我們的實際應用中,我們大可以通過數據庫事務的ACID特性來滿足實際業務場景,所以咱們做技術的一定要把ACID牢記于心,隨時調用。
六、CAP、BASE
有一句話不知道大家有沒有聽過,叫做“CAP走天下”,CAP為何如此重要呢?
這里先科普一下:
CAP定理表示在分布式系統中的三大特性:一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance),三者之間形成一個不可能三角,即在一個分布式系統內不能同時滿足強一致、高可用和分區容錯。
CAP定理
CAP定理在分布式架構上指導我們,系統應該如何在CP和AP中進行權衡,因為分布式系統做了分區,一定是先滿足分區容錯性的。
比如說常用的分布式配置中心與服務注冊中心,我們允許系統之間存在短暫的數據不一致,也要保證系統的高可用,以免影響系統的正常運作,所以這種分布式系統可以采用AP+最終一致的方案去設計;至于涉及到交易場景的業務,比如銀行轉賬這類交易場景,以CP的方式去設計更加嚴謹。
那CP系統就不能保證高可用了嗎?當然不是。
咱們對于可用性也有別的方法去實現,比如在CP之上嵌套使用AP系統負責CP系統的高可用,在一個大型分布式系統中,都是CP+AP相互結合使用的。
那BASE又是什么呢?
BASE理論是Basically Available(基本可用),Soft State(軟狀態)和Eventually Consistent(最終一致性)三個短語的縮寫,它是對CAP定理中一致性和可用性權衡的結果,其來源于對大規模互聯網分布式系統實踐的總結。
BASE理論的底層邏輯是這樣的:通過基本可用、軟狀態來犧牲CAP中的可用性,通過最終一致性來犧牲CAP中的強一致性。
BASE是基于CAP逐步演化而來的:即使無法做到強一致性,但應用可以采用適合的方式達到最終一致性,CAP中提到的一致性是強一致性,所謂“犧牲一致性”指犧牲強一致性保證弱一致性。
七、分布式事務
隨著架構的演進,系統與數據庫進行了不同程度的拆分,系統之間由進程內通訊變成通過網絡IO通訊,相應地,事務的ACID也被散落到各個單體應用中,不再能夠服務于有ACID需求的業務場景。
我們此時就需要有一個能滿足ACID特性的分布式事務解決方案,來解決業務場景。
怎么辦呢,數據庫的ACID是在進程內通訊的,因為在一個單體應用中,這很好辦到,那在分布式系統也可以做到類似的設計,區別在于通訊方式由進程內通訊變成了網絡IO通訊,由此前輩們提出了一些分布式事務解決方案。
我們把事務的范圍上升到分布式系統的一個“上帝視角”,那么單體事務就變成了全局事務,以下是X/Open組織提出的DTP模型:
DTP模型
在DTP分布式事務模型中,XA規范除了定義的RM-TM交互的接口,即TM與數據庫之間的接口規范,TM還用它來通知數據庫事務的開始、結束以及提交、回滾等;而XA接口函數由數據庫廠商提供。
分布式通信協議XA規范:
- 第一步:AP創建了RM1 RM2的JDBC連接。
- 第二步:AP通知生成全局事務ID,并把RM1 RM2注冊到全局事務ID。
- 第三步:執行二階段協議中的第一階段prepare。
- 第四步:根據第一階段中的prepare情況,決定整體提交或回滾。
在XA規范中大致分為兩部分:事務管理器和本地資源管理器。
其中本地資源管理器往往由數據庫實現,比如Oracle、DB2這些商業數據庫都實現了XA接口,而事務管理器作為全局的調度者,負責各個本地資源的提交和回滾。
兩階段提交(2PC)、三段式提交(3PC)就是基于XA規范落地的,此外還有TCC協議,也能滿足我們實際的業務場景。
八、系統容量預估
系統容量指系統所能承受的最大訪問量,而系統容量預估則是在峰值流量到達之前系統架構師所給出的若干技術指標值,它是架構師必備的技能之一。
常用的技術指標值有:QPS、PV、UV、并發量、帶寬、CPU使用率、內存硬盤占用率等。
QPS(Query Per Second)表示每秒查詢量,在分布式系統中 QPS 的定義是,單個進程每秒請求服務器的成功次數,QPS一般可以通過壓力測試工具測得,例如 LoadRunner、Apache JMeter、NeoLoad、http_load等。
QPS = 總請求數 / 進程總數 / 請求時間 = 總請求數 / ( 進程總數 * 請求時間 )
UV(Unique Visitor)表示獨立訪客數量,指一定時間范圍內站點訪問所來自的IP數量,同一IP多次訪問站點只計算一次,一般以24小時計算。
PV(Page View)表示頁面訪問量,指一定時間范圍內打開或刷新頁面的次數,一般以24小時計算。
那并發量、帶寬這些具體有沒有可量化的公式呢?答案是YES。
1、帶寬計算
平均帶寬的計算公式為:
平均帶寬 = 總流量數(bit) / 產生這些流量的時長(秒)=(PV * 頁面平均大小 * 8) / 統計時間(秒)
公式中的 8 指的是將 Byte 轉換為 bit,即 8b/B,因為帶寬的單位是 bps(比特率),即bit per second,每秒二進制位數,而容量單位一般使用 Byte。
假設某站點的日均 PV 是 10w,頁面平均大小 0.4 M,那么其平均帶寬需求是:
平均帶寬 = (10w * 0.4M * 8) / (60 * 60 * 24) = 3.7 Mbps
以上計算的僅僅是平均帶寬,我們在進行容量預估時需要的是峰值帶寬,即必須要保證站點在峰值流量時能夠正常運轉。
假設峰值流量是平均流量的5倍,這個5倍稱為峰值因子,按照這個計算,實際需要的帶寬大約在 3.7 Mbps * 5=18.5 Mbps 。
帶寬需求 = 平均帶寬 * 峰值因子
2、并發量計算
并發量,也稱為并發連接數,一般是指單臺服務器每秒處理的連接數。
平均并發連接數的計算公式是:
平均并發連接數 = (站點 PV * 頁面平均衍生連接數)/(統計時間 * web 服務器數量)
頁面平均衍生連接數是指,一個頁面請求所產生的 http 連接數量,如對靜態資源的 css、 js、 images 等的請求數量,這個值需要根據實際情況而定。
例如,一個由5臺web主機構成的集群,其日均PV是50w,每個頁面平均30個衍生連接,則其平均并發連接數為:
平均并發量 = (50w * 30) / (60 * 60 * 24 * 5) = 35
若峰值因子為 6,則峰值并發量為:
峰值并發量 = 平均并發量 * 峰值因子 = 35 * 6 = 210
3、服務器預估量
根據往年同期活動獲得的日均 PV、并發量、頁面衍生連接數,及公司業務擴展所帶來的流量增長率,就可以計算出服務器預估值。
服務器預估值 = 站點每秒處理的總連接數 / 單機并發連接數 = (PV * 頁面衍生連接數*(1 + 增長率)) / 統計時間 / 單機并發連接數
注:統計時間,即 PV 的統計時間,一般為一天。
寫在最后
本文簡單梳理了一些常用架構師術語,并沒有深入展開去聊,只為打開大家的技術視野,僅憑短短一個篇幅是不足以了解技術全貌的。