日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Elasticsearch全量数据增量遍历实现原理

發布時間:2024/1/17 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Elasticsearch全量数据增量遍历实现原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

0、需求

針對鳳凰網財經版塊的新聞數據和評論數據, 1個索引存儲采集鳳凰網財經版塊的新聞數據;1個索引存儲相關的財經數據評論結果。?
統計:?
1)某條新聞的評論數的多少??
2)某條評論屬于哪條新聞??
3)當前已采集數據的所有評論、評論數匯總,按照評論數逆序排序,以便于圖形化展示。

1、問題分解

1.1 數據如何存儲,方案選型?

方案一:類似需求,1個索引ifeng_index存儲新聞數據;1個索引ifeng_comm_index存儲評論數據。?
二者之間通過唯一值建立關聯:評論數據中其來源新聞的唯一id值。?
優點:數據分開存儲,不存在交叉問題;?
缺點:如果實現需求3),會非常復雜,做全局兩通道的遍歷和統計。

方案二:借助2.X-5.X版本ES中特有的父子文檔實現。?
注意:由于6.X版本以后,一個索引下只能存儲一個type,所以父子文檔也就不再可以使用。?
所謂父子文檔,可以理解為:?
1)統一索引下的兩個type,1個父type存儲鳳凰網新聞數據;1個子type存儲鳳凰網評論數據;?
2)其中子type的Mapping定義要特殊處理;?
3)其中子type的每條鳳凰網評論數據都要關聯唯一的父type的相關ID值。?
優點:可以以相對較小的復雜度滿足需求1)、2)、3)?
缺點:以上方案二,ES6.X+都不再適用。?
注意:?
ES6.X已經移除父子文檔的相關實現:http://t.cn/RE07V5A?
但是轉換為新的join的實現方式:http://t.cn/RE07IG1?
綜上分析,我是5.X的版本,采取方案二。

1.2 所需要技術支撐

1)父子文檔技術?
父子文檔定義:?
用于兩個索引之間通過某一個特殊字段建立關聯的場景。?
在1對多的場景,尤其適用。如:1個父文檔下有多個子文檔。?
缺點: 查詢速度會比同等的嵌套查詢慢5到10倍,詳見:http://t.cn/ROir5rQ

父子文檔實現:?
建立父-子文檔映射關系時只需要指定某一個文檔 type 是另一個文檔 type 的父親。 該關系可以在如下兩個時間點設置:1)創建索引時;2)在子文檔 type 創建之前更新父文檔的 mapping。

2)全局遍歷技術?
借助Scroll實現。之前的博文也有說明,http://t.cn/RE068mD?
【scroll機制】:相對于from和size的分頁來說,使用scroll可以模擬一個傳統數據的游標,記錄當前讀取的文檔信息位置。這個分頁的用法,不是為了實時查詢數據,而是為了一次性查詢大量的數據(甚至是全部的數據)。?
假設某索引下共有8個document,document中由code字段標記不同,0,1,2….8區分。

  • 第一次scroll請求中,size設置為3,基于code升序排序,時間戳設置為1min;
  • 第二次基于scroll_id查詢,基于scroll_id查詢第一次返回結果:0,1,2; 基于scroll_id查詢第二次,返回結果:3,4,5; 基于scroll_id查詢第三次,返回結果:6,7。
  • 假設仍在的有效時間1min內,繼續查詢,返回結果:空。?
    若超時,繼續scroll_id請求,則會返回類似如下的錯誤:

    {"error": {"root_cause": [{"type": "search_context_missing_exception","reason": "No search context found for id [79110689]"},{"type": "circuit_breaking_exception","reason": "[parent] Data too large, data for [<transport_request>] would be [23195655038/21.6gb], which is larger than the limit of [23190280601/21.5gb]","bytes_wanted": 23195655038,"bytes_limit": 23190280601},

    3)增量遍歷統計計數?
    對修改字段打flag標記,可以通過ES中update_by_query方法,對ES中數據進行更新操作。?
    如果:不存在flag字段,遍歷到該條記錄的時候,新增flag字段且flag置為1。?
    如果:存在flag字段,代表該條記錄已經被遍歷過。?
    這樣的好處,防止數據被循環遍歷。?
    其實:scroll機制已經預防了這一點,以防萬一。

    2、具體原理

    2.1 scroll實現遍歷DSL實現

    步驟1:scroll查詢。?
    基于特定的字段進行排序如下:

    POST scroll_index/_search?scroll=1m {"size": 3,"query": {"match_all": {}},"sort": {"code":"asc"} }

    返回結果:

    {"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAFcOGqFllFRGNIdVQ2Ui1LaFJRblJKOWVDNkEAAAAABXDhqxZZRURjSHVUNlItS2hSUW5SSjllQzZBAAAAAAPXB3EWTllZcVhfUlNSRUN5M3NueUJ2YkVXUQAAAAAD1wd0Fk5ZWXFYX1JTUkVDeTNzbnlCdmJFV1EAAAAAA9cHchZOWVlxWF9SU1JFQ3kzc255QnZiRVdR","took": 4,"timed_out": false,"_shards": {"total": 5,"successful": 5,"failed": 0},"hits": {"total": 8,"max_score": null,"hits": [{"_index": "scroll_index","_type": "scroll_type","_id": "0","_score": null,"_source": {"code": 0},"sort": [0]},{"_index": "scroll_index","_type": "scroll_type","_id": "1","_score": null,"_source": {"code": 1},"sort": [1]},{"_index": "scroll_index","_type": "scroll_type","_id": "2","_score": null,"_source": {"code": 2},"sort": [2]}]} }

    步驟2:基于Scroll_id查詢

    POST /_search/scroll {"scroll" : "1m","scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAFcOGqFllFRGNIdVQ2Ui1LaFJRblJKOWVDNkEAAAAABXDhqxZZRURjSHVUNlItS2hSUW5SSjllQzZBAAAAAAPXB3EWTllZcVhfUlNSRUN5M3NueUJ2YkVXUQAAAAAD1wd0Fk5ZWXFYX1JTUkVDeTNzbnlCdmJFV1EAAAAAA9cHchZOWVlxWF9SU1JFQ3kzc255QnZiRVdR" }

    步驟3:循環執行,直至遍歷結束。?
    主要注意的時間。

    2.3 增量部分java如何實現?

    在延遲指定時間后以指定的間隔時間循環執行定時任務。?
    借助Java Timer類實現。 Timer 是一種定時器工具,用來在一個后臺線程計劃執行指定任務。

    public class TimerTest03 {Timer timer;public TimerTest03(){timer = new Timer();timer.schedule(new TimerTaskTest03(), 1000, 2000);}public static void main(String[] args) {new TimerTest03();}}public class TimerTaskTest03 extends TimerTask{@Overridepublic void run() {Date date = new Date(this.scheduledExecutionTime());System.out.println("本次執行該線程的時間為:" + date);}}

    2.5 父子文檔的實現。

    步驟1:定義索引,同常規定義索引一致。

    但,要規劃好父子文檔,通過:type類型區分。?
    如,父文檔的type定義為:fenghuang_type, 子文檔定義為ifeng_comm_type。

    PUT ifeng_index {"mappings": {"ifeng_type": {}," ifeng_comm_type ": {"_parent": {"type": "fenghuang_type"}}} }

    步驟2:插入子文檔數據。

    父文檔數據插入和傳統導入數據方式一致。?
    舉例如下:?
    PUT /ifeng_index/ifeng_comm_type/1?parent=XVFBASDE!?
    注意: 父子文檔關聯建立的關鍵是:在導入子文檔數據的時候通過加入參數parent=父文檔的_id。

    步驟3:基于父文檔查詢子文檔。

    POST ifeng_index/ifeng_comm_type/_search {"query": {"has_parent": {"type": "ifeng_type","query": {"match": {"title": "世錦賽-墨西哥錦標賽移動日精彩集錦"}}}} }

    步驟4:基于子文檔查詢父文檔。

    POST ifeng_index/ifeng_type/_search {"query": {"has_child": {"type": "ifeng_comm_type","score_mode": "max","query": {"match": {"title": "很精彩,棒極啦!"}}}} }

    步驟5: 查看索引中每個父文檔下有多少個子文檔

    POST /ifeng_index/ifeng_type/ {"size": 0,"aggs": {"ifeng_key_agg": {"terms": {"field": "_key","order": {"ifeng_comm_type": "desc"}},"aggs": {"ifeng_comm_type": {"children": {"type": "ifeng_comm_type"}}}}} }

    3、小結

    通過父子文檔,實現了1對多數據的關聯;?
    通過scroll可以實現遍歷操作,實現全量遍歷;?
    通過scroll+java定時任務Timer,實現增量遍歷。

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的Elasticsearch全量数据增量遍历实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。