菜鸟架构笔记:上部
目錄
- 從零開始學架構
- 李運華|著
- 程序設計與架構設計
- 架構即人性!切勿好大喜功。
- 組件與模塊
- 框架Framework和架構Architecture
- 高**的誤區
- 以史為鑒
- 架構設計的主要目的
- 高屋建瓴,有的放矢,而非貪大求全
- 任務分配器與業務服務器
- 系統的高可用
- 數據+邏輯=業務
- CAP定理
- 高可用狀態決策
- 可擴展性
- 創新
- 安全
- 規模
- 名詞解釋
- 規范
- 建筑
- 備選方案
- 關系數據庫
- CAP
- CAP理論的實踐
- 正常情況下,不存在CP和AP的選擇(即:當P可以舍棄時),可以同時滿足CA。
- 分區期間(一年可能5分鐘(4個9)、50分鐘(5個9))
- BASE
- FMFA(Failure mode and effects analysis)故障模式與影響分析
- 存儲高可用
- 主備倒換(主讀寫,備備份)與主從倒換(主讀寫,從讀)
- 開源的數據集中集群
- 數據分散集群
- 分布式事務算法
- 分布式一致性算法
- 數據分區
- 復制規則
- 計算高可用
- 主備
- 主從
- 對稱集群與非對稱集群
- 業務高可用
- 異地多活設計步驟
- 3.數據同步
- 4.異常處理
從零開始學架構
照著做,你也能成為架構師
李運華|著
技術成就夢想,堅持就能成功
程序設計與架構設計
程序設計的關鍵思維是邏輯和實現。
架構設計的關鍵思維是判斷和取舍。
架構即人性!切勿好大喜功。
三大原則:
《UNIX編程藝術》Kiss:KeepItSimple,Stupid!
系統是其內部的諸多有關聯的個體按照相應的規則
運行出的具備新的能力的東西。
組件與模塊
從邏輯的角度來拆分系統得到的單元是模塊
從物理的角度來拆分系統得到的單元是組件
劃分模塊的主要目的是職責劃分
劃分組件的主要目的是單元復用
component組件,零件,屬于物理范疇。
框架Framework和架構Architecture
不同角度理解問題,所抽象出的概念是不同的。
高**的誤區
不能一味的追求高性能、高可用和高擴展!
Done is better than perfect!
以史為鑒
探索一個事務的目的,最好的方式就是去追尋這個事物出現的
歷史背景和推動因素。
屁股決定腦袋,位置決定想法。
事物的量級達到一定程度后,問題也會***變質***。
模塊、對象再到組件,差別是隨著軟件的復雜度不斷增加,拆分
的粒度越來越粗,拆分的角度越來越高。
架構設計的主要目的
是為了解決復雜度帶來的問題。
低成本是架構設計的附加約束。
高屋建瓴,有的放矢,而非貪大求全
不同架構應該針對不同的復雜點。
任務分配器與業務服務器
任務分配隨著量級的增加,性能損耗越來越高,整體收益會大打折扣。
任務分解,拆大為小,進而更容易找到關鍵性能點進行突破,且不會
牽一發而動全身,方便調優。
拆分后的子系統之間交流也有成本,所以拆分的粒度要適度。
系統的高可用
通過冗余實現無中斷。相當于功能備份。
存儲高可用的難點不在于如何備份數據,而在于如何減少或規避數據不一致
對業務造成的影響。
數據+邏輯=業務
即便是毫秒級別的傳輸延時,也會照成數據的不一致,進而導致業務出現問題。
CAP定理
consistency
available
partitionTolerance
存儲高可用不可能同時滿足一致性、可用性、分區容錯性,最多滿足
其中兩個,在做架構設計時要結合業務進行取舍。由于網絡延時等不可避免,
所以通常在一致性與可用性之間進行取舍。
高可用狀態決策
獨裁式:一個決策者與多個上報者
協商式:主從通信問題
民主式:投票選舉,腦裂混亂問題
可擴展性
設計模式
正確預測變化,完美封裝變化。
唯一不變的是變化
變與不變,穩定層與變化層的確立。
創新
小公司引入新技術,大公司創造新技術。
安全
功能上的安全,在攻與防的矛盾中逐步完善。
架構上的安全
防火墻一般不適用海量用戶訪問與高并發。
運營商或云服務商具備強大的帶寬和流量清洗能力。
規模
規模的線性增加帶來的是復雜度的指數增加。
數據越來越多,系統復雜度也會由量變帶來質變。
大數據的三架馬車。
傳統mysql推薦單表5000萬行左右。
名詞解釋
CDN:Content Delivery Network
GSLB:Global Server Load Balance
規范
憑借個人經驗與感覺設計架構。
積累自己的儲備庫。
大公司具備的平臺、資源和積累是架構衍生的關鍵。
環境逼迫創新。
情境激活靈感。
建筑
對于建筑來說,永恒是主題。
對于軟件來說,變化是主題。
條條大路通羅馬,要綜合選擇。
備選方案
3-5個
幾乎沒有無暇的方案
如果你有一把錘子,那么所有的問題在你看來都是釘子。
不要被既有經驗局限。
備選階段關注技術選型,而不是技術細節。
360度環評:最簡派、最牛派、最熟派、領導派
極端情況的出現畢竟是小概率事件,留有較多余力的時候再去考慮。
舉例:
1.橫向擴展
2.系統拆分
不同的方案,面對不同的公司情況,考慮問題的側重點應該不同。
權值的設定應該依具體情況而定。
按優先級選擇。
詳細方案的設計階段可能顯露出備選方案中遺漏的關鍵點,進而導致
備選方案全局否定。架構師應該在早期看的更深入。
海納百川,博采眾長。
關系數據庫
高性能數據庫集群:
- 讀寫分離:將訪問壓力分散到多個節點。主機讀寫,從機讀操作。
主從復制延遲問題:
1.寫操作后的讀操作指定發給主機。
2.從機讀取失敗后再讀一次主機,二次讀取會增加主機壓力。
3.關鍵業務全部指向主機,非關鍵業務由從機完成。 - 分庫分表:既分散訪問壓力,又分散存儲壓力。
join操作問題:無法使用join
事務問題:分布式事務解決方案性能不高。
成本問題:業務分庫一般后期進行。前期業務規模小且不穩定。 - 單表數據拆分的兩種方式:
垂直拆分:不常用的字段剝離出去。
水平拆分:如果單表行數超過5000萬,相對來說可以考慮拆分。
范圍路由:單表水平分段建議100萬到2000萬之間。
最后一張表可能導致分布不均。
Hash路由:所有表分布均勻,但后期擴充要重分布。
配置路由:記錄拆分信息,利于擴充,但多一次查詢。
拆分難點:粒度選取。
舉例:count()
拆分后的多個表求總記錄數,需要把每張表的count()
累加求和,性能會受到影響。引入記錄數表記錄當前表
的行數,又會導致同步更新的問題,復雜度增加。
order by操作無法進行,需要單表排序后引入中間件匯總排序。 - 讀寫分離實現:
程序代碼封裝:實現簡單,但每個語言都需要自己實現一次,無法通用。
如:TDDL(Taobao Distributed Data Layer)頭都大了!
中間件封裝:數據庫中間件對業務服務器提供的是標準SQL接口。
實現復雜,主從切換服務器無感知。
如:mysql-proxy、mysql-router、奇虎360的Atlas。 - NoSQL
關系數據庫的缺點:
1.無法存儲數據結構,存儲的是行記錄。
2.schema擴展不方便。擴充列導致表長時間鎖定。
3.大數據場景下IO較高。即使是對某一列進行統計,
關系數據庫也會將整行進行讀取。
4.且全文搜索能力比較弱。
NoSQL!= no sql 而是 NoSQL = Not only sql
針對上述缺點常見的NoSql方案:
1.k-v存儲:Redis
2.文檔數據庫:MongoDB
3.列式數據庫:HBase
4.全文搜索引擎:Elasticsearch
1.Redis事務只支持I(是單進程單線程的工作模式)和C,不支持
A(不支持回滾)和D.
2.no-schema的文檔數據庫,如JSON數據是自描述的,無需在使用前
定義字段,讀取一個JSON中的不存在的字段也不會導致SQL的語法錯誤。
JSON比起先要執行DDL的關系數據庫要方便更多。但某些對事務要求嚴格
的業務場景是不能使用文檔數據庫的。通常可以sql+noSql組合使用。
3.行式存儲可以同時高效讀取多個列,也可以同時在一行中對多個列進行
寫操作。但在海量數據進行統計的場景中并不適用。普通行式數據庫一般
壓縮率在3:1到5:1左右,而列式數據庫壓縮率一般在8:1到30:1左右。
4.全局搜索引擎技術原理:倒排索引。
正排索引:根據文檔名稱來查詢文檔內容。
倒排索引:根據關鍵詞來查詢文檔內容。
全文搜索引擎的索引對象是單詞和文檔,而關系數據庫的索引對象是鍵和行。
全文搜索引擎在支持關系型數據全文搜索時需要JSON(不唯一)與表對應轉換。
Elasticsearch是分布式的文檔存儲數據庫。它能存儲和檢索復雜的數據結構
————序列化稱為JSON文檔————以實時的方式。在Elasticsearch中,每個字
段的所有數據都是默認被索引的。即每個字段都有為了快速索引設置的專用倒
排索引。而且,不像其他多數的數據庫,它能在相同的查詢中使用所有的倒排
索引,并以驚人的速度返回結果。 - 緩存
將可能重用的數據放到內存中,一次生成,多次使用,避免每次使用都去訪問
存儲系統。
緩存穿透:故意訪問不存在的數據,空值替代。
生成緩存耗費時間和資源,當競爭對手故意爬取所有分頁時(通常
緩存前10頁比如),會拖慢整體。
緩存雪崩:緩存失效后引起系統性能極具下降。
解決方法:1.更新鎖機制:加鎖保證只有一個線程進行緩存更新。
2.后臺更新機制:后臺線程更新緩存而不是由業務線程更新緩存。
緩存本身的有效期設置為永久,后臺線程定時更新緩存。
定時讀取:頻繁查看被踢的數據,及時更新空值。
消息隊列通知:業務線程發現緩存丟失主動發消息
通知后臺線程更新緩存。相對簡單,且可以用于系統
預熱。
緩存熱點:某明星大咖的消息復制多份緩存,緩解服務器壓力。
PPC:Process per Connection,每次有new connection,then fork a new process. - some problems:
performance.
- solvable method:
1.prefork,which needs system solve “驚群” phenomenon.
2.TPC:Thread per Connection.
3.進程池:
read操作改為非阻塞,然后進程不斷地輪詢多個連接,
但這并不優雅,且連接達到幾千上萬的時候,效率低下。
4.I/O多路復用結合線程池:Reactor 即:反應堆(事件反應)非阻塞
同步網絡模型
當多個連接共用一個阻塞對象后,進程只需要在一個阻塞對
象上等待,而無需再輪詢所有的連接。
當某條連接有新的數據可以處理時,操作系統會通知進程,
進程從阻塞狀態返回,開始進行業務處理。
Reactor模式也稱為Dispatcher模式,即:I/O多路復用
統一監聽事件,收到事件后分配給某個進程。
實用類型:單Reactor單進程/單線程。
單Reactor多線程。
多Reactor多進程/線程。
上述具體線程還是進程依具體編程環境及平臺有
關。java一般使用多線程。
5.Proactor 前攝器 類比proactive主動的,主動器
Reactor:來了事件我通知你,你來處理。
Proactor:來了事件我來處理,處理完了我通知你。
解釋:”我“是操作系統,”事件“是新的連接、有數據可讀、數據可寫。
流程:
1.Proactor Initiator負責創建Proactor和Handler,并
將Proactor和Handler都通過Asynchronous Operation
Processor注冊到內核。
2.Asynchronous Operation Processor負責處理注冊請
求,并完成I/O操作后通知Proactor。
3.Asynchronous Operation Processor完成I/O操作后
通知Proactor。
4.Proactor根據不同的事件類型回調不同的Handler進行
業務處理。
5.Handler完成業務處理,Handler也可以注冊新的
Handler到內核進程。
目前windows下采用IOCP,而linux采用Reactor模式為主
因為linux下的AIO并不完善。
集群高性能:負載均衡不只是為了計算單元的負載達到均衡狀態,而是一種綜合的考慮。 - DNS負載均衡
地域級別的均衡。就近原則。 - 硬件負載均衡
集群級別負載均衡。昂貴,擴展能力大。 - 軟件負載均衡
機器級別負載均衡。通過軟件實現負載均衡功能。 - 負載均衡算法
任務平分類:輪詢
負載均衡類:權重輪詢
性能最優類:按服務器性能分配,適當概率判斷服務器性能
Hash類:同IP或者同session id歸屬到同一服務器
CAP
- What is Partition Tolerance?
System continues to work despite message loss or partial failure.
The System will continue to function when network partitons occur.
- What is CP?當發生分區時,返回錯誤。
- What is AP?當發生分區時,返回錯誤值。
CAP理論的實踐
- 需要將系統內的數據按照不同的應用場景和要求進行分類,每類數據選擇不同的的策略。
- 比如:用戶信息數據選擇AP,而用戶賬號數據選擇CP。
- AP相當于是放寬了一致性的要求,可用就好。CP由于追求強一致性而導致不可用情況發生。
- CAP是忽略網絡延遲的。有時強一致性的要求導致只能單點寫入,其他節點備份,無法做到分布式情況下多點寫入。但并不意味著系統無法應用分布式架構,可以兩個節點各自負責一半業務,同時備份另一半。這樣即便其中一個節點發生故障,也只是影響一半的用戶。
正常情況下,不存在CP和AP的選擇(即:當P可以舍棄時),可以同時滿足CA。
- 此情況我們需要考慮分區發生情況下的CP與AP的選擇,同時也要考慮P沒有發生情況下的CA的實現。
- 不同的數據CA實現方式可能不一樣,比如:用戶賬號數據可以采用消息隊列,因為可以比較好的控制實時性。而用戶信息數據可以采用數據庫同步的方式來實現,因為實現簡單。
分區期間(一年可能5分鐘(4個9)、50分鐘(5個9))
- 分區發生,則記錄相關日志。
- 分區故障解決后,系統根據日志進行數據恢復。
- CAP關注的粒度是數據,而不是整個系統。
BASE
- Basically Available 登錄比注冊重要。
- Soft State 允許數據存在中間狀態(CAP理論中的數據不一致),但不影響系統整體可用性。
- Eventual Consistency 系統中的所有副本經過一定時間后,最終能夠達到一致性的狀態。是對AP方案的一個補充。
FMFA(Failure mode and effects analysis)故障模式與影響分析
- 是一套分析和思考的方法,應用于各個領域。
- 像登錄、注冊才是功能點。
- 故障模式關注現象和對應影響,即便原因不同。盡量使用量化描述,而非泛化。
- 對于故障現象,殊途同歸,殊因同果,應不同對待。
存儲高可用
主備倒換(主讀寫,備備份)與主從倒換(主讀寫,從讀)
- 問題關鍵點:狀態判斷、倒換決策和數據沖突修復。
- 互連式與中介式(MongoDB(A)),還有模擬式(將備機模擬為客戶端進而判別主機狀態)。
- 主主倒換需要雙向復制。
開源的數據集中集群
- ZooKeeper,ZAB協議,開源
數據分散集群
- 均衡性
- 容錯性
- 可伸縮性
- Hadoop,Namenode是一個中心服務器,負責數據分區的分配。HDFS,master/slave.
分布式事務算法
- 2PC(Two-phase commit protocol)
- 提交請求階段,看看是否有No存在,都yes則提交執行階段。
- 強一致性算法,簡單,但不好用。
- 3PC(Three-phase commit protocol)
- 在2PC中間插入一個準備階段。
分布式一致性算法
- Paxos,state machine replication(active replication)各個節點間復制操作
- Raft,state machine replication(active replication)
- ZAB,primary backup(passive replication)Leader節點執行操作,將執行結果復制給其他節點。
數據分區
- 地理級別重大災害規避風險。每個區域負責一部分數據。
- 國家洲際間分區僅作為備份,而城市之間由于延遲低、業務相似,分區同時適合對外提供服務。
復制規則
- 集中式 所有分區將數據備份到備份中心。
- 互備式 形成閉合鏈,但如何加入新的一環。
- 獨立式 一對一,不同區域。
計算高可用
主備
冷備(未啟動)與 溫備(已啟動)
主從
從機也干活,主機有故障,從機升級主機(一般升級配置),新增從機。
對稱集群與非對稱集群
業務高可用
- 異地多活,把雞蛋放到多個籃子里。
- 優先實現核心業務的異地多活架構!
- 物理(地理等)因素導致無法很快。所以取舍:核心數據最終一致性。采用多種手段,保證絕大部分用戶的核心業務異地多活!
- 保證最終一致性,不保證實時一致性。
異地多活設計步驟
- 1.業務分級,根據不同標準不同情境(核心、訪問量、盈利)區分業務。
- 2.數據分類,根據(數據量、唯一性、實時性、可丟失性、可恢復性)
3.數據同步
- 存儲系統同步(延遲高)
- 消息隊列同步(無事務性和無時序性業務)
- 重復生成(如:cookie、session)
4.異常處理
- 多通道同步
- 同步和訪問結合:本地沒有去其他接口找。
- 日志記錄
- 用戶補償
總結