当前位置: 首页 > news >正文

Apache Commons Pool2 池化技术

对象池是一种设计模式,用于管理和重用对象,以提高性能和资源利用率。对象池的概念在许多应用程序中都有广泛应用,特别是在需要频繁创建和销毁对象的情况下,例如数据库连接、线程、HTTP连接等

对象池通过预先创建一组对象并将它们存储在池中,以供需要时获取和使用。当对象不再需要时,它们不会被销毁,而是被返回到池中,以便在后续的请求中重新使用

对象池的优点包括:

  • 减少对象创建和销毁的开销,提高性能和响应时间
  • 最大限度地利用系统资源,避免资源的浪费
  • 控制对象的数量,防止资源耗尽和系统崩溃
  • 提供对象的重用机制,避免频繁的对象创建和垃圾回收

Apache Commons Pool2

Apache Commons Pool2 是一个广泛使用的Java对象池库,被许多开源项目和企业应用程序采用。它提供了通用的对象池化解决方案,可用于管理各种类型的对象,如数据库连接、线程池、HTTP连接等

Commons Pool 工作原理

核心类

ObjectPool

对象池,负责对对象进行生命周期的管理,并提供了对对象池中活跃对象和空闲对象统计的功能

  • 对象的提供与归还:borrowObjectreturnObject
  • 创建对象:addObject
  • 销毁对象:invalidateObject
  • 池中空闲对象数量、被使用对象数量:getNumActivegetNumIdle

PooledObjectFactory

对象工厂类,负责具体对象的创建、初始化,对象状态的销毁和验证

commons-pool2框架本身提供了默认的抽象实现BasePooledObjectFactory,业务方在使用的时候只需要继承该类,然后实现warpcreate方法即可

PooledObject

池化对象,是需要放到ObjectPool对象的一个包装类。添加了一些附加的信息,比如说状态信息,创建时间,激活时间等

池对象状态及流程

PooledObjectState 池对象状态枚举

public enum PooledObjectState {//在空闲队列中,还未被使用IDLE,//使用中ALLOCATED,//在空闲队列中,当前正在测试是否满足被驱逐的条件EVICTION,//不在空闲队列中,目前正在测试是否可能被驱逐。因为在测试过程中,试图借用对象,并将其从队列中删除。//回收测试完成后,它应该被返回到队列的头部。EVICTION_RETURN_TO_HEAD,//在队列中,正在被校验VALIDATION,//不在队列中,当前正在验证。该对象在验证时被借用,由于配置了testOnBorrow,//所以将其从队列中删除并预先分配。一旦验证完成,就应该分配它。VALIDATION_PREALLOCATED,//不在队列中,当前正在验证。在之前测试是否将该对象从队列中移除时,曾尝试借用该对象。//一旦验证完成,它应该被返回到队列的头部。VALIDATION_RETURN_TO_HEAD,//无效状态(如驱逐测试或验证),并将/已被销毁INVALID,//判定为无效,将会被设置为废弃ABANDONED,//正在使用完毕,返回池中RETURNING
}

流程理解

此段原文自 https://www.cnblogs.com/haixiang/p/14783955.html

对象存储
 private PooledObject<T> create() throws Exception {.....final PooledObject<T> p;try {p = factory.makeObject();.....allObjects.put(new IdentityWrapper<>(p.getObject()), p);return p;}

我们查看allObjects,所有对象都存储于ConcurrentHashMap,除了被杀掉的对象

/** All of the objects currently associated with this pool in any state. It* excludes objects that have been destroyed. The size of* {@link #allObjects} will always be less than or equal to {@link* #_maxActive}. Map keys are pooled objects, values are the PooledObject* wrappers used internally by the pool.*/
private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =new ConcurrentHashMap<>();
对象取用逻辑
  • 首先根据AbandonedConfig配置判断是否取用对象前执行清理操作
  • 再从idleObject中尝试获取对象,获取不到就创建新的对象
    • 判断blockWhenExhausted是否设置为true,是的话按照设置的borrowMaxWaitMillis属性等待可用对象(这个配置的意思是当对象池的active状态的对象数量已经达到最大值maxinum时是否进行阻塞直到有空闲对象)
  • 有可用对象后调用工厂的factory.activateObject方法激活对象
  • getTestOnBorrow设置为true时,调用factory.validateObject(p)对对象进行校验,通过校验后执行下一步
  • 调用updateStatsBorrow方法,在对象被成功借出后更新一些统计项,例如返回对象池的对象个数等

//....
private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
//....
public T borrowObject(final long borrowMaxWaitMillis) throws Exception {assertOpen();final AbandonedConfig ac = this.abandonedConfig;if (ac != null && ac.getRemoveAbandonedOnBorrow() &&(getNumIdle() < 2) &&(getNumActive() > getMaxTotal() - 3) ) {removeAbandoned(ac);}PooledObject<T> p = null;// Get local copy of current config so it is consistent for entire// method executionfinal boolean blockWhenExhausted = getBlockWhenExhausted();boolean create;final long waitTime = System.currentTimeMillis();while (p == null) {create = false;p = idleObjects.pollFirst();if (p == null) {p = create();if (p != null) {create = true;}}if (blockWhenExhausted) {if (p == null) {if (borrowMaxWaitMillis < 0) {p = idleObjects.takeFirst();} else {p = idleObjects.pollFirst(borrowMaxWaitMillis,TimeUnit.MILLISECONDS);}}if (p == null) {throw new NoSuchElementException("Timeout waiting for idle object");}} else {if (p == null) {throw new NoSuchElementException("Pool exhausted");}}if (!p.allocate()) {p = null;}if (p != null) {try {factory.activateObject(p);} catch (final Exception e) {try {destroy(p, DestroyMode.NORMAL);} catch (final Exception e1) {// Ignore - activation failure is more important}p = null;if (create) {final NoSuchElementException nsee = new NoSuchElementException("Unable to activate object");nsee.initCause(e);throw nsee;}}if (p != null && getTestOnBorrow()) {boolean validate = false;Throwable validationThrowable = null;try {validate = factory.validateObject(p);} catch (final Throwable t) {PoolUtils.checkRethrow(t);validationThrowable = t;}if (!validate) {try {destroy(p, DestroyMode.NORMAL);destroyedByBorrowValidationCount.incrementAndGet();} catch (final Exception e) {// Ignore - validation failure is more important}p = null;if (create) {final NoSuchElementException nsee = new NoSuchElementException("Unable to validate object");nsee.initCause(validationThrowable);throw nsee;}}}}}updateStatsBorrow(p, System.currentTimeMillis() - waitTime);return p.getObject();}
对象的激活和钝化

在对象使用完被返回对象池时,如果校验失败直接销毁,如果校验通过需要先钝化对象passivateObject(PooledObject<T> p)再存入空闲队列。至于激活对象的方法activateObject(PooledObject<T> p)在上述取用对象时也会先激活再被取出。因此我们可以发现处于空闲和使用中的对象他们除了状态不一致,我们也可以通过激活和钝化的方式在他们之间增加新的差异

例如我们要做一个Elasticsearch连接池,每个对象就是一个带有ip和端口的连接实例,很显然访问es集群是多个不同的ip,所以每次访问的ip不一定相同,我们则可以在激活操作为对象赋值ip和端口,钝化操作中将ip和端口归为默认值或者空,这样流程更为标准

对象回收机制

EvictionTimer为回收对象的定时器,当且仅当设置了timeBetweenEvictionRunsMillis参数后才会开启定时清理任务

对象状态为evict,直接调用destroy进行回收。否则会进行进一步地处理,逻辑如下:

  1. 尝试激活对象,如果激活失败则认为对象已经不再存活,直接调用destroy进行销毁
  2. 在激活对象成功的情况下,会通过validateObject方法取校验对象状态,如果校验失败,则说明对象不可用,需要进行销毁
// org.apache.commons.pool2.impl.GenericObjectPool#evict
if (evict) {destroy(underTest);destroyedByEvictorCount.incrementAndGet();
} else {if (testWhileIdle) {boolean active = false;try {factory.activateObject(underTest);active = true;} catch (Exception e) {destroy(underTest);destroyedByEvictorCount.incrementAndGet();}if (active) {if (!factory.validateObject(underTest)) {destroy(underTest);destroyedByEvictorCount.incrementAndGet();} else {try {factory.passivateObject(underTest);} catch (Exception e) {destroy(underTest);destroyedByEvictorCount.incrementAndGet();}}}}if (!underTest.endEvictionTest(idleObjects)) {// TODO - May need to add code here once additional// states are used}
}

常用参数详解

参数类型(默认值)描述
lifoboolean(true)当去获取对象池中的空闲实例时,是否需要遵循后进先出的原则
fairnessboolean(false)当对象池处于exhausted状态,即可用实例为空时,大量线程在同时阻塞等待获取可用的实例,fairness配置来控制是否启用公平锁算法,即先到先得。这一项的前提是blockWhenExhausted配置为true
maxTotalint(8)对象池中最大使用数量
maxIdleint(8)对象中空闲对象最大数量
minIdleint(0)对象池中空闲对象最小数量
maxWaitMillislong(-1)最大阻塞时间,当对象池处于exhausted状态,即可用实例为空时,大量线程在同时阻塞等待获取可用的实例,如果阻塞时间超过了maxWaitMillis将会抛出异常
testOnCreateboolean(false)创建对象前,是否校验该新对象的有效性
testOnBorrowboolean(false)取用对象前,是否检验对象的有效性
testOnReturnboolean(false)归还对象前,是否检验对象的有效性
testWhileIdleboolean(false)当回收器在扫描空闲对象时,是否校验对象的有效性
numTestsPerEvictionRunint(3)根据该值x可以推导出一个数值n,标识回收过程需要检查多少个空闲对象。如果x>=0,那么n=x。如果x<0,那么n=(空闲对象数量/x的绝对值)向上取整,假设空闲对象一共有10个,该值配置为-3,那么就意味着这次回收需要检查4个空闲对象
timeBetweenEvictionRunsMillislong(-1)回收器线程多久执行一次空闲对象回收
softMinEvictableIdleTimeMillislong(-1)软回收时间阈值一个对象如果空闲时间超过了该值(毫秒),并且空闲对象的数量已经大于了minIdle时,就可以被回收器回收
minEvictableIdleTimeMillislong(1000L * 60L * 30L)硬回收时间阈值一个对象如果空闲时间超过了该值,即使空闲对象的数量已经小于minIdle了,一样也会被回收器回收

假如在某个高负载的系统里,对象频繁被借出、被归还。此时推荐对象池配置为

  1. testOnBorrowtestOnReturn都设置为false,提升性能
  2. timeBetweenEvictionRunsMillis设置为60000,一分钟进行一次空闲对象的回收检查
  3. numTestsPerEvictionRun设置为-1,检查所有空闲对象
  4. minEvictableIdleTimeMillis设置为180000,空闲超过3分钟的可以被回收
  5. testWhileIdle设置为true,不管空闲时间是否超时,每个空闲对象都检查下有效性,无效的一样被回收

通过异步的回收器来尽可能的保证空闲对象的有效性,减少同步调用时有效性检查导致的响应延迟、以及有效性检查对底层带来的访问压力

总结

Apache Commons Pool2是一个用于对象池化的Java库,它提供了一种管理和重用对象实例的机制,旨在改善应用程序的性能和资源利用率。下面是对Apache Commons Pool2的总结:

  • 对象池化:Apache Commons Pool2允许您创建和管理一个对象池,该对象池中保存着可重用的对象实例。通过将对象保存在池中而不是频繁地创建和销毁对象,可以减少系统开销,提高性能。
  • 对象生命周期管理:Pool2提供了生命周期管理功能,允许您定义在对象从池中借出和归还时的初始化和清理操作。这确保了从池中借出的对象始终处于一种可用状态。
  • 池化策略:Pool2支持多种池化策略,如通用对象池、软引用对象池和弱引用对象池。您可以根据应用程序的需求选择适合的策略。
  • 线程安全:Pool2是线程安全的,它提供了同步机制来处理多个线程同时访问池的情况,确保对象的正确分配和归还。
  • 配置灵活:Pool2允许您通过配置文件或编程方式来配置对象池的各种属性,如最大池大小、最小空闲对象数、池中对象的最大空闲时间等。这使得您可以根据应用程序的需求进行优化和调整。
  • 连接池和资源池:Pool2不仅适用于对象池,还可用于连接池和其他资源的池化管理。这使得它在处理数据库连接、线程池等资源时非常有用。

总的来说,Apache Commons Pool2是一个功能强大且灵活的对象池化库,可帮助您管理和重用对象实例,提高应用程序的性能和资源利用率。无论是在Web应用程序、并发编程还是资源管理方面,Pool2都是一个可靠的选择


参考资料:

  1. Apache Commons Pool
  2. commons-pool2 池化技术探究
  3. 对象池
  4. apache common pool2原理与实战

相关文章:

Apache Commons Pool2 池化技术

对象池是一种设计模式&#xff0c;用于管理和重用对象&#xff0c;以提高性能和资源利用率。对象池的概念在许多应用程序中都有广泛应用&#xff0c;特别是在需要频繁创建和销毁对象的情况下&#xff0c;例如数据库连接、线程、HTTP连接等 对象池通过预先创建一组对象并将它们存…...

二叉树的最近公共祖先LCA

系列题目 236. 二叉树的最近公共祖先 1676. 二叉树的最近公共祖先IV 1644. 二叉树的最近公共祖先 II 235. 二叉搜索树的最近公共祖先 1650. 二叉树的最近公共祖先 III class LowestCommonAncestor:"""236. 二叉树的最近公共祖先题目强调p和q一定存在于二叉树中&…...

AWS SAA知识点整理(作成中)

共通 一些信息已经更新了&#xff0c;但参考题的答案还是旧的。 比如&#xff1a; S3的最大读写性能已经提高到 3,500 PUT/COPY/POST/DELETE or 5,500 GET/HEAD requests per second 并且不再要求使用random prefix 题目中有时候会让选择Not violation 不合适的一项&#xff…...

C++模板大全(持续更新,依不同网站整理而成)

C模板大全 基本模板快读快写快读快写火车头缺省源 基本算法暴力枚举模拟贪心二分三分尺取法分治前缀和差分递推递归倍增排序sort冒泡排序桶排序选择排序插入排序希尔排序归并排序快速排序堆排序计数排序基数排序 基础数据结构栈队列哈希链表单向链表双向链表 单调栈单调队列 高…...

《CTFshow-Web入门》10. Web 91~110

Web 入门 索引web91题解总结 web92题解总结 web93题解 web94题解 web95题解 web96题解 web97题解 web98题解 web99题解总结 web100题解 web101题解 web102题解 web103题解 web104题解 web105题解总结 web106题解 web107题解 web108题解 web109题解 web110题解 ctf - web入门 索…...

计组--总线

一、概念 总线是一组能为多个部件分时共享的公共信息传送线路。 共享是指总线上可以挂接多个部件&#xff0c;各个部件之间互相交换的信息都可以通过这组线路分时共享。 分时是指同一时刻只允许有一个部件向总线发送信息&#xff0c;如果系统中有多个部件&#xff0c;则它们…...

Git中的HEAD

Git中的HEAD HEAD^数字&#xff1a;表示当前提交的父提交&#xff0c;具体是第几个父提交通过数字指定&#xff0c;HEAD^1第一个父提交&#xff0c;该语法只 能用于合并(merge)的提交记录&#xff0c;因为一个通过合并产生的commit对象才有多个父提交。 HEAD~数字&#xff1…...

软件设计师_数据库系统_学习笔记

文章目录 3.1 数据库模式3.1.1 三级模式 两级映射3.1.2 数据库设计过程 3.2 ER模型3.3 关系代数与元组演算3.4 规范化理论3.5 并发控制3.6 数据库完整性约束3.7 分布式数据库3.8 数据仓库与数据挖掘 3.1 数据库模式 3.1.1 三级模式 两级映射 内模式直接与物理数据库相关联的 定…...

毛玻璃态计算器

效果展示 页面结构组成 从上述的效果可以看出&#xff0c;计算机的页面比较规整&#xff0c;适合grid布局。 CSS3 知识点 grid 布局 实现计算机布局 <div class"container"><form class"calculator" name"calc"><input type…...

常说的I2C协议是干啥的(电子硬件)

I2C&#xff08;Inter-Integrated circuit&#xff09;协议是电子传输信号中常用的一种协议。 它是一种两线式串行双向总线&#xff0c;用于连接微控制器和外部设备&#xff0c;也因为它所需的引脚数只需要两条&#xff08;CLK和DATA&#xff09;&#xff0c;硬件实现简单&…...

C/C++进程超详细详解【中部分】(系统性学习day07)

目录 前言 一、守护进程 1.概念 2.守护进程创建的原理&#xff08;如图清晰可见&#xff09; 3.守护进程的实现&#xff08;代码块&#xff09; 二、dup和dup2 1&#xff0c;复制文件描述符 2.文件描述符重定向 三、系统日志 1&#xff0c;打开日志 2&#xff0c;向日…...

S型速度曲线轨迹规划(约束条件为速度和位移)

S型速度曲线规划的基础知识可以查看下面这篇博客: 带平滑功能的斜坡函数(多段曲线控温纯S型曲线SCL源代码+完整算法分析)_RXXW_Dor的博客-CSDN博客PLC运动控制基础系列之梯形速度曲线,可以参看下面这篇博客:PLC运动控制基础系列之梯形速度曲线_RXXW_Dor的博客-CSDN博客运…...

从零手搓一个【消息队列】实现数据的硬盘管理和内存管理(线程安全)

文章目录 一、硬盘管理1, 创建 DiskDataCenter 类2, init() 初始化3, 封装交换机4, 封装队列5, 关于绑定6, 关于消息 二、内存管理1, 数据结构的设计2, 创建 MemoryDataCenter 类3, 关于交换机4, 关于队列5, 关于绑定6, 关于消息7, 恢复数据 三、小结 创建 Spring Boot 项目, S…...

自动驾驶中的感知模型:实现安全与智能驾驶的关键

自动驾驶中的感知模型&#xff1a;实现安全与智能驾驶的关键 文章目录 引言感知模型的作用感知模型的技术安全与挑战结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;全新的PnC培训…...

【CVPR 2023】DSVT: Dynamic Sparse Voxel Transformer with Rotated Sets

文章目录 开场白效果意图 重点VoxelNet: End-to-End Learning for Point Cloud Based 3D Object DetectionX-Axis DSVT LayerY-Axis DSVT Layer Dynamic Sparse Window AttentionDynamic set partitionRotated set attention for intra-window feature propagation.Hybrid wind…...

MySQL超入门(1)__迅速上手掌握MySQL

# 1.选择语句 # 注意事项&#xff1a;MySQL不区分大小写&#xff0c;SELECT * 代表选择全部 // 测试一 USE sql_store; -- 使用 sql_store库 SELECT * FROM customers -- 查询customers表 WHERE customer_id 1 OR customer_id 4 -- 条件判断为customer_id 1或customer_id …...

四、浏览器渲染过程,DOM,CSSDOM,渲染,布局,绘制详细介绍

知识点&#xff1a; 1、为什么不能先执行 js文件&#xff1f;&#xff1f; 我们不能先执行JS文件&#xff0c;必须等到CSSOM构建完成了才能执行JS文件&#xff0c;因为前面已经说过渲染树是需要DOM和CSSOM构建完成了以后才能构建&#xff0c;而且JS是可以操控CSS样式的&#…...

2021-06-10 51单片机设计一个蜂鸣器报警电路每秒

缘由求助一下谢谢啦51单片机_嵌入式-CSDN问答设计一个蜂鸣器报警电路&#xff0c;按下K1&#xff0c;蜂鸣器响一声&#xff0c;按下K2&#xff0c;蜂鸣器响三声&#xff0c;按下K3,蜂鸣器长鸣。要求响声和间隔的时间均为1秒&#xff0c;长鸣不限时&#xff0c;但是此时应设置一…...

D‘Agostino-Pearson正态检验|偏度skewness和峰度kurtosis

DAgostino-Pearson检验&#xff08;也称为DAgostino和Pearson正态性检验&#xff09;是一种用于检验数据是否符合正态分布的统计检验方法。它基于数据的样本统计量&#xff0c;主要包括偏度&#xff08;skewness&#xff09;和峰度&#xff08;kurtosis&#xff09;&#xff0c…...

基于树莓派CM4制作img系统镜像批量制作TF卡

文章目录 前言1. 环境与工具2. 制作镜像3. 烧录镜像4. 总结 前言 树莓派烧录完系统做定制化配置比较费时间。在面对大批量的树莓派要配置&#xff0c;那时间成本是非常巨大的。第一次配置完可以说是摸着石头过河&#xff0c;但是会弄了以后再配置&#xff0c;都是一些重复性操…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

Redis:现代应用开发的高效内存数据存储利器

一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发&#xff0c;其初衷是为了满足他自己的一个项目需求&#xff0c;即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源&#xff0c;Redis凭借其简单易用、…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...