构建可扩展的搜索架构

任何规模和复杂性的软件项目都面临着共同的挑战:构建可扩展的搜索解决方案。谁从未见过应用程序使用RDBMS SQL语句来用于搜索?您可能想知道,这是一个很好的解决方案吗?正如我大学的数据库教授所说,这看应用场景。

使用SQL来执行搜索可能足以满足您的当前使用需求,但随着项目需求的增长和需要更多高级功能(例如,启用同义词,多语言搜索甚乃至机器学习),您的关系数据库可能满足不了这些需求。
免责声明:像PostgreSQL全文搜索这样的项目可能足以满足您的使用需求,您当然可以考虑使用它们。

出于这个原因以及其他原因,许多项目开始使用他们的数据库来处理所有事情,随着时间的推移,他们可能会转移到像Elasticsearch或Solr这样的搜索引擎。

构建一个弹性且可扩展的解决方案并非易事。它涉及许多移动部件,从数据准备到构建索引和查询管道。幸运的是,这个任务看起来很像我们处理连接数据时出现的问题的方法。

常见的第一步就是使用应用程序的持久层将文档直接保存到数据库以及搜索引擎。对于小型项目,此技术可让开发团队快速迭代,而无需扩展所需的基础架构。


构建可扩展的搜索架构_第1张图片
Figure 1. Direct indexing

众所周知的分布式事务,你可能遭遇过这样的问题:一个成功写入,另一个写入失败,从而遇到一致性的问题。它还要求两个系统始终可用,因此不需要维护窗口(no maintenance windows)。

如果您有兴趣了解更多,Martin Kleppmann等人的文章很棒。它描述了异构分布式事务的现有问题。分布式事务很难成功实现,这就是为什么我们将引入一个受日志启发( log-inspired )的系统,如ApacheKafka®。

我们将介绍ApacheKafka®的三种不同的使用方法,帮助您构建可扩展且具有弹性的解决方案,能够处理越来越多的数据或文档,集成不同的信息源,引入本体(注:Ontology 是近年信息科学界最热门的词汇之一,国内一般将其译为“本体”,实质上应该译为“存在”。原是哲学的分支,研究客观事物存在的本质)和其他机器学习方法,如学习排名等。

使用Kafka Connect大规模构建索引管道

一旦搜索特性中涉及的数据点的数量增加,通常我们将在所有涉及的组件之间引入一个代理。这种体系结构模式提供了以下几个好处:

  • 更好的扩展性 :允许多个数据生产者和消费者并行运行
  • 强大的灵活性、可维护性、灵活性:通过将生产与数据消费进行分离,并允许所有系统独立运行
  • 增加数据多样性:从多个不同来源获取并最终为每个索引流水线步骤提供组织管理,例如数据统一,规范化或更高级的流程,如集成本体。

通常情况下他看起来如下所示:


构建可扩展的搜索架构_第2张图片
Figure 2. Scaling indexing

一组代理(agent)负责从数据源(例如,关系数据库)收集数据并将它们存储在服务器中间件代理(Broker)中。之后,另一个代理(agent)或代理组将从服务器代理收集数据并将其存储在我们的搜索引擎中。

当然你也可以使用许多不同的工具来实现,但如果您已经使用Apache Kafka作为中间件/Broker,Kafka Connect是一个可扩展的框架,非常适合连接Kafka的系统。 Kafka Connect具有简化部署的巨大优势,因为它与Apache Kafka及其生态系统捆绑在一起。

如果你对Kafka Connect不熟悉,在继续之前,我建议您查看Kafka Connect系列博客,其中我的同事Robin Moffatt对Kafka Connect的介绍做了一个很好的例子。

如果您访问Confluent Hub,您还会发现有许多连接器,例如Kafka Connect JDBC连接器,Kafka Connect Elasticsearch连接器,两个Apache-2.0许可的Solr社区连接器以及社区创建的其他连接器。

JDBC和Elasticsearch连接器包含在Confluent Platform中,但如果您使用的是其他Apache Kafka发行版,则可以通过从Confluent Hub下载连接器并按照文档进行安装。

使用JDBC连接器将数据迁移Apache Kafka中

在构建类似于本文所述的基础架构时,移动数据同时使其适应搜索产品的需求是一个常见的集成点。

这通常通过实现变更数据捕获模式的一些变体来实现,其中JDBC连接器起的就是这个作用。此连接器可用作源(将数据流从数据库传输到Kafka)或作为接收器(将数据从Kafka topic传输到数据库)。对于此用例,我们将使用它作为源连接器。

设置连接器

JDBC连接器具有许多强大的功能,例如支持各种JDBC数据类型,检测CREATE和DELETE TABLE命令,改变轮询间隔,以及最值得注意的是:以递增方式复制数据。

移动数据的过程通过定期运行SQL查询来工作。为了实现这一点,JDBC连接器跟踪一组列,这些列用于确定哪些行是新的,哪些行是更新的,等等。

JDBC连接器支持多种操作模式:

  • 递增模式适用于始终保证每个新行都有一个自增的ID,例如自动增量字段。请记住,此模式只能检测新行。
  • 时间戳模式以类似的方式工作,但此模式不是使用递增的整数列,而是跟踪时间戳列,捕获时间戳大于上次轮询时间的所有行。通过此模式,您可以捕获现有数据的更新以及新数据。
    注意: 您须要仔细选择要在此模式下监视的列,因为它将影响跟踪更新和新记录的方式。
  • 时间戳和递增的组合模式非常强大。此模式可以跟踪新记录以及对现有记录的更新。
  • 自定义查询: 使用此模式时请记住,不会执行自动偏移跟踪 - 自定义查询应该这样做。如果查询很复杂,此模式可能会变得昂贵。
  • 批量数据导入: 是引导系统的一种有价值的模式。

关于如何使用JDBC连接器的更多细节可以在我的同事Robin Moffatt的深度帖中找到。

JDBC 驱动

该连接器依赖于数据库JDBC驱动程序来实现其核心功能。所选数据库的JDBC驱动程序应安装在与连接器相同的kafka-connect-jdbc目录中。如果您使用的是诸如DEB或RPM之类的Linux软件包,则通常位于/ usr / share / java / kafka-connect-jdbc目录中。如果从存档进行安装,则它将位于安装中的share / java / kafka-connect-jdbc目录中。

下面是一个示例配置,用于设置连接器以查询MySQL数据库的products表,使用“modified”列为时间戳,使用“ID”列为主键,并将记录写入db-products Kafka topic中:

name=mysql-source
connector.class=io.confluent.connect.jdbc.JdbcSourceConnector
tasks.max=10

connection.url=jdbc:mysql://mysql.example.com:3306/my_database
table.whitelist=products

mode=timestamp+incrementing
timestamp.column.name=modified
incrementing.column.name=id

topic.prefix=db-

模式演变

模式演变在所有数据集成情况下都是不可避免的,搜索也不例外。如果使用Avro作为转换器,连接器将检测何时发生传入表模式的更改并管理与Confluent Schema Registry的交互。

很可能,您的数据模式将在应用程序的整个生命周期中发生变化,因此使用模式注册表(Schema Registry )将使您更容易调整和确保数据格式的一致性,以及使数据生成和使用能够随着模式独立性而发展。

使用JDBC连接器需要注意的事项

JDBC连接器的常见问题是选择正确的操作模式。虽然该连接器允许您从完全适合初始加载批量模式的操作模式开始,但是逐个将每个表的记录导入Apache Kafka的最佳方法非常重要。

该连接器允许您编写自定义查询以将数据导入Kafka。如果您打算使用此高级模式,则​​应该小心并确保查询的性能符合您的时间预期。

但同样重要的是,请记住该连接器的工作原理是将常规SQL查询直接发送到数据库中。始终密切关注其性能,并确保它们在预期的时间内运行,以使管道正常运行。

您可以阅读更多关于将自关系数据库的数据集成到Kafka中的选项的更多信息:如何将您的数据库与Apache Kafka和CDC集成

使用Elasticsearch连接器索引文档

把事件存储到Apache Kafka之后,要构建初始索引的下一个逻辑步骤是将数据从Kafka提取到Elasticsearch。此时,您可以使用Kafka Connect Elasticsearch连接器来完成。

Kafka Connect Elasticsearch连接器有着丰富的功能,例如映射推断和模式演变。您可以在文档中找到相关的配置详细信息。

设置连接器

开始使用Elasticsearch连接器的比较简单方法可以请使用以下配置:

name=search-indexing-sink
connector.class=io.confluent.connect.elasticsearch.ElasticsearchSinkConnector
tasks.max=1
topics=db-products
key.ignore=true
connection.url=http://localhost:9200
type.name=products

这个配置将会从名为db-products的topic中拉取数据,且使用JDBC 连接器。这个配置配置的是最多任务数为一个(您可以根据需要去配置更多任务数),然后它会将存储在该topic中的数据提取到位于http:// localhost:9200的Elasticsearch实例的db-products索引中。

有关Kafka Connect Elasticsearch连接器的说明

Elasticsearch连接器通常很简单,但你需要注意一些事项。

您可能已经知道,Elasticsearch映射可能很难做到正确。您需要仔细考虑数据如何查找所涉及的每个用例,因为即使使用动态字段,查询的最终结果也将取决于您如何配置分析器和断词器。

Elasticsearch连接器允许您在某种程度上使用自动映射推断。但是,如果要构建搜索基础结构,则更好的方法是定义索引模板,您可以精确控制数据在内部的处理方式。

此外,您还可能遇到的另一个问题就是重试,这可能由于各种原因而发生(例如,Elasticsearch处于繁忙状态或者维护状态)。在这种情况下,连接器将继续运行并使用指数退避重试不成功的操作,从而使Elasticsearch有时间恢复。
原文地址:https://www.confluent.io/blog/building-a-scalable-search-architecture

你可能感兴趣的:(构建可扩展的搜索架构)