AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

多索引下的 Lucene 性能优化

  • 2020-03-26
  • 本文字数:4508 字

    阅读完需:约 15 分钟

多索引下的Lucene性能优化

1.1 业务背景

本次优化的背景来源于公有云 AOM 日志服务。日志服务底层采用 Lucene 进行索引,对每个用户建立索引文件夹,方便对每个用户的日志进行管理。AOM 日志服务的对象为面向所有用户,有着用户数量多、流量大、流量分布不均匀等情况。虽然可以通过增加服务节点将大量用户分配到不同节点上,但是如果能够提升单个节点的处理速度极限处理速度可以有效的提高节点资源利用率。

1.2 建立模型

考虑公有云多用户查询,结合 Lucene 索引存储的特性,提出以下三个模型:


  • 单用户单线程索引模型

  • 线程池索引模型

  • 多线程 Multi 组合索引模型

1.3 单用户单线程索引模型

由于不同用户需要建立不同的索引文件夹,可以对每个用户单独建立线程进行索引,该模式下索引管理方便,也是最简单直接的方案。


为模拟不同数量用户下索引速度的变化,使用固定整体流量的方式进行测试。用户数量*用户流量=总体流量,总体流量固定不变为 40MB/s,随着用户数量增加,用户的流量对应减少。

1.3.1 测试结果


测试结果表明,单用户单线程索引模型下,随着用户数量的增加,整体索引写入速度呈现先增大后减小的趋势。用户数量大于 1024 以后,整体的索引速度降低到 3MB/s,已经不能满足一个节点的正常索引写入要求了。

1.3.2 结果分析

  • 用户数量较少情况下,索引速度随着用户数量显著升高

  • 每个用户使用一个线程进行索引,而单线程只能跑在每次只能运行在单个 CPU 上,不能充分利用测试环境下的多核 CPU。而随着用户数量的增多,索引的线程增加,多个线程在不同 CPU 下同时索引,整体的索引速度有明显的上升。

  • 用户数量继续增加,索引速度降低

  • 在用户持续增加的情况下,线程数也相应的增加。CPU 在多个线程来回切换,大量的时间浪费在线程的上下文切换过程中,从而导致索引写入速度降低,使得其整体索引速度降低到非常低的水平。

1.3.3 问题定位

针对上文测试的结果,现有代码框架下,整体的日志索引写入速度对用户数量有很大关联。其根本原因是对每个用户创建一个线程,造成在大量用户写入的情况下,存在大量的线程,程序大量的时间都用在了线程的上下文的切换上。

1.4 线程池索引模型

对于用户随着用户数量增多而线程数增加的问题,首先想到的是使用线程池,用户处理日志的逻辑添加到线程池队列,线程池的线程对队列的任务进行处理。这样可以固定线程数最大为线程池的最大线程数量。

1.4.1 测试结果


其中 pool 代表线程池索引模型、single 代表单线程索引模型

1.4.2 结果分析

  • 线程池在小用户量情况下,其索引速度相对较稳定

  • 随着用户数量的增加,线程池模型的索引速度也会显著的降低

1.4.3 问题定位和分析

对于随着用户数量增加索引速度下降的问题,多线程只会启动固定线程数,用户数量的增加对其索引速度不会有很大的影响,按理其索引速度不会有很大的影响。


为了找到这个问题的原因,提出了很多种可能性,如是否是用户流量太高、索引缓存设置太低、刷新时间太短等。但经过测试,这些可能性都被排除了,线程池模型索引速度在用户数大于 500 以后就会出现明显的很低情况。


最后,通过研究 Lucene 的多线程索引模型,找到了可能导致这种现象的原因。


首先,Lucene 索引都是通过 IndexWriter 对象完成的,每个用户都包含一个 IndexWriter 对象,对应了用户的索引文件夹。也就是说,有多少个用户,就有多少个索引文件夹。在大量用户同时写入数据时候,需要频繁的在多个文件夹下切换,频繁的更换写入的文件夹,也即进行随机写入,所以索引的速度会降低。


其次,而 IndexWriter 是线程安全的对象,其能够支持多线程访问,实现多线程同时访问的原理如下。



Lucene 为了支持多线程,会对每个访问 IndexWriter 的线程缓存一个 DWPT(Document Writer Per Thread)对象,不同线程对相同 IndexWriter 使用的是不同的 DWPT 对象。每个 DWPT 对象能够独立的完成对数据进行索引,对一个索引来说,多线程索引能够显著的提升其索引速度。这个从之前单个用户在线程池模型其索引速度明显大于单用户单线程索引速度快也能看出。


正是 Lucene 对多线程的这个优化造成线程池模型的问题:由于多线程访问 IndexWriter 会缓存多个 DWPT 对象,每个 DWPT 对象其对应的就是一个小的索引文件,在多线程写入时会频繁的在每个 DWPT 上进行切换,也就是在多个文件上进行频繁写入切换。例如:如果线程池中有 20 个线程,在对某个用户写入索引的时候,会生成 20 个文件进行同时写入。可以预见,当用户数量增加时,同时写入的文件数量等于用户数线程数。当用户为 512 个是,同时写入文件的数量为 51220=10240 个文件。高频率的随机写入请求的,整体的索引数据会有明显的下降。

1.5 多线程 Multi 组合索引模型

找到了线程池模型下大量用户索引速度慢的问题是由于多个线程同时对每个用户进行索引造成的,就需要为每个用户配置单独的线程进行索引,但是这样就和之前的单线程模型一样,会有大量线程频繁切换的问题了。要解决这个问题有如下两个关键点:


  • 索引的线程数不能过多,避免频繁的线程上下文切换。

  • 每个用户需要在固定线程下进行索引,避免同一个索引下生成多个小索引文件

  • 为此提出了多线程 Multi 组合索引模型,其结合了线程池模型和单线程模型的优势,有效的解决了上述问题。

1.5.1 模型原理

1、建立多个只有单线程的线程池模型,每个线程池只有一个线程工作,且对每个线程池进行编号。


2、以用户 id 进行 hash,得到的结果对线程池总数进行求余,得到的数即为该用户所在的线程编号。将该用户的索引任务提交到对应编号的线程池中,实现单个用户只对应一个线程进行索引处理。


3、新建一个多线程数(数量为 4-20)的线程池,并对所有用户流量进行监控,将用户流量大于一个固定阈值(如:1MB/s)的用户索引统一交由该线程池进行处理。增加大流量用户索引速度。


Multi 模型总共具有两种线程池,第一种为单线程线程池,只有单个线程进行处理任务,用户的索引任务将会固定到某个单线程池中。第二种为普通的多线程线程池,其包含多个线程同时处理任务,主要面向的是对大流量用户,并发索引,增加索引能力。这么做的前提是某个节点大用户数量不会很多,以每个用户 5M/s 的流量下,10 个用户总体流量就达到 50M/s,已经远远超过一个节点的总体速度了,采用多线程并发同时索引能够极大的增加索引能力的同时索引的文件最大也就 50 个,是完全能够接受的。

1.5.2 Multi 模型测试结果

1.5.3 结果分析

通过对比三种模型 single 单用户单线程模型、pool 线程池模型、multi 多线程组合模型的结果可以发现,Multi 模型在用户数量小于 2000 的情况下都能保持一个相当高的总体索引写入速度。在用户数量大于 2000,由于此时同时索引的文件数量过多,过多的对磁盘进行随机读写,造成磁盘的写入速度降低,索引速度有所下降。

1.6 多应用场景测试

上述的测试场景比较单一,所有用户的流量相同,用户数量增大,每个用户平均流量降低。而现网可能出现很多其他场景,为了进一步说明 Single、Pool、Multi 模型的差别,对比 Multi 模型的优势,创建了多种用户流量测试场景和参数,具体测试场景说明如下:


  • pool 线程数速度测试

  • 单用户大流量

  • 多用户小流量(10M/s)

  • 固定大用户多小用户流量测试(24M/s)

  • multi 测试

1.6.1 测试参数说明

为了完成上述测试,编写了一个测试脚本,其中包含了各种运行参数设置,方便实现各种测试场景下。


1.6.2 pool 线程数速度测试

测试目的:测试不同线程数量对单个单用户索引速度的影响



结果分析:对于单个用户,并发索引的线程数量的增加,其索引速度有所增加,线程数达到 8 以后,其整体索引速度趋于稳定。

1.6.3 单用户大流量

测试目的:测试单个用户其流量增加三种模型的整体索引速度的变化



结果分析:对于单个用户,随着其流量的增加,single 模型索引速度维持不变,multi 和 pool 模型都能够显著增加。说明 pool 和 multi 模型其对大用户的最大索引速度都能够达到 30MB/s 的较高水平。

1.6.4 多用户小流量(10M/s)

测试目的:在多个用户,每个用户的流量较小的情况下,三种模型的索引速度对比。



结果分析:Multi 模型能够很好的处理多个小用户的场景,其整体索引速度能够维持稳定不变,而 pool 和 single 模型都对大量用户比较敏感,用户数大于 500,索引速度会有明显的下降。

1.6.5 固定大用户多小用户流量测试(24M/s)

测试目的:测试在有几个大流量用户的情况下,小用户的数量对整体索引速度的影响。



其中,大用户数量为 4,大用户流量为 5M/s


结果分析:Multi模型对用户数量的增加,整体的索引索引速度略有下降,但也维持在一个较高的水平。Pool和Single模型其整体索引速度维持不变,相对于Multi有很大的差距。

1.6.6 multi 模型测试

测试目的:测试 multi 模型在各种参数情况下其索引速度的变化



其中图例 1-1024 表示总体小用户数量为 1024 个,每个小用户流量为 1KB/s。


结果分析:从测试结果可以看出,Multi 模型在不同小用户数量和流量,不同大用户数量和流量下具有较稳定的索引速度。

1.7 结论

根据上述各种场景的测试,可以得到 Multi 模型对比 Single 和 Pool 模型都有显著的优势,其能够稳定的维持较高的索引速度,在一定范围内,用户数量的增加,对其索引速度的影响最小。

1.8 Multi 模型进一步改进

Multi 的组合模型相对于单线程和线程池在大量用户情况下有着较大的索引速度的提升,但是还有很多地方可以进一步优化:


1、 线程数量的优化,线程数量的大小直接影响着索引的速度,既不能太多也不能太少,需要根据实际的运行环境调节出一个最优的线程数量。


2、 用户分配策略,现在是根据用户的 id 进行 hash 分配到不同的线程进行索引,会造成不同线程处理的整体流量不均匀状况,不能充分利用每个线程的处理能力。需要研究一种更好的用户分配策略。


本文的测试还有很多不足之处,还有很多可以优化的地方,测试的方案也比较简单,只是为以后的进一步优化提供指导,接下来还需要进一步优化方案。

1.9 测试环境参考

本次测试的环境为申请的 AOM-技术项目环境,测试节点的信息如下:


1.9.1 测试数据的获取

本次测试使用本地的日志文件作为日志数据进行索引。同时为了尽可能符合真实的日志内容,本次测试从华为公有云获取到的 AOM 服务自身产生的日志数据,该日志文件的大小为 20G。


本文转载自华为云产品与解决方案公众号。


原文链接:https://mp.weixin.qq.com/s/19C74VlkknN0uHq6-NRowg


2020-03-26 20:511396

评论

发布
暂无评论
发现更多内容

BuildPacks 打包

Zhang

Docker image CNB OCI

InnoDB 表空间

leonsh

MySQL innodb 表空间

上游思维:凭一己之力能做些什么?

石云升

读书笔记 8月日更 上游思维

快手基于 Flink 构建实时数仓场景化实践

阿里云大数据AI技术

亚信数据库AIDB通过统信UOS认证,国产自主可控项目新选择

亚信AntDB数据库

国产化 国产数据库 亚信数据库AIDB

Go- switch-case结构

HelloBug

Go 语言 switch case

最好用的 Angular 甘特图组件 ngx-gantt

PingCode研发中心

软件 工具 甘特图 ngx-gantt

Go- 函数返回值

HelloBug

函数 返回值 Go 语言

中国法定数字货币(DCEP)全面启航!全国普及势在必行

CECBC

LVS 学习: netfilter 与 ipvs 无秘密

绅鱼片

Linux 负载均衡 LVS Netfilter IPVS

ipfs矿机公司哪家好?ipfs矿机公司实力排行?

分布式存储 Filecoin ipfs挖矿 ipfs矿机 ipfs矿商排名

火爆 GitHub!这个图像分割神器开源了

百度开发者中心

人工智能 开源 最佳实践 图像

Agora 教程丨一个典型案例,教你如何使用水晶球“数据洞察”

声网

Agora 教程 水晶球

Go- break和continue

HelloBug

Go 语言 break continue

探索技术与应用融合的区块链 实现产业良性发展

CECBC

模块五:微博评论模块高性能高可用计算架构设计

kk

架构实战营

Tron波场链智能合约系统开发案例|波场链源码搭建

Geek_23f0c3

TRONex波场智能合约 DAPP智能合约交易系统开发 波场DAPP

干货!DataPipeline2021数据管理与创新大会全篇划重点

DataPipeline数见科技

大数据 数据融合 数据管理

项目进度经常超时怎么办?项目经理如何有效管理项目进度?

优秀

项目管理工具

再也不怕 JavaScript 报错了,怎么看怎么处理都在这

前端依依

学习 技术 大前端 js

Socket 通信原理

一个大红包

8月日更

docker概念很乱?俺来替你理一下!

Java Docker 架构 后端

做正确的事情,而不是把事情做正确

非著名程序员

个人成长 提升认知 认知提升 8月日更

英特尔CEO帕特·基辛格:面向未来的数字化需求,推进未来计算创新、探索与颠覆

科技新消息

Python代码阅读(第16篇):列表求差集

Felix

Python 编程 Code Programing 阅读代码

跨团队项目的集成测试实践分享

PingCode研发中心

软件测试 测试

Go- for循环

HelloBug

for Go 语言

适女化科技(一):伪需求,真消费

脑极体

BI软件漫谈

格林海文

BI Tableau 帆软

量化策略APP系统开发,马丁策略交易平台

13530558032

Vue进阶(五十九):ES数组操作:splice() 实现数组删除、替换、增加指定元素

No Silver Bullet

Vue 8月日更 splice

多索引下的Lucene性能优化_行业深度_华为云产品与解决方案_InfoQ精选文章