首页 > 商家 > 将Yelp的核心商家搜索功能迁移至Elasticsearch

将Yelp的核心商家搜索功能迁移至Elasticsearch

2017-08-13 20:55| 来源:www.cts2008.com

将Yelp的核心商家搜索功能迁移至Elasticsearch

2017-08-01 21:44 来源:细说云计算 程序设计 /操作系统

原标题:将Yelp的核心商家搜索功能迁移至Elasticsearch

将Yelp的核心商家搜索功能迁移至Elasticsearch

作者|Umesh Dangat

译者|大愚若智

虽然 Yelp 较新的搜索引擎通常使用 Elasticsearch 作为后端,但核心的商家搜索功能依然在使用基于 Lucene 自行开发的后端,这已经是 Yelp 生产环境中最古老的系统之一。

这个自定义搜索引擎的部分功能包括:

分布式 Lucene 实例

主 - 从架构

为多种语言提供自定义的文本分析支持

大部分商家搜索功能依然在用的自定义商家评级功能(例如点评、名称、hours_open、service_areas 等业务特性)

通过派生出的 Yelp 分析数据改善搜索结果的质量,如某商家最常用的查询

遗留系统存在的问题

对实时索引支持欠佳

我们原本的系统使用了一种主 - 从架构,主系统负责处理写入(索引查询),从系统负责实时流量。一个主实例负责为 Lucene 索引创建快照并将其上传至 S3,这样从实例就可以定期下载进而刷新数据。因此更新后的索引需要延迟一段时间才能被用于搜索查询。一些搜索功能,例如预订和交易无法承受这样的延迟(几分钟之久),需要索引数据能够立刻使用(最多等待几秒钟)。

为解决这一问题,我们只能使用另一种实时存储:Elasticsearch,并将其与商家信息(遗留的搜索存储)并行查询,但这意味着应用程序服务必须根据两个结果额外计算才能获得最终结果。随着业务增长,这种方法无法很好地扩展,我们开始在应用程序层对结果进行合并和排序时面临性能问题。

代码推送缓慢

我们有一个规模庞大的开发者团队在不断努力改善搜索结果的排名算法。工作完成后编写好的代码会推送至底层的搜索排名算法。在遗留系统中,这样的推送每天进行多次,每次需要花费数小时的时间。现在,Yelp 几乎所有微服务都使用 PaaSTA 部署,同时遗留系统可能是 Yelp 内部使用 PaaSTA 的最大“微服务”。我们的数据已经大到需要进行分片(Shard),为此使用了一种两层的分片方法。

Geosharding:根据地理位置将商家拆分为不同逻辑索引。例如旧金山和芝加哥的商家位于不同索引中,因为分片操作有可能会在同一个国家内部进行。

Microsharding:我们会进一步将每个地区索引拆分为多个“微索引”或“微分片”,为此使用了一种基于简单模块的方法,例如:

business_id % n, where “n” is the number of microshards desired

所以我们最终使用的 Lucene 索引看起来是这样的:

<<geographical_shard>>_<<micro_shard>>

每个 Lucene 索引支撑的进程都有自己的服务实例,为确保可用性,还需要考虑复制问题。例如,每个 _ 会有多个名为“副本”的实例,借此防范实例故障或中断。这意味着我们的服务实例数量巨大,每个实例都需要花一些时间才能启动,因为每个实例都需要:

从 S3 下载数十 GB 的数据

让 Lucene 索引预热,预加载 Lucene 缓存

计算不同数据集并将其载入内存

强制进行垃圾回收,因为启动过程会创建大量暂存对象

每次代码推送意味着必须对工作进程进行循环操作,每次都要重复上述过程。

无法执行某些功能性工作

对所有数据重建索引需要耗费大量时间,这意味着增加新的功能需要付出更高成本。因此我们无法执行很多操作,例如:

对分片算法进行快速迭代。

对分析程序进行迭代。我们使用针对不同语言自行开发的分析程序实现文字的令牌化(Tokenize),Lucene 这样的搜索引擎会在索引时使用特定的分析程序(执行令牌生成、剔除字 [Stopword] 筛选等工作),同时在查询时一般也会选择使用同一个分析程序,这样就可以在反转后的索引中找到令牌化的查询字符串。更改分析器意味着要对整个语料库重建索引,因此我们通常会尽可能避免对分析代码库进行优化。

通过索引更多字段改善排名。商家特征是对搜索结果进行排名的主要因素之一。随着商家数据日渐丰富,我们可以使用这些数据来改善搜索排名。然而此时必须使用另一个实时存储来查询这些商家特征,因为对遗留系统进行改动实在是一个让人望而生怯的过程。

相关阅读

精华攻略推荐


热门游记排行


最新活动


热门问答