这篇文章介绍了使用 Logstash 在 Elasticsearch中 对数据进行重复数据删除的方法。 根据你的用例,Elasticsearch中 的重复内容可能不被接受。 例如,如果你要处理指标,则 Elasticsearch中 的重复数据可能会导致错误的聚合和不必要的警报。 即使对于某些搜索用例,重复的数据也可能导致不良的分析和搜索结果。

背景:Elasticsearch 索引

在介绍重复数据删除解决方案之前,让我们简要介绍一下 Elasticsearch 的索引编制过程。 Elasticsearch 提供了一个 REST API 来为你的文档建立索引。你可以选择提供唯一代表你的文档的 ID,也可以让 Elasticsearch 为你生成ID。如果你将 HTTP PUT 与索引 API 一起使用,Elasticsearch 希望你提供一个 ID。如果已经存在具有相同 ID 的文档,Elasticsearch 将用你刚才提供的文档替换现有内容-最后索引的文档将获胜。如果使用 POST 动词,则即使语料库中已经存在内容,Elasticsearch 也会生成具有新ID的新文档。例如,假设你刚在一秒钟之前为博客文章建立了索引,并使用 POST 动词重新发送了同一篇博客文章,Elasticsearch 创建了另一个具有相同内容但新具有 ID 的文档。你可以参阅我之前的文章 “开始使用Elasticsearch (1)”以了解更多。

虽然 Elasticsearch 提供了一个显式的 _update API,可以将其用作潜在的解决方法,但我们将把本文重点放在索引 API 上。

Logstash 的 Elasticsearch 输出使用索引API,并且默认情况下不希望提供 ID。因此,它将每个单个事件视为单独的文档。但是,有一个选项可让你轻松为 Logstash 中的每个事件设置唯一的 ID。

定义你的 ID

如果你的数据源已经有一个ID,那么在索引到 Elasticsearch 之前很容易将其设置为文档ID。 例如,JDBC 输入的用户可以轻松地将源表中的主键用作 Elasticsearch ID。 使用字段引用语法,可以在输出部分中直接设置文档 ID:

output {elasticsearch {hosts => "example.com"document_id => "%{[upc_code]}"}
}

其中 upc_code 是数据中的字段。 该字段可能来自结构化日志格式的字段,也可能是使用 grok 过滤器提取的。

删除重复的相似内容

如前所述,在你的用例中,重复的内容可能是不可接受的。使用称为指纹的概念和 Logstash 指纹过滤器(fingerprint),你可以创建一个称为指纹的新字符串字段,以唯一地标识原始事件。指纹过滤器可以将原始事件中的一个或多个字段(默认为消息字段)作为源来创建一致的哈希值 (hash)。一旦创建了这些指纹,你就可以将其用作下游Elasticsearch输出中的文档 ID。这样,Elasticsearch 将仅在比较指纹后更新或覆盖现有文档内容,但绝不会复制它们。如果你想考虑更多字段以进行删除重复数据,则可以使用 concatenate_sources 选项。

指纹过滤器具有多种算法,你可以选择创建此一致的哈希(hash)。请参阅文档,因为每个函数的哈希强度不同,可能需要其他选项。在下面的示例中,我们使用 MURMUR3 方法从消息字段创建哈希并将其设置在元数据字段中。元数据字段不会发送到输出,因此它们提供了一种在处理管道中的事件时临时存储数据的有效方法。

filter {fingerprint {source => "message"target => "[@metadata][fingerprint]"method => "MURMUR3"}
}output {elasticsearch {hosts => "example.com"document_id => "%{[@metadata][fingerprint]}"}
}

如果使用任何加密哈希函数算法(例如 SHA1,MD5),则需要提供密钥选项。 密钥可以是用于计算 HMAC 的任意字符串。

filter {fingerprint {source => "message"target => "[@metadata][fingerprint]"method => "SHA1",key => "Log analytics",base64encode => true}
}output {elasticsearch {hosts => "example.com"document_id => "%{[@metadata][fingerprint]}"}
}

密钥的其他示例可以是 departmentID,组织 ID 等。

意外重复:从 Logstash 生成 UUID

先前的用例涉及内容的有意识地删除重复数据。在某些部署中,尤其是 Logstash 与可确保至少交付一次的持久性队列或其他排队系统一起使用时,Elasticsearch 中可能存在重复项。如果 Logstash 在处理过程中崩溃,则重新启动时将重播队列中的数据-这可能导致重复。为了减少这种情况造成的重复,可以对每个事件使用 UUID。这里的重点是,在将数据序列化到消息队列之前,需要在生产方(即发布到排队系统的 Logstash 实例)上生成UUID。这样,Logstash使用者在从崩溃还原或重新启动时需要重新处理事件时,将保留相同的事件 ID。

如果你的源数据没有唯一标识符,则可以使用同一指纹过滤器来生成 UUID。请记住,此方法不考虑事件本身的内容,而是为每个事件生成 version 4 UUID。

filter {fingerprint {target => "%{[@metadata][uuid]}"method => "UUID"}
}output {elasticsearch {hosts => "example.com"document_id => "%{[@metadata][uuid]}"}
}

如果在 Logstash 生产者和使用者之间使用队列,则必须显式复制 @metadata 字段,因为它们不会持久化到输出中。 另外,你可以使用以下常规字段:

filter {fingerprint {target => "generated_id"method => "UUID"}
}output {kafka {brokers => "example.com"...}
}

从消费者方面,你可以只使用:

input {kafka {brokers => "example.com"}
}output {elasticsearch {hosts => "example.com"document_id => "%{[generated_id]}"}
}

例子

在下面,我们用一个实际的例子来展示,这个是如工作的。首先让我们先创建一个叫做 logstash_fingerprint.conf 的 Logstash 配置文件:

logstash_fingerprint.conf

input {http {id => "data_http_input"}
}filter {fingerprint {source => [ "sensor_id", "date"]target => "[@metadata][fingerprint]"method => "SHA1"key => "liuxg"concatenate_sources => truebase64encode => true}
}output {stdout {codec => rubydebug}elasticsearch {manage_template => "false"index => "fingerprint"hosts => "localhost:9200"document_id => "%{[@metadata][fingerprint]}"}
}

在这里,我们使用 http input 来收集数据。在这里,我们使用 sensor_id 及 date 这两个字段来生成一个 fingerprint。也就是说,只有这两个字段是一样的,那么无论我们输入多少次数据,那么在 Elasticsearch 中将不会有新的数据生成,因为它们的 ID 都是一样的。 我们启动 Logstash:

sudo ./bin/logstash -f ~/data/fingerprint/logstash_fingerprint.conf 

我们可以在另外一个 console 中打入如下的命令:

curl -XPOST --header "Content-Type:application/json"http://localhost:8080/" -d '{"sensor_id":1, "date": "2015-01-01", "reading":16.24}'

这个时候,我们可以在 Logstash 的 console 中查看到:

我们在 Kibana 的 Dev Tools 中进行查看:

GET _cat/indices

我们可以看到有一个新的 fingerprint 的索引已经生产了。

我们查看 fingerprint 的文档数:

GET fingerprint/_count

结果显示:

{"count" : 1,"_shards" : {"total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0}
}

我们在另外一个 console 中打入无数次的如下的命令:

我们发现,只要是 sensor_id 和 date 的值都是一样的,那么 fingerprint 的文档数永远是 1。当然你也可以更新其它字段的值,比如 reading 字段的值为20,那么新的值将会在里面得以体现。这个操作相当于更新的操作。

如果我们改动一下 sensor_id 的值为2,也就是:

curl -XPOST --header "Content-Type:application/json"http://localhost:8080/" -d '{"sensor_id":2, "date": "2015-01-01", "reading":16.24}'

那么我们重新查看 fingerprint 索引的文档数:

GET fingerprint/_count

上面显示文档的数值为2。也就是说,在索引 fingerprint  中,只要是 sensor_id 及 date 的数值是一样的,那么我们将永远只有一个文档,而且是永远不会重复的。

结论

如你在本文中所看到的,指纹过滤器可以用于多种用途,并且是你应该在 Logstash 生态系统中熟悉的插件。它可以很方便地让我们保持我们的文档的唯一性,而不招致重复的数据生成。

Logstash:运用 fingerprint 过滤器处理重复的文档相关推荐

  1. ES 5.x Bulk update重复的文档id性能低下

    现在很多公司(包括我们自己)将ES用作数据库数据的索引,将多个数据库的数据同步到ES是非常常见的应用场景.所以感觉这个问题可能会困扰不止一个用户,而官方的文档也没有对update的底层机制及局限做特别 ...

  2. ES 5.x bulk update重复的文档ID性能低下分析

    目前很多公司将ES作为数据库数据的索引,将多个数据库的数据同步到ES是非常常见的应用场景.所以感觉问题可能会困扰不止一个用户,而官方的文档没有对update底层机制作了详细的说明,特将该问题整理成文章 ...

  3. Logstash 使用fingerprint filter过滤重复数据

    1. 概要 工作中,Elasticsearch有个索引是通过Logstash同步Oracle数据生成的.但是又需要根据一定的规则,过滤掉重复的数据,生成另一个索引.用一张图来表示就是这样: 数据源是O ...

  4. 【毕业设计】60-基于ZigBee无线智能消防\烟雾报警逃生系统设计(原理图工程、源代码、低重复率参考文档、实物图)

    [毕业设计]60-基于ZigBee无线智能消防\烟雾报警逃生系统设计(原理图工程.源代码.低重复率参考文档.实物图) 文章目录 [毕业设计]60-基于ZigBee无线智能消防\烟雾报警逃生系统设计(原 ...

  5. API 文档搜索引擎

    项目简介 该项目主要实现了在前端页面的搜索框内输入需要搜索的 Java API 文档的关键字,对后端发出请求,后端将处理后的结果返回给前端展示,并且按照一定的权重排序展示出来. 开发环境:IDEA.T ...

  6. Mongo文档增删改查超大全

    前言 这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题 于是乎,我自己开发了一款面试宝典,希 ...

  7. python html 语法高亮,在Python中使用doxygen样式文档字符串的Vim语法高亮显示

    我开始使用doxygen来生成我的Python代码的文档. 我使用doxypy过滤器来预处理Python文档字符串. 我的目标是在Python中有一个很好的语法突出显示doxygen注释. 在专用.d ...

  8. 智能文档控制——文档的智能归档、捕获、索引、访问和协作

    Smart Document Control 一.杜绝成堆的文件和文件混乱,保证业务连续性,创建企业新阶段 清晰有条理和即时可用的信息是成功的业务流程的关键.随时随地安全管理业务文档,快速查找并智能使 ...

  9. 【Java】花费数十小时,带你体验Java文档搜索引擎的实现过程

    Java文档搜索引擎 项目运行效果 一.简述搜索引擎概念 二.搜索引擎实现思路 2.1倒排索引介绍 2.2项目目标 2.3获取java文档 2.4模块划分 2.5创建项目 2.6认识分词 2.7分词的 ...

最新文章

  1. C++类构造函数初始化列表
  2. 马化腾首谈腾讯开源时,鹅厂已在Github上放出82个项目,标星24万+ | 附AI项目链接...
  3. 应用程序创建自己的奔溃转储(crash dump)文件
  4. Web前端文档阅读笔记-vis.js动态添加节点(vue cli环境)
  5. Django视图层:Django便捷函数,render()函数返回HttpResponse对象,redirect()函数返回HttpResponseRedirect指向传递参数的URL
  6. linux set命令例子,学习一个 Linux 命令:declare/typeset 命令
  7. div 中的i标签如何点击事件_前端优化:语义标签进化史
  8. Python实现LBP算法
  9. Struts2(Maven),小白版
  10. C# AutoMapper 了解一下
  11. 前端 jQuery鼠标移入移出
  12. TortoiseSVN安装最新版,设置中文;并修改比对工具为BeyondCompare
  13. ZOJ 142 - The 14th Zhejiang Provincial Collegiate Programming Contest Sponsored by TuSimple - D
  14. c语言 pow和sqrt注意
  15. 请更换备份电池 pos机_UPS电池维护与保养
  16. 王爽-汇编语言 万字学习总结
  17. matlab 编程计算θ0的变化对三相短路电流的影响(电力系统暂态分析)
  18. 快餐店促销活动流程,快餐店网络营销方案
  19. JDK 1.8 201百度云盘下载
  20. 首批元宇宙公司已经发不出工资了!

热门文章

  1. 微信支付开发(7) 告警通知
  2. 数字人民币 为经济添活力
  3. 使用ADExplorer导出域内信息
  4. 【Python爬虫项目】新发地蔬菜水果等食品价格爬取(详细附源码)
  5. 【NKOJ-昨天今天和明天】考试游记
  6. Unity 图片画线Shader
  7. Python 标准库
  8. CS61C学习 —— 第一课
  9. 锐龙r7 5700X和5800X区别
  10. 为了更好地了解植物,这些识别植物的软件值得一试