倒排索引架構(gòu)
在廣告系統(tǒng)中倒排索引起著至關(guān)重要的作用,當(dāng)請(qǐng)求過來時(shí),需要根據(jù)定向信息從倒排索引中匹配合適的廣告。我們的倒排索引采用的是ElasticSearch(后面簡(jiǎn)稱ES),考慮點(diǎn)是社區(qū)活躍,相關(guān)采集、可視化、監(jiān)控以及報(bào)警等組件比較完善,同時(shí)ES基于JAVA開發(fā),所以調(diào)優(yōu)和二次開發(fā)相對(duì)方便
先看下我們的倒排索引的架構(gòu)圖
這個(gè)架構(gòu)設(shè)計(jì)成如上圖這樣,經(jīng)過了下面的思考與迭代
索引問題與優(yōu)化
單點(diǎn)與穩(wěn)定性問題
采用多節(jié)點(diǎn)部署
其中 A builder和 B builder都是兩個(gè)節(jié)點(diǎn),一個(gè)主和一個(gè)備,他們通過爭(zhēng)搶鎖(用zookeeper實(shí)現(xiàn))來決定誰是主
多個(gè)節(jié)點(diǎn)會(huì)帶來數(shù)據(jù)不一致問題
- 多生產(chǎn)者多消費(fèi)者產(chǎn)生消息時(shí)序問題
把消息設(shè)置成無狀態(tài)的
查詢數(shù)據(jù)庫獲取最新數(shù)據(jù)(訂單和創(chuàng)意更新頻率低,所以對(duì)數(shù)據(jù)庫壓力不大)
- 因?yàn)槌霎惓?dǎo)致數(shù)據(jù)不一致
采用重試(冪等)和定時(shí)任務(wù)處理異常
- 全量更新索引,影響線上索引查詢功能
采用主備索引
主備索引切換流程:更新備用索引->驗(yàn)證備用索引->主備切換->更新主索引
索引查詢與重建索引問題與優(yōu)化
壓測(cè)ES QPS不高、CPU負(fù)載高、YGC頻繁、索引重建索引耗時(shí)長(zhǎng)
我們分別從查詢和重建兩個(gè)方向來看
查詢
- 1s一次YGC,STW約10ms,對(duì)低延遲系統(tǒng)影響較大
調(diào)整 -Xmn 3g->7g,調(diào)整后10s一次YGC,STW約12ms
調(diào)整前YGC頻繁,對(duì)低延遲系統(tǒng)影響較大,所以想增大YGC的時(shí)間間隔,降低性能抖動(dòng),考慮到Y(jié)GC采用復(fù)制算法,每次垃圾回收時(shí)間主要包括掃描年輕代存活對(duì)象和復(fù)制存活對(duì)象,掃描對(duì)象的成本遠(yuǎn)低于復(fù)制對(duì)象,所以YGC的時(shí)間主要取決于存活對(duì)象的數(shù)量,在對(duì)象生命周期沒有較大變化的情況下,YGC的時(shí)間自然不會(huì)有較大變化
調(diào)整后,YGC的時(shí)間間隔有了很大改善,GC時(shí)間并沒有線性增加
- 調(diào)整分片數(shù)和副本數(shù),減少線程損耗、較少IO
ES默認(rèn)分片數(shù)是5,默認(rèn)條件下,索引會(huì)被分配到不同的節(jié)點(diǎn),這樣每個(gè)節(jié)點(diǎn)只有部分索引,會(huì)導(dǎo)致一次請(qǐng)求需要合并多個(gè)節(jié)點(diǎn)的數(shù)據(jù),IO數(shù)多
如圖所示,假設(shè)有3個(gè)節(jié)點(diǎn),2個(gè)主分片,每個(gè)分片有一個(gè)副本。當(dāng)一次查詢過來的時(shí)候
查詢流程大致為:首先是node3收到請(qǐng)求,它可能會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到node2的R0或node1的P0,然后完成檢索后把數(shù)據(jù)匯集到node3,最后返回。其中每個(gè)索引的內(nèi)部,數(shù)據(jù)會(huì)保存到多個(gè)segment中,而對(duì)segment的查詢是串行的
而我們的場(chǎng)景是請(qǐng)求量大,索引小(100M以內(nèi)),所以把主分片調(diào)整為1,副本調(diào)整為節(jié)點(diǎn)數(shù)-1,這樣能保證每個(gè)節(jié)點(diǎn)都存儲(chǔ)所有索引,這樣只會(huì)有一次io操作,如下圖所示
- ES(lucencu) 串行讀取所有segment
索引更新會(huì)使segment數(shù)量增加,es對(duì)segment的查詢是串行的,所以我們采用每分鐘定時(shí)用 _forcemerge將segment降為1
- 熱點(diǎn)方法排查發(fā)現(xiàn)JSON反序列化占50%cpu
禁用source只采用field存儲(chǔ)必要字段
- 指定查詢偏向本機(jī)節(jié)點(diǎn)
設(shè)置preference:_local
重建
- 全量重建前關(guān)閉從分片,禁用實(shí)時(shí)索引
replicas:0 refresh_interval:-1
減少索引在重建過程中索引同步帶來的消耗
- 批量重建索引
使用 bulk批量重建索引,提高建索引的性能
后記
我們采用的方案,有些并不符合業(yè)界常用和推薦的方式,但是符合我們自己的業(yè)務(wù),所以方案一定要適合自己團(tuán)隊(duì)的業(yè)務(wù),沒有最好的方案,只有更適合的方案






