使用ElasticSearch对高负载项目进行负载优化

哈Ha!我叫Maxim Vasiliev,我是FINCH的分析师和项目经理。今天,我想告诉您,在ElasticSearch的帮助下,我们如何能够在6分钟内处理1,500万个查询,并优化其中一位客户的站点的每日负载。不幸的是,由于我们拥有NDA,因此我们必须没有名称,我们希望本文的内容不会受到影响。走吧

项目安排方式


在我们的后端,我们创建可确保客户站点和移动应用程序性能的服务。在图中可以看到一般结构:

图片

在此过程中,我们处理大量交易:购买,付款,具有用户余额的操作,我们在其中存储大量日志,并将此数据导入和导出到外部系统。

当我们从客户端接收数据并将其传输给用户时,也存在反向过程。此外,还有一些用于支付和奖金计划的流程。

背景短


最初,我们使用PostgreSQL作为唯一的数据仓库。它对DBMS的标准优势:交易的可用性,开发的数据采样语言,广泛的集成工具;再加上良好的性能,满意的人们早已满足了我们的需求。

我们绝对将所有数据存储在Postgres中:从交易到新闻。但是用户数量增加了,请求数量也随之增加了。

为理解起见,2017年仅台式机站点的年度会话数为1.31亿.2018年为1.25亿,2019年又为1.3亿。从移动版本的站点和移动应用程序再增加100-200百万,您将收到大量的请求。

随着项目的增长,Postgres不再应付负载,我们没有时间-出现了大量的各种查询,在这些查询之下我们无法创建足够数量的索引。

我们意识到,需要其他数据仓库来满足我们的需求并减轻PostgreSQL的负担。Elasticsearch和MongoDB被认为是可能的选择。后者失去了以下几点:

  1. 随着索引中数据量的增加,索引速度变慢。在Elastic上,速度与数据量无关。
  2. 没有全文搜索

因此,我们为自己选择了Elastic并为过渡做好了准备。

切换到弹性


1.我们从销售点搜索服务开始了过渡。我们的客户总共有大约70,000个销售点,并且需要在网站和应用程序中进行几种搜索:

  • 通过城市名称进行文字搜索
  • 从某个点开始以给定半径进行地理搜索。例如,如果用户想查看哪些销售点最接近他的家。
  • 按给定的正方形进行搜索-用户在地图上绘制一个正方形,并向他显示该半径内的所有点。
  • 搜索其他过滤器。销售点在分类上互不相同

说到组织,那么在Postgres中,我们在地图和新闻上都有数据源,而在Elastic Snapshot中,快照是由原始数据制成的。事实是,一开始Postgres无法满足所有条件的搜索。不仅有很多索引,而且它们也可以相交,所以Postgres调度程序迷路了,不知道要使用哪个索引。

2.接下来是新闻部分。每天,出版物都会出现在网站上,以使用户不会迷失在信息流中,必须在发布之前对数据进行排序。为此,您需要搜索:在站点上,您可以按文本匹配进行搜索,同时连接其他过滤器,因为它们也是通过Elastic制作的。

3.然后,我们进行了交易处理。用户可以在网站上购买特定产品并参加抽奖。购买此类产品后,我们会处理大量数据,尤其是在周末和节假日。相比之下,如果在平常的日子里购买次数在1.5到200万之间,那么在假日这一数字可以达到5300万。

同时,数据需要在最短的时间内处理-用户不希望等待几天的结果。您无法通过Postgres达到这样的截止日期-我们经常会锁,并且在处理所有请求时,用户无法检查他们是否收到奖品。这对于业务而言不是很令人满意,因此我们将处理移至Elasticsearch。

周期性


现在,在以下情况下,按事件配置更新:

  1. 销售点。一旦有来自外部来源的数据提供给我们,我们将立即开始更新。
  2. 新闻。在网站上编辑任何新闻后,该新闻将自动发送到Elastic。

再次在这里,值得一提的是Elastic的优势。在Postgres中,发送请求时,您需要等待,直到它诚实地处理了所有记录。您可以将1万条记录发送到Elastic,并立即开始工作,而无需等到记录分散到所有Shard中。当然,某些分片或副本可能不会立即显示数据,但很快所有内容都将可用。

整合方法


有两种与Elastic集成的方式:

  1. 通过本机客户端通过TCP。本机驱动程序正在逐渐消失:不再受支持,它的语法非常不方便。因此,我们实际上不使用它,而是尝试完全放弃它。
  2. 通过HTTP接口,您可以在其中同时使用JSON请求和Lucene语法。后者是使用Elastic的文本引擎。在此选项中,我们可以通过HTTP批处理JSON请求。这是我们正在尝试使用的选项。

由于有了HTTP接口,我们可以使用提供HTTP客户端异步实现的库。我们可以利用Batch和异步API的优势,它们最终提供了高性能,这在执行大型操作的过程中

起到了很大的帮助作用(请参见下文)

  • 节省在20个流中没有分组的情况下在Postgres中获得奖品的用户:42秒内获得460,713个条目
  • 弹性+响应式客户端10个线程+批处理1000个元素:596749条记录在11秒内
  • 弹性+响应式客户端10个线程+批处理1000个元素:4分钟内记录23801684

现在,我们已经编写了一个HTTP请求管理器,它以批处理/而不是批处理的形式构建JSON,并通过任何HTTP客户端将其发送,而与库无关。您也可以选择同步或异步发送请求。

在某些集成中,我们仍然使用官方的传输客户端,但这只是重构的问题。同时,使用基于Spring WebClient构建的自定义客户端进行处理。

图片

大促销


每年一次,针对该项目的用户都会进行一次大型活动-这就是相同的Highload,因为此时我们同时与数千万用户一起工作。

通常,高峰时段会在假期期间出现,但是这种提升是完全不同的水平。在促销的前一天,我们卖出了27,580,890单位商品。数据处理时间超过半小时,给用户带来不便。用户因参与而获得奖励,但是很明显,这一过程需要加快。

在2019年初,我们决定需要ElasticSearch。整整一年,我们在Elastic中组织了对接收到的数据的处理,并在移动应用程序和站点的api中对其输出进行了组织。结果,在竞选活动的第二年,我们在6分钟内处理了15 131 783条记录。

由于我们有很多人想要购买商品并参加促销中的抽奖活动,因此这是一种临时措施。现在我们将相关信息发送到Elastic,但是将来我们计划将过去几个月的存档信息作为永久存储库转移到Postgres。为了不阻塞弹性索引,这也有其局限性。

结论/结论


目前,我们已将所需的所有服务转移到了Elastic并暂时停止了。现在,我们在Postgres的主要持久性存储之上的Elastic中建立索引,该索引会承担用户负载。

将来,如果我们了解到数据请求变得过于多样化并且受到无数列的搜索,我们计划转移服务。对于Postgres来说,这不再是一项任务。

如果我们需要在功能中进行全文搜索,或者我们有很多不同的搜索条件,那么我们已经知道需要将其转换为Elastic。

⌘⌘⌘


谢谢阅读。如果您的公司也使用ElasticSearch并有自己的实现案例,请告诉我们。知道其他人的状况会很有趣:-)

All Articles