热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

性能优化_多索引下的Lucene性能优化

篇首语:本文由编程笔记#小编为大家整理,主要介绍了多索引下的Lucene性能优化相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了多索引下的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 测试结果



多索引下的Lucene性能优化


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

1.4.2 结果分析

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

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

1.4.3 问题定位和分析

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

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

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

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

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



多索引下的Lucene性能优化


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

正是Lucene对多线程的这个优化造成线程池模型的问题:由于多线程访问IndexWriter会缓存多个DWPT对象,每个DWPT对象其对应的就是一个小的索引文件,在多线程写入时会频繁的在每个DWPT上进行切换,也就是在多个文件上进行频繁写入切换。例如:如果线程池中有20个线程,在对某个用户写入索引的时候,会生成20个文件进行同时写入。可以预见,当用户数量增加时,同时写入的文件数量等于用户数*线程数。当用户为512个是,同时写入文件的数量为512*20=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模型测试结果



多索引下的Lucene性能优化


1.5.3 结果分析

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


1.6 多应用场景测试



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

• pool 线程数速度测试

•单用户大流量

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

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

• multi 测试

1.6.1 测试参数说明

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



多索引下的Lucene性能优化


1.6.2 pool 线程数速度测试

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



多索引下的Lucene性能优化


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

1.6.3 单用户大流量

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




多索引下的Lucene性能优化


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

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

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



多索引下的Lucene性能优化


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

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

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



多索引下的Lucene性能优化


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

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

1.6.6  multi 模型测试

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



多索引下的Lucene性能优化其中图例1-1024表示总体小用户数量为1024个,每个小用户流量为1KB/s。


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




1.7 结论



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


1.8 Multi模型进一步改进



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

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

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

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


1.9 测试环境参考



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



多索引下的Lucene性能优化



1.9.1  测试数据的获取

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


点击阅读原文,12.12超级会员节,感恩回馈,应用性能管理APM低至4折起!


推荐阅读
  • 深入剖析JVM垃圾回收机制
    本文详细探讨了Java虚拟机(JVM)中的垃圾回收机制,包括其意义、对象判定方法、引用类型、常见垃圾收集算法以及各种垃圾收集器的特点和工作原理。通过理解这些内容,开发人员可以更好地优化内存管理和程序性能。 ... [详细]
  • 本文作者分享了在阿里巴巴获得实习offer的经历,包括五轮面试的详细内容和经验总结。其中四轮为技术面试,一轮为HR面试,涵盖了大量的Java技术和项目实践经验。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • 本文深入探讨了MySQL中常见的面试问题,包括事务隔离级别、存储引擎选择、索引结构及优化等关键知识点。通过详细解析,帮助读者在面对BAT等大厂面试时更加从容。 ... [详细]
  • 本文详细探讨了Java中Volatile关键字的工作原理、优化技巧及其在实际开发中的应用场景,特别是在提高多线程环境下数据可见性和减少锁竞争方面的优势。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 深入理解Java多线程并发处理:基础与实践
    本文探讨了Java中的多线程并发处理机制,从基本概念到实际应用,帮助读者全面理解并掌握多线程编程技巧。通过实例解析和理论阐述,确保初学者也能轻松入门。 ... [详细]
  • Netflix利用Druid实现高效实时数据分析
    本文探讨了全球领先的在线娱乐公司Netflix如何通过采用Apache Druid,实现了高效的数据采集、处理和实时分析,从而显著提升了用户体验和业务决策的准确性。文章详细介绍了Netflix在系统架构、数据摄取、管理和查询方面的实践,并展示了Druid在大规模数据处理中的卓越性能。 ... [详细]
  • 本文详细介绍了Grand Central Dispatch (GCD) 的核心概念和使用方法,探讨了任务队列、同步与异步执行以及常见的死锁问题。通过具体示例和代码片段,帮助开发者更好地理解和应用GCD进行多线程开发。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • ElasticSearch 集群监控与优化
    本文详细介绍了如何有效地监控 ElasticSearch 集群,涵盖了关键性能指标、集群健康状况、统计信息以及内存和垃圾回收的监控方法。 ... [详细]
  • vivo Y5s配备了联发科Helio P65八核处理器,这款处理器采用12纳米工艺制造,具备两颗高性能Cortex-A75核心和六颗高效能Cortex-A55核心。此外,它还集成了先进的图像处理单元和语音唤醒功能,为用户提供卓越的性能体验。 ... [详细]
  • 如何使用 CleanMyMac X 2023 激活码解锁完整功能
    本文详细介绍了如何使用 CleanMyMac X 2023 激活码解锁软件的全部功能,并提供了一些优化和清理 Mac 系统的专业建议。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
author-avatar
手机用户2702936061
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有