目录
一、Elasticsearch是什么?
Elasticsearch是一个高度可扩展的开源全文搜索和分析引擎。它允许您快速、近实时地存储、搜索和分析大量数据。它通常用作支持具有复杂搜索功能和需求的应用程序的底层引擎/技术。
二、ES模块架构模型
1.ES整体架构
Elasticsearch服务的主要组成部分如图1-1所示。
对Elasticsearch Nodes进行了种类划分:EsMaster、EsNode1~9和EsClient。
集群服务职责规划:
- EsMaster:Elasticsearch的主节点,负责Master选举和集群管理。
- EsNode1~9:Elasticsearch的数据节点,负责数据索引和搜索。
- EsClient:Elasticsearch的协调节点,负责处理请求,搜索,及分发索引等操作。自身不存储数据,也不管理集群。
Elasticsearch服务的主要组成部分:
本文重点关注的是Elasticsearch写入索引和查询数据的性能问题,基于以上的组件框架图,下面来了解一下Elasticsearch写入索引和查询索引数据的具体流程。
2.索引流程
2.1 写入索引流程:
过程描述:
- 客户端发送一个请求给任意节点,假设是Node 1。
- Node 1通过请求判断出该文档应该被存储的分片,假设是shard 0这个分片,因此Node 1会把请求转发到shard 0的primary shard P0存在的Node 3节点上。
- Node 3在shard 0的primary shard P0上执行请求。如果请求执行成功,Node 3并行地将请求发给shard 0的所有存在于Node 1和Node 2中的replica shard R0上。如果所有的replica shard都成功地执行了请求,那么将会向Node 3回复一个确认成功,当Node 3收到了所有replica shard的确认信息后,则向用户返回一个Success消息。
2.2 查询流程
Elasticsearch查询流程分为两个阶段,即查询(query)阶段与提取(fetch)阶段。
查询阶段流程如图所示:
- 客户端发送一个检索请求给任意节点,假设是Node 3。
- Node 3将检索请求发送给该index中的每一个shard,此时会采取轮询策略,在primary shard及其所有replica shard中随机选择一个,让读请求负载均衡。每个shard在本地执行检索,并将结果排序添加到本地。
- 每个shard返回本地所记录的结果,发送给Node 3。Node 3将这些值合并,做全局排序。
查询阶段主要定位了所要检索数据的具体位置,而提取阶段的任务就是将这些定位好的数据内容取回并返回给客户端。提取阶段如图所示:
- Node 3获取了所有待检索数据的定位之后,发送请求给与数据相关的shard。
- 每个收到Node 3请求的shard,将读取相关文档中的内容,并将它们返回给Node 3。
- 当Node 3获取到了所有shard返回的文档后,Node 3将它们合并成一条汇总结果,返回客户端。
2.3 基本概念
- Index:即索引,是Elasticsearch中一个逻辑命名空间,指向一个或多个分片,内部Apache Lucene实现索引中数据的读写。索引与关系数据库实例Database相当。一个Elasticsearch实例可以包含多个索引。
- Type:文档类型,文档类型使得同一个索引中在存储结构不同的文档时,只需要依据文档类型就可以找到对应的参数映射信息,方便文档的存储。相当于数据库中的Table。一个索引对应一个文档类型。
- Document:文档,是可以被索引的基本单位,特指最顶层结构或根对象序列化成的JSON数据。相当于数据库中的Row。一个类型包含多个文档。
- Mapping:映射,用来约束字段的类型,可以根据数据自动创建。相当于数据库中的Schema。
- Primary Shard:主分片,索引中的每个文档属于一个单独的主分片,主分片的数量决定了索引最多能存储多少数据。
- Rreplica Shard:即复制分片,它是主分片的一个副本,可以防止硬件故障导致的数据丢失,同时可以提供读请求,比如搜索或者从别的shard取回文档。
Segments:Lucene index是由许多segments构成,每个segment都是一个write-once,read many times(类似于HDFS文件,写完后不可修改)。每个segment都是一个小的Lucene index。Segment merge就是利用多个小的segments来合并为一个大的、新的segment的过程,新的segment包含有旧的segments。每次merge消耗资源大,因为lucene要重写它。在删除docement的过程中,其实Lucene只是将该document标记为deleted,然后在segment merge的过程中,被标记为deleted的docment会从物理上移除。
3.性能衡量指标
3.1衡量指标
- 批量索引速率
- 处理搜索的并发量和不同并发量下搜索的响应时间
- 实时索引条件下,处理搜索的并发量和不同并发量下搜索的响应时间
3.2指标观测方法
- 批量索引速率观测方法
从磁盘IO的角度来考虑,通过测试每秒处理的索引文件字节数来衡量,通常可以给定待建索引的一定量数据D(M),在各种参数调整到最合理状态下,记录Elasticsearch导入这批数据的时间T(s),然后计算出每秒处理的数据字节数v=D/T (M/s)。
- 处理查询的并发量观测方法
在网络带宽范围内,并发测试能稳定返回结果时,每秒能处理的最大并发请求数来衡量。通常可以通过构造不重复的查询参数的查询请求,不断增加并发量,同时观察硬件资源的使用率,以及查询响应的平均时间,在当前硬件资源达到瓶颈的情况下,且查询响应时间正常稳定,系统所能处理的最大并发请求数量。 具体的方法,指标,手段
- 不同并发量下返回结果的响应时间观测方法
通过测试不同并发请求数的情况下,正常稳定返回查询结果的时间来衡量。在测试处理查询的并发量的过程中,获取查询响应的稳定时间。
- 实时索引条件下,处理搜索的并发量和不同并发量下搜索的响应时间观测方法
启动实时创建索引的流程的同时,使用2、3的测试方法,测试处理搜索的并发量和不同并发量下搜索的响应时间。
4.ES 的推荐配置与部署
1.频繁的请求下,Elasticsearch对内存、CPU、网络与磁盘的性能有较高的要求,一般情况下,建议Elasticsearch独占这些物理资源,尽量不与其他耗资源的组件合布。
建议配置:
内存:256G,
CPU:56 vcore.
硬盘:24*1.2T Sass盘。
5.根据不同的配置,对进行性能测试
以下配置:
内存:256G,
CPU:48 vcore.
硬盘:12*4T sata盘。
共6台机器
不同节点规模下写入性能测试结果:
集群节点数 |
副本数 |
一次bulk批量写入数 |
并发线程数 |
CPU使用率 |
写入文档数 |
写入速度(MB/node/s) |
6 |
1 |
1000 |
150 |
60% |
300000000 |
3.6 |
说明: 考虑到数据写入到磁盘所占的容量大小,会随后台段合并而发生变化,每次测试周期较长(平均每次测试时间3-4小时)为了保证数据的正确性,以实际写入的索引条数为准。每条数据的大小为1.6Kb。
即:写入速度=写入索引条数*每条数据量大小/1024/索引写入时间/EsNode实例个数(例:3MB/node/s)
集群节点数 |
副本数 |
10并发查询响应时间 |
50并发查询响应时间 |
100并发查询响应时间 |
200并发查询时间 |
500并发查询时间 |
6 |
1 |
2.62s |
2.98s |
3.05s |
3.15s |
5.13 |
说明:3亿条数据,大小1.4T,全文检索查询某个值,数据使用的Elasticsearch的标准分词器。
当前可以参考2.2、2.3、2.4的理论计算方法部署规划。
6.物理资源规划
6.1 内存配置
Elasticsearch单实例(node)默认分配的HeapSize为4GB,资源允许的情况下,单个实例可以分配的最大HeapSize配置为31GB。建议多部署一个专门用于查询的实例。
另外,需要留下一半的物理内存作为Lucene缓存使用。如果不按照此建议设置,将会影响索引与查询的性能。
示例:
- 如果系统为128GB物理内存,那么建议留下64GB预留给Lucene缓存,剩下的64GB可以分配2个Elasticsearch实例(nodes)。每个实例分配31GB内存。
- 如果系统为256GB物理内存,那么建议留下128GB预留给Lucene缓存,剩下的128GB可以分配4个Elasticsearch实例(nodes)。每个实例分配31GB内存。
注意:务必留一半的内存给lucene缓存
6.2 磁盘挂载
Elasticsearch单索引数据目前可以较优支持到TB级别,数据量庞大,建议Elasticsearch按照实例(nodes)进行单独挂盘。
示例:
用户某个物理机上分配了两个Elasticsearch nodes,分别是EsNode1和EsNode2。由于FusionInsight Elasticsearch的“node.max_local_storage_nodes”默认为“1”,即一个实例只对应写一个固定磁盘。现在需要为这两个实例挂载两个磁盘,挂载目录分别为“/data /ess/node1/”和“/data /ess /node2/”。 说明
- 磁盘类型不同,性能也相差巨大。如:SSD读写速度大约是SAS盘的50倍,而SAS盘读写速度可以达到SATA盘的2倍以上。
- 推荐每个Elasticsearch实例的挂载目录大小为1.2-6TB左右,最大支持18TB。
- 建议各Elasticsearch实例磁盘大小保持一致,防止实例磁盘空间使用率超过90%后触发节点之间的分片频繁迁移,降低对Elasticsearch读写性能的影响。
6.3 cpu 配置
关于CPU消耗,如果查询需要做排序则需要字段对比,消耗CPU比较大,如果有可能尽量分配16核以上的CPU,具体根据业务压力来配置CPU核数。
6.4 物理节点数计算
举例:某项目Elasticsearch历史数据150亿,每日增量为10亿,存储周期为60天。单条数据为1k,有两个副本(包含原数据),有12盘,6个盘做做一组raid5,硬盘空间利用率80%。服务器内存256G,。
历史数据(亿):150
每日增量(亿):10
存储周期(天):60
单数据大小(K): 1k
副本(包含原数据):2
Raid利用率: 5/6
硬盘利用率: 0.8
服务器内存(G): 256G
服务器硬盘(T): 12*1.2
副本(包含原数据):2
6.4.1 按照磁盘容量评估
计算公式
服务器数量=每日增量(亿)*存储周期(天)*单数据大小(K)*(100000000/1024/1024/1024)*副本/Raid利用率/硬盘利用率/(服务器硬盘(T))
例子:
服务器数量=(150+10*60)*1*(100000000/1024/1024/1024)*2/(5/6)/0.8/(12*1.2)
=16.17
向上取整服务器数量为17台。
6.4.2 按照最佳入库性能评估
对一张表,每个节点一个分片可以达到入库与查询这个表的最佳性能。
这时跟据一个字段的查询的性能可达到500qps
(配置:256G内存,12*1.2Tsas盘,64 vcore)
Ps:这个当做一个参考,实例的数据不能少于这个评估值的1/4。
计算公式
服务器数量=每日增量(亿)*单数据大小(K)*(100000000/1024/1024)/平均每个分片的大小(G)/(服务器内存/2/32)
例子:
服务器数量=10*1*(100000000/1024/1024)/25/256/2/32
=9.53
向上取整服务器数量为10台。
6.4.3 按照最佳实践的经验评估
数据与内存配比(日志型:16(16-40),全量型:60(60-100))
计算公式:
服务器数量= (历史数据(亿)+每日增量(亿)*存储周期(天))*单数据大小(K)*(100000000/1024/1024)*(内存大小/2)/数据与内存配比
例子:
服务器数量=(150+10*60)*1*(100000000/1024/1024)*2/(256/2)/60
=7.4
6.4.4 服务器最终评估
取:根据容量、最佳入库性能、最佳实践的评估取最大值(或根据实现情况小调整)。
7.索引参数设置
7.1 shard个数规划
一个index可以被分为多个shards,从而分布到不同的物理机上。Shard的划分结果也会影响索引和查询速度。
在划分shard的过程中,需要注意以下几点信息:
- 总的shard个数建议是Elasticsearch nodes个数的整数倍,因为尽可能保持每个node的负荷是一样的,这样在查询的时候就不会出现短板。
- 应该根据数据量的规划大小来决定shard个数,一般来说,预计存储的数据量越大,应当分配的shard越多,分布式查询的优势越明显。如果确认某个index的数据量非常少(如一年不到1GB),那么过多的分配shard,反而可能不如单shard的性能好。
- 每个shard包含的数据条数越多,查询性能会降低(建议1亿条左右,最多建议不超过4亿)。每个shard大小不要超过50GB,推荐20-30GB,100GB以下的index设置成3-5个shard,超过100GB的index单shard建议不超过30GB。
- 每个node可以支撑的shards个数是有限的,node是物理资源分配的对象,随着shards中数据的增大,shards中的数据在查询时被不断加载到内存,达到一定量时,将会把HeapSize耗尽,导致频繁GC,系统将不能正常工作。推荐1GB内存管理15个shard,以一个Elasticsearch实例内存最大31G为例,单实例管理的shard数保持在500以内。
7.2 Mapping的设置
合理地向Elasticsearch中进行数据索引时,也要注意以下几点:
- Elasticsearch可以对数据做动态mapping,但请不要这么做,尽量在创建index时便赋予index固定的mapping配置。
- 如果数据量巨大,可以分的字段个数太多,如超过1000个字段,最好给字段赋予不同的级别索引到不同的index中。例如,常用的查询字段可以写入到一个index中,字段长度较长且不常用的索引到另一个index中。
- 合理的设计Mapping,根据实际的业务数据去设置优化Mapping,根据具体的字段和需求去选择对应的类型设置,可参考如下几点:
- 分片控制25G一个分片,如果数据大于小1k,即2500w一个分片。如果数据为0.5k,为5000w一个分片
- 一个表如果大部份的场景有用身份证或手机号进行查询时,一定要用route=xx进行路由,加快查询速度
- 字符串类型默认分成:text和keyword两种类型。需要分词:text,否则keyword。
- 对不会用到排序和聚合的,doc_valuse 设置为false .对日志类比较大的数据量,一定要设置,如:auth,post,pm,log等量比办大的类
- 如果某个字段不需要被检索,将“index”参数设置为“false”。
- 对网安的日志类和hbase混合使用的,_source 设置为false,除id
- norms字段,norm是索引评分因子,如果不用按评分对文档进行排序,设置为“false”,默认是“true”。
- 对需要进行全文检索的字段设置合理的分词器,不同的分词器查询效率相差较大。
- _source字段,默认是开启的,如果不需要update、reindex和高亮操作,可以禁止“_source”,节省更多的磁盘空间。
总结
大家对本文有好的建议或见解,欢迎沟通!三克油!