讀書筆記:《大型網站系統與Java中間件實踐》

大型網站演進

在這裏插入圖片描述

  1. 單機扛不住 , 上集羣
  2. 集羣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.線程池。

《大型網站系統與Java中間件實踐》

發佈了118 篇原創文章 · 獲贊 47 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章