玩轉分佈式

g# elasticsearch

搜索流程

  1. client發送請求到任意一個node,這node成爲協調節點
  2. 協調節點將搜索請求轉發所有的shard對應的primary shard或replica shard
  3. 每個shard將自己搜索結果的doc id返回給協調節點,由協調節點進行數據的合併、排序、分頁等操作,產出最終結果
  4. 最後由協調節點根據doc id,去各個節點拉取實際的document數據,返回給client

寫數據

  1. 客戶端選擇一個node發送請求,這個node成爲協調節點
  2. 協調節點對document進行路由,請請求轉發對應的node(primary shard)
  3. 實際的node上的primary shard處理請求,然後將數據同步到replic node
  4. 協調節點發現primary和所有replica node都搞定之後,就返回響應結果給客戶端

es原理圖

在這裏插入圖片描述

  1. es是準實時的,數據寫入1s後可搜索到
  2. es每隔5s寫入日誌文件,可能丟失5s數據

es在十億級別的數據如何提高查詢效率

  1. es的jvm不要分配太大,留足夠的內存給filesystem cache,如果查詢數據都在filesystem cache性能就能提高很多(如每次查詢5~10s,放在filesystem cache就是50ms)。
  2. 只存要檢索的數據到es中,使數據少,都能放到filesystem cache中。其它展示數據可以放到hbase中。
  3. 數據預熱,做一個專門的緩存預熱子系統,對熱數據每隔一段時間訪問一下,讓數據進入filesystem cache中。這樣別人訪問,性能一定會好很多
  4. 冷熱分離,將冷數據放到另一個索引中。這樣可確保熱數據在被預熱之後,儘量都讓他們在filesystem os cache裏,不被冷數據刷掉
  5. 儘量不要讓es做複雜的關聯查詢,儘量在document設計時,寫入的時候就能完成
  6. es的分頁越翻到後面越慢。解決方案:
    1. 不允許深度分頁
    2. 使用scroll api或search_after,缺點是不能隨意跳到任何一頁

Redis

redis過期策略:定期刪除+惰性刪除
key過期不是立刻刪除的,如果此時大量過期key堆積在內存裏,導致redis內存耗盡,則走內存淘汰機制
redis內存淘汰默認是最近最少使用算法

緩存雪崩解決方案

產生原因redis掛了或熱點數據大量同時過期,如果是後者需要通過讓熱點數據在不同時間段失效來解決。
事前:redis cluster保證高可用
事中:本地ehcache緩存+hystrix限流和降級,避免mysql被打死
事後:redis持久化,一旦重啓能從磁盤上加載數據

緩存穿透

緩存穿透容易被人利用惡意攻擊,黑客針對不存在的數據發起大量請求,導致請求都打在了mysql中,可寫一個空值到緩存然後設置一個過期時間,可以讓下次同一個key查詢請求直接走緩存

緩存擊穿

某個key訪問非常頻繁,當key失效時,大量請求走mysql。可基於redis或zookeeper實現互斥鎖,等待第一個請求構建完緩存之後,再釋放鎖,進而其它請求能直接走緩存。

MySQL

如何解決主從同步延時與數據丟失問題

如果從庫還沒有把主庫數據同步過來,主庫宕機了就會產生數據丟失,可通過半同步複製解決,即讓主庫接收到至少一個從庫的ack之後纔會認爲寫操作成功
主從數據延時問題,解決辦法有:

  1. 並行複製,從庫開啓多個線程並行讀取relay log中不同庫的日誌,然後並行重放不同庫的日誌,這是庫級別的並行
  2. 分庫,將一個主庫拆分爲多個主庫,每個主庫的寫併發就減少了幾倍,此時主從延遲可以忽略不計
  3. 寫代碼的同學,要注意,插入數據時立馬查詢可能查不到,如果寫代碼邏輯是先插入一條數據,再把它查出來,然後更新這條數據。可能會因無法立即查詢出來而更新失敗
  4. 如果確實要插入數據要立馬能查詢到,可對這個查詢設置直連主庫。不過,此時讀寫分離就失去意義了

如何設計一個高併發系統

可從以下6點討論

  1. 系統拆分
  2. 緩存
  3. MQ
  4. 分表分庫
  5. 讀寫分離
  6. elasticsearch

Dubbo

dubbo默認走dubbo協議,默認基於hessian作爲序列化協議,除此之外還支持rmi協議、hessian協議、http協議、webservice協議

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章