从SQL Server向Elasticsearch加载数据的模式

时间:2014-07-04 15:14:46

标签: elasticsearch merge-replication

这是我们想出的。通过使用3值状态列。

0 = Not indexed
1 = Updated
2 = Indexed

将有2个工作......

作业1将选择状态= 0的前X条记录,并将它们弹出到像RabitMQ这样的队列中。 然后,消费者将这些记录批量插入ES,并将DB记录的状态更新为1。

对于更新,因为我们控制了我们的数据......更新该特定记录的SQL存储过程会将其状态设置为2. Job2将选择top = x记录,其中status = 2并在RabitMQ上弹出它们。然后,消费者将这些记录批量插入ES,并将DB记录的状态更新为1。

当然,我们可能需要“排队”的中间状态,因此没有任何作业再次获取相同的记录,但如果尚未完成,则不应运行相同的作业。排队记录更新的可能性很小。由于更新通常仅在第二天结束时发生。

  

所以我知道有河流(但被弃用,可能不像ETL那样灵活)

     

我想将记录从我的SQL服务器批量插入Elasticsearch。

     

编写ETL或任何其他工具无关紧要的某种计划批处理作业。

     

从表格中选择ID> lastIdInsertedToElasticSearch这将允许以预定的时间间隔将最新记录加载到Elasticsearch中。

     

但是如果在SQL服务器中更新记录怎么办?在SQL服务器中跟踪更新记录然后在ES中推送更新记录的好模式是什么?我知道ES在放置相同的Id时有文档版本。但似乎无法将图案可视化。

2 个答案:

答案 0 :(得分:2)

所以恕我直言,批量插入有利于构建或重建索引。因此,您第一次可以运行运行SQL查询并执行批量更新的批处理作业。正如你正确指出的那样,里弗斯在转型方面并没有提供很大的灵活性。

如果SQL数据存储中的条目是由您创建的(即您控件中的某些代码库),那么相同的代码库更新Elasticsearch中的文档会更好,可能不是直接但通过通知其他服务或与队列的帮助,不要浪费时间来回应请求(如果这是你的设置)。

我们有一个非常相似的Elasticsearch用例。我们在我们的应用程序内提供搜索,该搜索跨不同类别的数据执行搜索。其中一些数据实际上是由我们的应用程序用户通过我们的应用程序创建的 - 因此我们可以轻松处理我们的应用程序将该数据写入我们的SQL数据存储,并在RabbitMQ中推送相同的数据,以便在Elasticsearch中进行索引/更新。在RabbitMQ的另一端,我们有一个用Python编写的消费者基本上替换了Elasticsearch中的整个文档。因此,我们的SQL数据存储区中的相应行和Elasticsearch中的文档共享ID,这使我们能够更新文档。

另一种情况是,我们执行搜索的几种类型的数据来自某些通过其HTTP API公开数据的第三方服务。数据创建在我们的控制之下,但我们没有自动更新Elasticsearch中条目的机制。在这种情况下,我们基本上运行一个cron作业来处理这个问题。我们设法调整了cron的时间表,因为我们还有一些有限的API查询配额。但在这种情况下,我们的数据每天都没有真正更新。所以这种系统对我们有用。

答案 1 :(得分:1)

免责声明:我共同开发了这个解决方案。

我需要jdbc-river之类的东西,可以做更复杂的"汇总"数据的。在仔细考虑修改jdbc-river以满足我的需要需要什么之后,我最终编写了river-net

以下是一些功能:

  • 它的性能相当不错(与jdbc-river相当。我们的速度达到6k行/秒)
  • 它可以连接多个表来创建复杂的嵌套文档数组,而不会创建重复的子文档
  • 它遵循许多与jdbc-river相同的约定。
  • 它还支持从文件中读取。
  • 用C#编写
  • 它使用Quartz.Net并支持cron表达式进行调度。

这个项目是开源的,我们已经有了第二个项目(也是开源的),它使用RabbitMQ进行通用作业调度。我们已经移植了很多这个项目,并计划到RabbitMQ河流,以便在索引到Elasticsearch时获得更好的性能和稳定性。

为了对抗大型更新,我们无法直接访问表格。相反,我们使用只抓取增量的stored procedures。我们在sp上还有一个选项可以重置delta来重新索引所有内容。

该项目相当年轻,只有少数提交,但我们对协作和新想法持开放态度。