g# elasticsearch
搜索流程
- client發送請求到任意一個node,這node成爲協調節點
- 協調節點將搜索請求轉發所有的shard對應的primary shard或replica shard
- 每個shard將自己搜索結果的doc id返回給協調節點,由協調節點進行數據的合併、排序、分頁等操作,產出最終結果
- 最後由協調節點根據doc id,去各個節點拉取實際的document數據,返回給client
寫數據
- 客戶端選擇一個node發送請求,這個node成爲協調節點
- 協調節點對document進行路由,請請求轉發對應的node(primary shard)
- 實際的node上的primary shard處理請求,然後將數據同步到replic node
- 協調節點發現primary和所有replica node都搞定之後,就返回響應結果給客戶端
es原理圖
- es是準實時的,數據寫入1s後可搜索到
- es每隔5s寫入日誌文件,可能丟失5s數據
es在十億級別的數據如何提高查詢效率
- es的jvm不要分配太大,留足夠的內存給filesystem cache,如果查詢數據都在filesystem cache性能就能提高很多(如每次查詢5~10s,放在filesystem cache就是50ms)。
- 只存要檢索的數據到es中,使數據少,都能放到filesystem cache中。其它展示數據可以放到hbase中。
- 數據預熱,做一個專門的緩存預熱子系統,對熱數據每隔一段時間訪問一下,讓數據進入filesystem cache中。這樣別人訪問,性能一定會好很多
- 冷熱分離,將冷數據放到另一個索引中。這樣可確保熱數據在被預熱之後,儘量都讓他們在filesystem os cache裏,不被冷數據刷掉
- 儘量不要讓es做複雜的關聯查詢,儘量在document設計時,寫入的時候就能完成
- es的分頁越翻到後面越慢。解決方案:
- 不允許深度分頁
- 使用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之後纔會認爲寫操作成功
主從數據延時問題,解決辦法有:
- 並行複製,從庫開啓多個線程並行讀取relay log中不同庫的日誌,然後並行重放不同庫的日誌,這是庫級別的並行
- 分庫,將一個主庫拆分爲多個主庫,每個主庫的寫併發就減少了幾倍,此時主從延遲可以忽略不計
- 寫代碼的同學,要注意,插入數據時立馬查詢可能查不到,如果寫代碼邏輯是先插入一條數據,再把它查出來,然後更新這條數據。可能會因無法立即查詢出來而更新失敗
- 如果確實要插入數據要立馬能查詢到,可對這個查詢設置直連主庫。不過,此時讀寫分離就失去意義了
如何設計一個高併發系統
可從以下6點討論
- 系統拆分
- 緩存
- MQ
- 分表分庫
- 讀寫分離
- elasticsearch
Dubbo
dubbo默認走dubbo協議,默認基於hessian作爲序列化協議,除此之外還支持rmi協議、hessian協議、http協議、webservice協議