使用JDBC输入插件在多个节点上运行Logstash

时间:2019-03-08 01:56:43

标签: elasticsearch logstash elastic-stack logstash-jdbc

我有一个用于Logstash的基本HA设置-两个单独的AWS可用区中的两个相同节点。每个节点运行一个管道,该管道从数据库集群中提取数据集,然后将其下游输出到ELasticSearch集群以进行索引。这对于一个Logstash节点可以很好地工作,但是由于每个节点分别跟踪:sql_last_value,因此并行运行的两个节点两次向ES发送相同的数据以进行索引。由于我在两个节点上都使用与文档ID相同的ID,因此所有重复的数据都将简单地更新,而不会插入两次。换句话说,每个数据集有1个插入和1个更新。显然,这不是很有效,并且会给ELK资源带来不必要的负载。随着添加其他Logstash节点,情况变得更糟。

有人知道如何设置并行Logstash节点的更好方法,因此如果每个节点都已经提取了相同的数据集,那么每个节点都不会提取相同的数据集?一个穷人的解决方案可能是在Logstash节点之间创建一个共享的NFS文件夹,并让每个节点都在其中写入:sql_last_value,但是我不确定使用这种设置会遇到什么样的副作用,尤其是在较高的负载下。谢谢!

2 个答案:

答案 0 :(得分:1)

我们有一个非常相同的场景:3个logstash实例,以服务器数据库作为数据源来确保高可用性。

在每个logstash实例上,按照以下逻辑安装并启用相同的jdbc-pipelines:

  • 在结果集中为每个文档(主键等)找到一个唯一标识符,或使用结果中的字段(MD5,SHA而不是UUID)生成fingerprint。该标识符必须稳定!返回相同实体时,在其他logstash节点上必须相同。
  • 在elasticsearch-output中的
  • 使用id或指纹作为文档_id。

以下是简单情况的简化示例(id是结果集的一部分):

input{
  jdbc{
     ...
     statement => "select log_id, * from ..."
     ...
  }
}
filter{...}
output{
  elasticsearch{
    ...
    index => "logs-%{+YYYY.MM.dd}"
    document_id => "%{[log_id]}"
    ...
  }
}

当您的数据缺少uniqe标识符并且您需要生成指纹

时,就会出现变体
input{
  jdbc{
     ...
     statement => "select * from ..."
     ...
  }
}
filter{
  fingerprint {
    method => "MD5"
    concatenate_all_fields => true
  }
}
output{
  elasticsearch{
    ...
    index => "logs-%{+YYYY.MM.dd}"
    document_id => "%{[fingerprint]}"
    ...
  }
}

通过两种方式,当文档属于一个logstash实例的结果集的一部分时,将创建文档。其他所有logstash实例将在以后获得相同的文档。使用id / fingerprint作为_id将更新先前创建的文档,而不是重复您的数据。

为我们运作良好,请尝试一下!

答案 1 :(得分:1)

我更喜欢在不同Logstash实例的计划参数中使用公用的last_run_metadata_path(在NFS或其他共享文件系统上)。

请检查输入的jdbc插件,以获取有关last_run_metadata_path

的更多详细信息