以前分享了一篇文章,介紹咱們的ES廣告倒排索引的架構與優化,我就不介紹了,建議先去看下這篇文章,再回來看這篇,下面只放下以前的架構圖網絡
原有架構是在代碼中寫 MQ 消息,而後 index_builder 消費消息,寫入到兩個索引中。但這種方式有個不足是不能覆蓋全部的訂單或創意變動,因此倒排索引中的數據有的時候和 DB 中是不一致的。同時代碼維護起來也比較麻煩。後面咱們就引入了阿里開源的框架 canal ,它能夠監聽 MySQL 的 binlog 的變動,而後把日誌發到 Kafka 中,這樣咱們只須要在 index_builder 這個工程中消費 Kafka 的消息就好了,省去了在 dsp_adinfo 中發消息。並且 binlog 的變動能夠覆蓋全部的變動操做。架構
以前 index_builder 部署在物理機上,且 builder 採用主備部署,經過爭搶用 zookeeper 實現的分佈式鎖來決定誰是主,遷移到雲平臺後,就去掉了這種對主備部署的方式,由於雲平臺有自動修復的策略。app
注意框架
咱們部署的兩個 builder 一個爲 m 索引,一個爲 f 索引,經過環境變量 dsp_index_name 區分是 m 索引 仍是 f 索引。同時由於這兩個 builder 都要消費 Kafka 的消息,但咱們知道 Kafka 處於同一個消費組的消費者只有一個能消費消息,因此要把兩個 builder 放到不一樣的消費組中,即設置不一樣的 group_id,一樣也是經過環境變量區分elasticsearch
增長了檢查 DB 和 ES倒排索引中的數據一致性的定時任務,每 10 分鐘執行一次,若是發現不一致會發短信通知,正常狀況下數據都是一致的分佈式
經過上面的一點點演進,總體架構以下所示源碼分析
由於咱們只部署了一套 ES 集羣,兩個索引都在上面,只是經過別名訪問,完成索引的切換,這就存在單點問題,一旦集羣出現問題,後果不堪設想。性能
就像墨菲定律所言學習
若是事情有變壞的可能,無論這種可能有多小,它總會發生優化
咱們的場景是讀多寫少,且索引佔用內存比較小,因此設置的主分片是 1 ,副本分片是 節點數-1,這樣就能夠保證每一個節點都保存全部數據,能夠減小在路由分片或節點的網絡消耗。
但在一次上線過程當中,忘記修改副本數了,因此副本數默認是 1,而後切換到該索引後,短期(大約幾十秒)內就致使 ES 集羣癱瘓,節點內存爆滿且不響應任何請求,由於主備索引都在一個 ES 集羣中,因此想切回主索引也切不回去了,致使咱們一段時間檢索不出來廣告,從而影響出價。最後沒有辦法只能在入口處把流量暫停,而後重啓 ES,很尷尬的是,咱們沒有準備批量重啓 ES 集羣的腳本,只能挨個節點登陸重啓,也浪費了一些時間。再 ES 集羣重啓完後,從新構建索引並正確設置副本數,再打開流量,才恢復了正常,當時真的心驚肉跳,至今記憶猶新。
咱們一個 ES 集羣部署了 35 個節點,設置的主分片是 1,副本分片是節點數-1,即 34,這樣作的好處是每一個節點都有完整的數據,當請求到該節點後,直接查詢數據就能夠返回了,省去了路由到其餘節點帶來的網絡消耗
而忘記修改副本數,即默認的是 1,這樣出現的狀況是,整個 ES 集羣 35 個節點,只有 2 個節點有數據,其餘節點是沒有數據的,可是每一個節點都是均勻的接收請求,可是這些沒有數據的節點會把請求轉發到有數據的兩個節點,也就是這兩個節點要承擔其餘沒有數據的 33 個節點的請求壓力,因此最後撐爆了整個集羣
此次線上問題後,咱們作了反思,也須要採用一些對策來避免相似的狀況發生
- 主備索引部署在同一個 ES 集羣上,存在單點問題,因此須要再部署一個 ES 集羣,實現物理隔離
- 提供重啓整個 ES 集羣的腳本,以備在出現問題時能夠快速重啓集羣
- 經過別名方式切換索引是 100% 流量切換,也容易出現問題,因此須要一個灰度慢慢切換的方式
- 切換索引時要增長必要的檢查項
- 調用 ES 增長熔斷機制,當 ES 集羣出現故障時觸發熔斷,保護 ES 集羣和服務
首先就是從新部署了一套 ES 集羣,實現物理隔離,避免一個 ES 集羣出問題,影響到另外一個集羣
其次在做業平臺中增長重啓 ES 的腳本
而後就是經過引入 Nacos 配置中心,配置流量分配比例,從而實現灰度切換流量。同時支持配置變動通知
調整後的架構以下所示
這個方案上線後,先採用了主備兩套 ES 集羣流量比爲 1:1,而後觀察效果,發現查詢 ES 的 t99 由以前的 10ms 降低到 5ms,降低大約 50%,在 Prometheus 中埋點展現以下
咱們對 ES 的讀取仍是有待優化的地方,在 kibana 中經過觀察 Search Profiler 發現 build_scorer 佔用了大部分時間,接近 80%,以下所示
經過查詢資料,發現能夠把 mapping 文件中爲 Integer 類型的映射字段改成 keyword 後能夠提升性能,由於這些字段只有有限個值,而且查詢時是經過 terms 精確匹配,因此定義爲 keyword 後性能高些,至於性能高的根本緣由仍是須要深刻源碼分析的,須要抽時間深刻研究。
而後咱們就改變 mapping 文件開始驗證,上線後的效果對比圖以下所示
可見上線後,效果仍是比較明顯的
由於對 ES 底層不夠了解,也只能經過問題驅動來一點點的優化,後面會深刻學習下 ES,再找能夠優化的點
學無止境,若是文中哪裏有問題,歡迎大佬批評指正,同時若是你有對 ES 優化有經驗,也歡迎分享給我
https://www.jianshu.com/p/9830413f62eb
https://elasticsearch.cn/article/446
https://elasticsearch.cn/question/3253
https://www.elastic.co/cn/blog/searching-numb3rs-in-5.0
https://www.elastic.co/cn/blog/better-query-planning-for-range-queries-in-elasticsearch 歡迎關注公衆號 【天天曬白牙】,獲取最新文章,咱們一塊兒交流,共同進步!