文章目錄
大型網站演進
- 單機扛不住 , 上集羣
- 集羣session問題
1.hash(key)到固定的單機節點上,讓其保持session
如果一臺web服務器故障,則會話丟失。需要登錄。
2.session複製
將session複製到其他節點上。
a.同步session增加網絡帶寬。
b.增加內存消耗。
3.session集中存儲
redis存儲。
好處:web之間沒了session複製,也不保存在本機了。
壞處:
a.讀寫session引入了網絡操作。
不過一般是Redis在內網, 還好。
b.存儲session的機器有問題,則影響應用。
4.Cookie Based
相當於每次 都自帶碗筷。
a.cookie長度。
b.安全性。
不能信賴前端傳來的數據,所以有加密解密。但是仍不安全。
c.帶寬消耗。
數據庫
讀問題
數據庫壓力變大,讀寫分離
1.數據庫作爲讀庫
2.搜索引擎作爲讀庫
加速數據讀取–緩存
1.數據緩存
2.頁面緩存
考慮局部熱點的問題。
擴容/縮容儘量平滑(一致性hash)
定時失效、變更時失效、變更時更新
寫問題
讀寫分離不能解決寫(主庫)問題
1.專庫專用,數據庫垂直拆分
交易、商品、用戶數據分開。
問題:引入了 分佈式事務的問題。
2.水平拆分
數據水平拆分就是把同一個表的數據,拆分到多個數據庫/表。
問題:
a.訪問數據 引入路由(到不同庫/表)
b.主鍵處理,不能簡單自增。
c.分頁出現問題。
應用應對的挑戰
跟數據庫拆分類似
a.從業務垂直拆分
訂單、物流、商品、用戶
b.也可以水平擴容
多臺訂單機器構建集羣,抗下單壓力
引入服務層(service)
引入消息中間件
引入服務層框架:
問題:網站規模擴大,開發人員增多,應用複雜、臃腫。
解決方案:應用拆小。
仍存在的問題:
數據庫連接數壓力還在。
系統之間存在重複代碼。
引入服務層:應用存在的問題 ,就繼續抽象一層。
將應用和底層數據庫、緩存系統、文件系統等系統之間增加了服務層。可以理解成服務層處理簡單、通用邏輯,並持久化到文件、數據庫中。
服務層的代表:dubbo
應用直接調用有網絡。
利用動態代理+反射生成代理對象,幫助序列化,網絡發送數據調用遠程應用,並反序列化結果。隱藏細節。
問題:
服務者集羣、調用者集羣,如何路由。
最初的路由尋址–找服務提供者
1.透明代理:lvs,eureka
2.從註冊中心找地址,再直連
基於服務提供者、接口、方法、參數來路由
避免負載不均衡。
多機房問題
其他機房也被當做同一集羣
解決:
1.根據調用者提供不同的服務者。
2.框架內部進行地址過濾,識別機房。
序列化與反序列化問題
儘量短小(節省帶寬)
壓縮與短小之間的平衡(cpu,網絡)
異步調用
1.拆分沒有前後依賴的服務,多線程異步調用。
2.不需要結果的,異步調用。
3.批量調用(類似mget)
4.fork/join
線程池隔離
避免某個接口阻塞後,影響應用內其他接口。
服務請求合併
服務提供者避免重複計算。
計算的時候加鎖,其他線程再次訪問則得到一個Future供之後獲取結果。
數據訪問層
數據拆分帶來的影響:
ACID
路由
join
分頁
自增ID
查詢跨庫
一致性的基礎理論–CAP/BASE
希望強一致,但是代價太大,最終一致就好了。
p:分區容忍性,系統部分有問題仍能運行。
放棄C,保留AP。最終一致。
如果強一致,單機。
或者類似於ZK寫入的時候,只要一半及以上同意就算寫入成功。
類似於MongoDB寫入的時候,一半及以上replication接收即可。
集羣內數據一致性算法
W+R>N 能保證強一致性
W+R<=N可以保證最終一致性
分佈式事務,考慮最終一致即可。
實現上來說通過補償不斷重試,而不是回滾。
或者TCC 應用層自行做抵消操作。
兩者可以合併
TCC+人工補償
多機的Sequence問題
水平分庫後,自增ID還是要保證:
唯一性
連續性
唯一性:
uuid
連續性:
1.單獨做一個id自增的管理器。
性能降低。
需要災備保證穩定。
2.應用指定ID段
擴庫join
1.多次查詢。
2.數據冗餘到單表上,避免join.
排序後分頁
1.考慮到所有數據可能都來自 一個數據源,所以分頁的時候在一個源中取足(size條)數據。
2.將所有數據源的數據組合排序,再取前size條。
消息中間件
功能
削峯削谷:
平滑處理消息。
異步:
快速返回。
解耦:
應用直接沒有直接聯繫,方便接入
消息一致性
jms通過XA解決
分階段-多次消息投遞
業務先發送到消息中間件標記爲待處理。
之後處理完業務後再發送到消息中間件,標記爲成功。(消息投遞)
不斷補償-最終一致
避免對消息中間件的強依賴
避免消息中間件掛掉後影響業務:
1.業務應用 將操作和需要入隊的消息 作爲一個事務,保證消息寫到【本地消息表】中。–一個事務保證完成。
2. 消息中間件/應用 輪詢 本地消息表去獲取消息,投遞到消息中間件中即可。–最終可靠
級聯、嵌套topic/queue
消息發送到中間件的可靠性保證(發送可靠)
持久訂閱、非持久訂閱
消息中間件返回成功才認爲 可靠消息到達中間件了,否則重發。
消息持久化到數據庫、文件。
消息投遞的可靠性保證(消費可靠)
得到消息,並處理成功才向 消息中間件 返回成功
業務沒處理完不能去確認消息(ack)
可能業務處理成功,但ack發送失敗,導致以爲失敗
業務繼續補償,但是冪等。直接ack,刪除消息中間件的消息。
消息者重複消費
1.重複發送到消息中心。
消息標記ID,同一ID無法重複發送。
2.應用端重複接收消息中心的消息。
應用端進行冪等操作。
避免投遞線程被阻塞
1.接受消息與處理消息分開。(類似於select+handler的boss線程與worker線程)
2.線程池。