搜索引擎优化高级编程:php版(互联网数据规模的爆炸式增长,如何从海量的历史,实时数据中快速获取有用的信息,)

优采云 发布时间: 2022-02-10 21:27

  搜索引擎优化高级编程:php版(互联网数据规模的爆炸式增长,如何从海量的历史,实时数据中快速获取有用的信息,)

  随着互联网数据规模的爆炸式增长,如何从海量的历史和实时数据中快速获取有用信息变得越来越具有挑战性。一个中型电商平台每天产生数百万的原创数据,数亿的用户行为数据。一般来说,电子商务数据主要有3种数据系统:

  关系型数据库,大部分互联网公司都会选择mysql作为数据库的主要选择,用于存储商品、用户信息等数据。关系数据库支持非常事务性的 OLTP 操作(例如订单、结算等)。

  Hadoop生态,Hadoop是数据仓库的主要载体。除了备份所有版本的关系数据库外,它还存储了用户行为、点击、曝光、交互等海量日志数据。Hadoop 比关系数据库更支持数据分析、数据挖掘和其他 OLAP。可扩展且稳定。

  搜索引擎,以elasticsearch和solr为代表。搜索引擎是获取信息最有效的方式,已经成为几乎所有类型的网站,应用程序的基本标准设施(地位仅次于数据库)。

  目前,搜索引擎技术有非常成熟的开源解决方案。最著名的 ElasticSearch 和 Solr 都是基于 lucence 的。很多中小型互联网公司的搜索引擎都是基于这两个开源系统构建的,但即便如此,一个搜索引擎团队还是希望将搜索引擎的质量做到商业标准。熟悉系统、构建服务和自定义功能通常需要很长时间。商业互联网搜索中的通用搜索引擎应用通常会遇到以下问题:

  搜索引擎与公司现有数据系统的整合。MySQL和hadoop是电子商务的两个主要数据载体,搜索引擎必须在全量索引和增量索引的过程中与MySQL或hadoop无缝集成,才能发挥搜索引擎本身的作用。实时、水平扩展(性能与容量和机器数量成正比)等优势。

  商业搜索的高度定制化与通用搜索引擎的矛盾。商业搜索的问题有时会超出搜索引擎本身的范围,比如产品的去重、店铺的去重,需要非常专业的搜索引擎技能;产品的重量,用户意图的识别需要算法和模型的支持。

  如果没有搜索引擎专业知识,就很难创建性能友好的索引。结果是一般搜索性能差的错觉。

  作者是有赞的大数据架构师。他从自己的搜索实践出发,分享了搜索引擎的实际结构以及它解决的问题。

  有赞搜索引擎实践分为两部分。第一部分是工程,主要介绍搜索引擎架构和性能优化的经验;第二部分是算法,介绍有赞实际需要的搜索算法的问题和解决方案。文章仅介绍一家中型电子商务公司的实际使用情况和作者的亲身经历。它并不代表搜索引擎的最佳实践方法,也不意味着它可以适用于所有场景。读者如有任何问题,可联系作者共同讨论讨论。

  1. 技术架构

  有赞搜索引擎基于分布式实时引擎elasticsearch(ES)。ES建立在开源社区最稳定成熟的索引库lucence之上,支持多用户租用,高可用,横向扩展;并具有自动容错和自动伸缩机制。我们的同事也实现了es与mysql、hadoop的无缝集成;自主研发高级搜索模块,提供灵活的相关性计算框架等功能。

  

  2. 索引构建

  互联网索引的特点是实时性高、数据量大。时效性要求用户和客户的各种行为都能在第一时间进入索引;大量数据需要一个有效的分布式方案,可以在恒定时间索引中创建一个不断增长的 TB 数量级。

  我们使用面向队列的架构进行实时索引。数据先写入DB(或文件),再通过数据库同步机制将数据流写入kafka队列。这种同步机制和数据库主从同步的原理是一样的。主要开源产品有:阿里推出的Mypipe和canal.es通过订阅相应主题实现实时索引。

  如果数据源是文件,使用flume实时写入Kafka。

  另一个索引问题是完全索引。有几种场景需要全索引: 1. 实时更新可能会丢失数据,每一次小的丢失都会花费很长时间,从而降低搜索引擎的质量。Cycle 解决这个问题最直接的方法就是更新全量自然;2. 即使可以保证实时更新,但业务的发展可能需要重新索引(如添加字段、修改属性、修改分词算法等)。

  3. 很多搜索引擎都是在业务启动很久之后才搭建的,冷启动必须要创建全索引。

  我们使用 Hadoop-es 通过利用 hadoop 的分布式特性来创建索引。Hadoop-es 使分布式索引对用户透明,就像在单台机器上更新索引一样。一是分布式数据平台,二是分布式搜索引擎。将这两者结合起来可以实现分布式全索引过程。Hadoop-es 是我们想要的工具。

  

  我们举一个通过Hive sql创建索引的例子:

  

  系统将 es 映射到 hive 的外部表,更新索引就像写入 hive 表一样。事实上,所有分配问题对系统都是透明的。

  不建议从数据库或文件系统中完全索引。一方面,这会给业务系统带来很大的压力。另一方面,由于数据库和文件系统并不是真正的分布式系统,所以自己编写程序可以保证全索引的横向扩展性非常高。很容易出错,没必要这么做。

  全索引和增量索引的架构如下图所示。还有一点是hadoop也订阅了Kafka来备份数据库和日志。我个人推荐一个公司的所有DB和文件都存储在hadoop上,这样至少有两个好处:1.hive或者spark在hadoop上创建的数据仓库,为大数据提供了统一的操作接口。

  2. hadoop 数据比在线稳定,可以作为数据恢复的最后一道防线。

  数据仓库的话题不在本文的讨论范围内文章,这里只是简单提一下。

  

  我们为什么选择卡夫卡?Kafka 是一种以高吞吐量着称的消息系统。Kafka开启日志压缩功能后,每条消息都可以永久保存。每条消息都有一个key,对应于数据库的主键,kafka总是保存一个key的最新消息,历史版本会被垃圾回收。有了这个特性,kafka 不仅可以保存数据库的最新快照,还可以实现实时更新消息系统。第一次同步时,数据表中的每一行记录都转换成一条以主键为键的消息进入kafka,可以被任意数量的broker消费。之后,数据库的每一次更新(插入、更新、删除)都会转换成kafka消息。如果某行记录经常发生变化,

  Kafka不仅保存了数据库最新的全量数据,还提供了实时的数据流,极大的方便了架构的可维护性。如果想从头开始扫描整个数据库,只需要开始消费这个kafka topic即可。, 阅读到主题时,自动获取实时更新的功能。

  Kakfa 的另一个特点是它支持从任意断点读取数据。例如,我们的完整索引是从 HDFS 读取的。我们可以根据 HDFS 中保存的最后一条数据的时间戳直接切换到 Kafka 读取的数据。

  3. 高级搜索:超越 ES 能力

  高级搜索模块 (AS) 在商业搜索引擎中起着至关重要的作用。AS 已成为各大商业搜索引擎公司的标准配置和最频繁更改的模块。

  AS在商业搜索引擎中主要扮演以下角色:

  1. 反向代理,实现基于sharding的分布式搜索(其实es有这个功能);提供必要的灾难恢复支持

  2. 提供插件相关计算框架

  3. 提供丰富的关联库,如查询分析库、查询重写库、排序库、过滤库等。

  4. 管理不同的搜索操作

  

  AS的主要功能之一就是通过业务插件来表示对应的搜索。最简单的插件只需要收录对应的ES搜索API,其实就是一个配置项,表示es的地址。这样,AS 就是一个纯代理。但是ES本身不支持商业搜索的需求,所以需要根据需求编写相应的Query rewriter、rerank等算法插件。这样实现了框架和业务的分离,AS具有很强的扩展性和复用性。

  AS的另一个功能是提供通用的算法库。实际上,它只是为每种算法提供了一个编程框架。算法也通过插件添加到算法库中。这种方法可以让算法工程师将公共算法库抽象出来供业务使用,避免了重新发明轮子的需要。特定业务要么使用现有算法(并修改参数),要么实现自己的算法。

  

  上图是一个例子。商品搜索和配送搜索各自实现了一个rerank算法,并且都调用了系统提供的rerank1算法库,并添加了各自独有的逻辑。

  除了基本的代理功能外,AS 还提供了基于查询的缓存功能,用于应用级缓存。内部有缓冲队列,防止雪崩现象。将在下一节性能优化中详细讲解。

  4. ES 性能优化

  在下面的总结中,我们写了一些我们遇到的性能优化场景。

  4.1 使用应用级队列来防止雪崩

  ES 的问题之一是在高峰时段很容易发生雪崩。ES 有完善的线程池系统来保证并发和稳定性问题。但是在流量突然变化的情况下(比如双十一尖峰),还是容易出现瘫痪的情况。主要原因如下:

  ES 几乎为每一种操作都配置了一个线程池;只能保证每个线程池的资源使用合理。当超过2个线程池竞争资源时,很容易导致资源响应失败。

  ES 没有考虑导致稳定性问题的网络负载。

  在AS中,我们实现了一个面向请求的全局队列来保证稳定性。它主要做三件事。

  将请求按照业务划分为幻灯片,每张幻灯片对应一个队列。默认情况下,一个应用程序是一张幻灯片,一个应用程序也可以区分不同的幻灯片,这样可以保护应用程序中的重要查询。

  配置每个队列的队列长度,默认为 50.

  计算每个队列的该队列的平均响应时间。当队列平均响应时间超过200ms时,停止工作1s。如果请求溢出,写入溢出日志保存数据以备恢复。如果队列平均响应时间连续10次超过500ms,就会报警,让工程师第一时间处理。

  4.2 自动降级

  应用级队列解决雪崩问题有点粗糙。如果应用本身查询速度很慢,很容易导致应用持续长时间超时。我们根据搜索引擎的特点编写了一个自动降级功能。

  以商品搜索为例,商品搜索最基本的功能是布尔查询,但也需要相关度得分、质量排名等功能,甚至是个性化需求。为了完成一个简单的布尔查询,ES可以使用bitsets操作来完成。但是,如果需要相关分数,则必须使用倒排索引,计算分数会消耗大量 CPU。ES 的位集比倒排索引快大约 50 倍。

  对于有降级计划的幻灯片,当队列响应太慢时,AS 直接使用降级查询代替普通查询。这种方法可以让我们在不扩容的情况下成功度过双十一流量的突然增长。

  4.3 善用过滤查询

  了解 lucence 过滤器的工作原理对于编写高性能查询至关重要。许多搜索性能优化都与过滤器的使用有关。过滤器使用位集进行布尔运算,而查询使用倒排索引进行计算,这就是过滤器比查询快的原因。.bitsets的优势主要体现在:

  1. bitsetcache 在内存中并且永远不会消失(除非 LRU)。

  2. 位集利用 CPU 原生支持的位操作,这比倒排索引快几个数量级

  3. 多个bitset的AND运算也很快(一个64位的CPU可以同时计算64个DOC的AND运算)

  4.bitset在内存中的存储独立于查询,复用性强

  5. 如果一个bitset分片全为0,计算会自动跳过这些分片,这样在数据稀疏的情况下bitset也比倒排索引表现更好。

  例如:

  

  lucence 处理这个查询的方式是在倒排索引中找到这三个项的倒链,并使用跳转指针技术找到交集。在计算的过程中,每一个doc都需要打分。实际上,标签和区域对于计算很重要。点不起作用,它们充当过滤器。

  这是过滤器的使用场景,它只存储有无两种状态。如果我们使用 bitset 来存储标签和区域,这两个过滤器总是可以缓存在内存中,这样会快很多。此外,标签和区域的交集速度非常快,因为一台 64 位机器可以在一个 CPU 周期内同时处理 64 个 doc 位操作。

  lucence 的黄金法则是:如果可以,请使用过滤器,除非您必须使用查询(当且仅当您需要计算点数时)。

  正确的写法是:

  

  Lucence的过滤查询会先智能计算过滤语句,再计算查询语句,从而在执行复杂的倒排算法之前尽可能减少计算空间。

  4.3 其他性能优化

  在线集群关闭分片的自动平衡。分片自动平衡的主要目的是防止更新导致每个分片中数据分布不均。但是,如果某个在线节点挂掉了,很容易触发自动均衡,集群内的数据会移动一段时间,占用所有带宽。建议使用空闲时间均衡策略,保证数据的一致性。

  尽可能延长刷新间隔。为了保证实时索引es索引刷新间隔默认为1秒,索引刷新会影响查询性能。在保证业务及时性的基础上,可以适当延长刷新间隔,保证查询的性能。

  除非有必要删除所有字段。除了默认为每个字段建立索引外,索引还额外创建了一个 all 字段来保存所有的文本。删除该字段可以将索引大小减少 50%。

  创建索引时,尽量在物理上将较慢的索引与较快的索引分开。

  5. 总结

  本文介绍了有赞搜索引擎的架构,重点介绍了索引创建机制、高级搜索模块的功能,最后列出了几种常见的性能优化场景。es本身的优化这篇文章就不多写了,因为es官网等博客上有很多es的优化意见,本文就不一一列举了。本文的主要目的是给读者一个构建商业电子商务搜索引擎的一般建议。此外,商业搜索引擎最头疼的问题是排序和算法问题。有兴趣的读者可以关注作者的另一篇文章文章《你喜欢搜索引擎实践(算法)》。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线