Elasticsearch實戰 | 必要的時候,還得空間換時間!
1、應用場景
實時資料流通過kafka後,根據業務需求,一部分直接藉助kafka-connector入Elasticsearch不同的索引中。另外一部分,則需要先做聚類、分類處理,將聚合出的分類結果存入ES叢集的聚類索引中。如下圖所示:業務系統的分層結構可分為:接入層、資料處理層、資料儲存層、介面層。那麼問題來了?我們需要基於聚合(資料處理層)的結果實現檢索和聚合分析操作,如何實現更快的檢索和更高效的聚合分析效果呢?
2、方案選型
方案一:只建立一個索引,aggs_index。資料處理層的聚合結果存入ES中的指定索引,同時將每個聚合主題相關的資料存入每個document下面的某個field下。如下示意圖所示:
方案一示意圖
方案二:新建兩個索引:aggsindex以及aggsdetail_index。其中:1)aggs_index儲存事件列表資訊。2)aggsdetailindex儲存事件關聯的文章內容資訊。如下圖所示:
方案二示意圖
3、方案對比
方案一優點:節省儲存空間,只儲存關聯文章id,資料沒有重複儲存。方案一缺點:檢索、聚合慢,效能不能達標。方案一後續的所有操作,都需要先遍歷檢索這一堆IDs,然後再進行檢索、聚合分析操作。
操作例項如下(實際比這要複雜):第一步:通過事件id,獲取關聯文章id列表;第二步:基於關聯文章id列表,進行檢索和聚合操作。
POST aggs_index/_search
{
"_source": {
"includes":[
"title","abstract","publish_time","author"
]},"query":{
"terms":{
"_id":"["789b4cb872be00a04560d95bf13ec8f42c","792d9610b03676dc5644c2ff4db372dec4","817f5cff3dd0ec3564d45615f940cb7437","....."]
}
}
}複製程式碼
步驟2當id數量很多時,會有如下的錯誤提示:
{
"error": {
"root_cause": [
{
"type": "too_many_clauses","reason": "too_many_clauses:
maxClauseCount is set to 1024"
},複製程式碼
。。。
方案二優點:分開儲存,便於一個索引中進行檢索、聚合分析操作。空間換時間,極大的提升檢索效率、聚合速度。方案二缺點:同樣的資料,多儲存了一份。其對應的檢索操作如下:
POST aggs_index/_search
{
"_source": {
"includes":[
"title","query":{
"term":{
"topic_id":"WIAEgRbI0k9s1D2JrXPC"
}
}
}複製程式碼
是真的嗎?用事實說話:以下響應時間的單位為:ms。方案一要在N個(N接近10)索引,每個索引近千萬級別的資料中檢索。
兩方案對比
兩方案響應時間對比效果圖
4、小結
- 由以上圖示,對比可知,方案二採取了空間換時間的策略,資料量多儲存了一份,但是效能提升了10餘倍。
- 在實戰開發中,我們要理性的選擇儲存方案,在磁碟成本日漸低廉的當下,把效能放在第一位,使用者才能用的"爽“!
推薦閱讀:
為什麼選擇 Spring 作為 Java 框架?
SpringBoot RocketMQ 整合使用和監控
使用Arthas 獲取Spring ApplicationContext還原問題現場
上篇好文: