天天看點

fingerprint filter 插件——Elasticsearch 去重必備利器

2、排查思路

2.1 Elasticsearch 去重的幾種方式

之前我有文章解讀:Elasticsearch6.X 去重詳解

方式一:terms 指定字段聚合 + top_hits 子聚合。

方式二:collapse 折疊去重。

拿個實戰列子看一下:

當下正值聯考出成績,我們拿新聞事件資訊作為資料來源。

如下文檔_id:1、_id:2、_id:3 是一模一樣的資料;_id: 4 是獨立資料。

也就是說:去重後資料分兩組,一組:[1,2,3]; 另外一組:[4]。

PUT news/_bulk

{"index":{"_id":1}}

{"title":"南開錄取通知書亮相,附贈嘉興蓮花種子、一封特殊的信","cont":"今天,南開大學曬出建黨百年特别版錄取通知書。","url":"https://baijiahao.baidu.com/s?id=1703334751082094750&wfr=spider&for=pc","publish_time":"2021-06-23 13:36"}

{"index":{"_id":2}}

{"index":{"_id":3}}

{"index":{"_id":4}}

{"title":"建黨百年特别版!南開大學錄取通知書送兩粒嘉興蓮花種子","cont":"@南開大學 6月23日消息,建黨百年特别版南開大學錄取通知書揭秘!","url":"https://www.163.com/dy/article/GD69KNIR0514R9P4.html","publish_time":"2021-06-23 13:25:00"}

# top_hits 子聚合去重

GET news/_search

{

 "query": {

   "match_all": {}

 },

 "aggs": {

   "type": {

     "terms": {

       "field": "title.keyword",

       "size": 10

     },

     "aggs": {

       "title_top": {

         "top_hits": {

           "_source": {

             "includes": [

               "title"

             ]

           },

           "sort": [

             {

               "title.keyword": {

                 "order": "desc"

               }

             }

           ],

           "size": 1

         }

       }

     }

   }

 "size": 0

}

# collapse 去重

 "collapse": {

   "field": "title.keyword"

 }

2.2 Elasticsearch scroll 不支援 collapse 确認

源碼确認:

fingerprint filter 插件——Elasticsearch 去重必備利器
的确不支援。

2.3 考慮新方案

原有的方案和思路都在 scroll 導出資料方面行不通的,隻能考慮新的思路了。

這個問題擴充一下,如何讓資料寫入 Elasticsearch 前去重呢?

說一下我的 Mysql 到 Elasticsearch 同步實戰思路:

fingerprint filter 插件——Elasticsearch 去重必備利器

資料源:爬蟲采集網際網路資料(由于是采集資料,難免會有轉載等重複資料)。

源資料存儲:Mysql。

如何界定重複?基于:發文标題、發文時間、發文正文内容、發文url 組成字段的MD5值作為去重标記。

資料由 Mysql 同步到 Elasticsearch 如何實作去重?

其實也很簡單,一旦有了MD5值,将MD5值作為寫入 Elasticsearch 的文檔 id,就可以完成 Mysql 資料到 Elasticsearch 的去重同步處理。

而下面要着重講解的 logstash fingerprint filter 插件實作資料去重處理,就是基于剛才的思路實作的。

3、logstash fingerprint filter 插件介紹

fingerprint:中文直譯為"指紋"。

https://www.elastic.co/guide/en/logstash/current/plugins-filters-fingerprint.html

3.1 fingerprint filter 插件版本

官方文檔強調:

Versioned plugin documentation is not available for plugins released prior to Logstash 6.0.

這是 Logstash 6.X 之後才有的功能。

3.2 fingerprint filter 插件用途

fingerprint filter 插件是 logstash filter 強大環節中的 58 個核心插件的中間一個插件。

fingerprint filter 插件——Elasticsearch 去重必備利器

其核心功能:建立一個或多個字段的一緻哈希(指紋)并将結果存儲在新字段中。

當文檔插入 Elasticsearch 時,可以使用此插件建立一緻的文檔 ID。

也就是說,如果兩個或者後續多個文檔的指紋一緻,則寫入 Elasticsearch 的 _id 一緻(前提 ES ID是明确指定使用指紋),是以相同指紋資料寫入 Elasticsearch 會覆寫,間接實作了寫入去重。

下面我們先實戰,再根據實戰講解核心參數意思,大家了解可能更順暢、通透一些。

4、logstash fingerprint filter 去重實戰

4.1 同步腳本

寫在配置檔案:logstash_print.conf 中(配置檔案名稱自己定義就可以)。

input {

 # Read all documents from Elasticsearch

 elasticsearch {

   hosts => "172.21.0.14:19022"

   index => "news"

   query => '{ "sort": [ "_doc" ] }'

filter {

   fingerprint {

       key => "1234ABCD"

       method => "SHA256"

       source => ["title", "cont", "url", "publish_time"]

       target => "[@metadata][generated_id]"

       concatenate_sources => true

output {

   stdout { codec => dots }

   elasticsearch {

       hosts => "172.21.0.14:19022"

       index => "news_after_fingerprint"

       document_id => "%{[@metadata][generated_id]}"

4.1.1 腳本講解

logstash 腳本大家就記住三段論。

第一:input,代表輸入(讀取端),本執行個體自然是基于 Elasticsearch 讀。

第二:filter,代表中間處理,那就是指紋處理部分。

第三:output,代表輸出(寫入端),本執行個體還是寫入 Elasticsearch,隻不過會寫入新的索引 news_after_fingerprint。

4.1.2 filter 環節核心參數講解

key => "1234ABCD",代表目前指紋的唯一值。

method => "SHA256",指紋生成方式。

source => ["title", "cont", "url", "publish_time"],生成指紋的基礎字段名稱。

target => "[@metadata][generated_id]":将存儲生成的指紋的字段的名稱,後面output 環節會使用。該字段的任何目前内容都将被覆寫。

concatenate_sources => true

如果為true 且 method 不是 UUID 或 PUNCTUATION 時,插件會在進行指紋計算之前将 source 選項中給出的所有字段的名稱和值連接配接成一個字元串。

如果給出 false 和多個源字段,則目标字段将是最後一個源字段的單個指紋。

4.2 同步實操

fingerprint filter 插件——Elasticsearch 去重必備利器

4.3 成功标記

fingerprint filter 插件——Elasticsearch 去重必備利器

5、小結

fingerprint filter 插件是基于現實業務問題而開發的,解決寫入去重或者導出去重的業務痛點。我們再看開頭兩個問題。

問題1 答案:不用 collapse,用 fingerprint filter 插件将資料轉存為另外索引,然後 scroll 周遊輸出就可以。

問題2 答案:用 fingerprint filter 插件将資料轉存為另外索引即可。

fingerprint filter 插件較開頭兩種去重方案優勢展現在:

能将去重後的資料獨立存儲為一個索引,且無需額外操作。

友善業務單獨處理資料。

歡迎留言交流一下您的去重思考。

參考

https://alexmarquardt.com/tag/deduplicate/