分布式本地緩存


技術選型理由

Etcd

  1. Zookeeper 和Etcd 都是業界優秀的分布式協調系統,解決了分布式系統協調和元數據存儲。etcd 參考了 ZooKeeper 的設計和實現經驗,並從 Zookeeper 中汲取的經驗教訓用於優化自身架構,從而幫助其支持 Kubernetes 等大型系統。
  2. 解決服務發現,保證元數據變更后對集群中的每個實例的本地緩存進行更新
  3. 技術創新,使用業界認可的中間件,保持技術先進性。使用成熟后可覆蓋其他業務場景。

Guava cache

    業界和本部門很多應用都比較常用,基於jvm的內存緩存,適用於以下場景:

  1. 願意消耗一些內存空間來提升讀性能
  2. 鍵值會多次被查詢
  3. 內存適用總量不會超過jvm內容容量

對於分布式協調的應用場景沒有用redis、ducc、jmq因為這些中間件的應用場景的優勢不在於此。

 

 

改造一:業務數據本地緩存化,並通過分布式數據庫解決元數據一致性

目的

  1. 當前數據查詢先走redis緩存,為提高服務器利用率,遇突發流量時可以減少redis單分片的壓力
  2. 兩級緩存提高服務穩定性
  3. 解決數據在集群環境下的一致性,保證每個jvm內存中的數據一致

影響范圍

    大促核心接口:

  1. xxx.checkSkuId,預估數據量10w條 (MaximumSize)10MB,最終按照壓測情況調優。
  2. PopWareDetailService.PC/M 樣式接口,但由於數據內容較大,如果要做緩存,數據量要線上實際去觀測一下,建議只做熱點。

業務流程

 

 

 

 

 

第一步:業務場景下,數據的新增與更新會觸發入庫(mysql/mongodb)和redis,本方案會新增寫入etcd集群。寫入規則是根節點(系統名)/子節點(業務名)/葉子節點(業務key)

第二步:每個應用客戶端docker節點訂閱etcd集群業務目錄,業務目錄下的key值變更都會監聽到

第三步:監聽到有變化的key會將數據同步到基於guava cache實現的本地緩存中

第四步:當業務代碼被訪問時先從本地緩存中獲取數據,本地緩存是有數據的

第五步:如果本地緩存沒有數據(或者應用被重啟)通過第6步回源到redis獲取數據並回寫到本地緩存中。數據有變更時會通過1,2,3步驟完成本地緩存的更新

第七步:監控服務負責Etcd集群監控,另外再用mdc系統監控

第八步:開源應用,查看Etcd節點和葉子節點數據

 

 

使用 對內存的管理:

 

  1. 緩存淘汰策略:LRU,最近最少使用策略,無論是否過期,根據元素最后一次被使用的時間戳,清除最遠使用時間戳的元素釋放空間。策略算法主要比較元素最近一次被get使用時間。在熱點數據場景下較適用,優先保證熱點數據的有效性
  2. 提供統計接口:緩存命中率、緩存條數
  3. 清理緩存接口:key、keys、all

 

業務規則

  1. etcd集群,一主兩從,預發環境2c4g,生產環境4c8g
  2. etcd集群監控,
    1. 現階段通過mdc進行服務器性能監控(cpu、內存、磁盤、連通性等)
    2. 搭建新應用來對集群健康進行監控,通過etcd提供http接口來獲取,結合ump進行監控,暫不進行監控數據的持久化
  3. 為XX.checkSkuId設置本地緩存優先讀取,如果沒查到回源到jimdb
  4. ducc參數與開關配置:
    1. 是否優先讀取本地緩存開關
    2. guava cache初始化配置,包括:緩存條數
  5. 本地緩存運維查詢接口:查詢key,刪除key/ALL,緩存命中率
  6. etcd SDK開發,包括功能put、get、del、watch

 

 

改造二:對緩存穿透、熱key、異常量、限流 4種數據上報,通過服務端計算進行結果的同步

目的

  1. null key進行計算,達到閾值則同步到集群的各客戶端jvm內存,解決緩存穿透
  2. 熱key進行秒級的計算,達到閾值則同步到集群的各客戶端jvm內存,防止redis單片過熱
  3. 對調用的上游業務接口異常量進行計算,達到閾值則同步到集群的各客戶端jvm內存,進行業務熔斷

影響范圍

  1.     PopWareDetailService.PC/M 樣式接口(nullkey、熱key)
  2.     工作台保存業務中的多個上游接口(熔斷)

業務流程

 

 

第一步,請求進入客戶端,從本地緩存讀取業務key數據進行業務流程判斷,是否空值,是否被限流、是否被降級

第二步,客戶端根據業務需求調用上報SDK模塊,進行null key的上報、調用上報、接口調用異常上報

第三步,計算集群上報心跳到etcd集群,SDK模塊從etcd獲取計算服務IP集合,實現服務發現

第四步,將業務key進行hash取模,再將上報請求固定在一台計算服務機器上進行計算。基於netty建立長鏈接,提高TPS

第五步,將符合閾值(ducc)的計算結果put到etcd集群的業務目錄/業務key。Sentinel、Resilience4j

第六步,客戶端對業務目錄/業務key進行訂閱,監聽程序進行數據同步,並更新到每個客戶端jvm內存

 

業務規則

  1. 先完成方案一的技術搭建
  2. 上報模塊SDK開發(空key、異常量、熱key),數據上報通信模塊客戶端開發
  3. 計算服務端開發(計算模塊),數據上報通信模塊服務端開發
  4. ducc參數與開關配置:
    1. 上報數據計算閾值配置
    2. 上報開關配置
    3. 是否優先讀取本地緩存配置

 

 

改造三:商品介紹數據Etcd兜底(探討,結論:不適合)

目的

  1. 為商品介紹數據尋找一個兜底數據庫,並且能100%負載大促流量和性能指標的數據庫

影響范圍

    大促核心接口:SkuDecCheckService.checkWareIdDecInfo、PopWareDetailService.獲取樣式接口

業務流程

 

 

 

 

原有架構,核心接口中讀數據由jimdb硬抗。改造后

第一步,業務模塊會進行三寫,jimdb+etcd+mongodb。

第二步,數據請求先訪問本地緩存

第三步,本地緩存沒有查詢jimdb

第四步,jimdb沒有數據回源查詢mongodb

第五步,jimdb異常從etcd查詢

第六步,ducc作為查詢jimdb還是etcd的手動開關

目前jimdb資源占用內存130G,8分片,峰值操作6.7w次。建議Etcd集群指標 QPS 8w、硬盤300G。

以下是官方的性能參考:

 

 

 

 

 

集群部署策略:

 

 

  1. 集群磁盤容量不足,分片存儲
  2. 提高QPS
  3. 數據分攤,單點故障也能提供有損服務

 

兜底數據可以考慮使用es。oss

 

Etcd運維

  1. etcd搭建(集群) etcd + (nginx/HAProxy) 高可用部署方案
  2. etcd服務監控(集群健康情況監控告警、新增節點、移除節點、單點故障與恢復)
  3. etcd方案權限控制(保證開發環境與生產環境的隔離)
  4. etcd重啟與數據恢復
  5. etcd磁盤打滿解決方案

 

 

 

其他

發布過的sku數量:27874618(未去重)

不進行全量數據的本地緩存(雖然全量數據不多),因為歷史數據可能就沒有訪問量,存入本地緩存浪費資源。

對非熱點數據不進行本地緩存數據一致性處理,比如場景:容器A接收到請求寫入本地緩存key1后,不將key1同步到容器B、C。

壓縮樣式內容字符串,提高緩存數量

其他:當前業務沒有限流的需求,但基於這樣的架構限流也能做

 

待確認

1、etcd的集群申請

2、實時計算服務的選型可以考慮kafka,kafka性能:單個Consumer每秒可消費三百萬條消息,單個Producer每秒可成功發送一百多萬條消息

3、災備建議使用jimdb成本較低

4、watch的延時問題,需要通過測試來驗證

 

1、願意消耗一些內存空間來提升讀性能
2、鍵值會多次被查詢
3、內存適用總量不會超過jvm內容容量


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM