Elastic Stack技术栈
2020-09-29 15:43:42 0 举报
AI智能生成
ElasticSearch
作者其他创作
大纲/内容
ElasticSearch
常见术语
Document 文档
用户存储在ES中的数据文档
常用数据类型:字符串、数值型、布尔型、日期型、二进制、范围类型
每个文档都有一个唯一ID标识。(可以自行指定,也可由ES自动生成)
Index 索引
由具有相同字段的文档列表组成。在当前版本,不在推荐下设Type,在后续版本,不再设立Type
索引中存储相同结构的文档,且每个index都有自己的Mapping定义,用于定义字段名和类型
一个集群中可以有多个inex,类似于可以有多个table
Node 节点
一个ES的实例,构成clister的单元
Cluster 集群
对外服务的一个/多个节点
倒排索引
概念
百度百科:倒排索引源于实际应用中需要根据属性的值来查找记录。
这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。
由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。
带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)
分词
Analysis
ES中专门处理分词的组件,组成和执行顺序如下:
A、Character Filters(多个)。针对原始文本进行处理,如:去除html特使标记符等
B、Tokenizer(一个)。将原始文本按一定规则划分为单词
C、Token Filters(多个)。针对Tokenizer处理的单词进行再加工,如:转小写、删除、新增等
Mapping
常见数据类型
字符串、数值、布尔值、日期、二进制、数组、object、nested object
Search API
字段类查询
match
针对text类型的字段进行全文检索,会对查询语句进行“先分词再查询”处理
term
将待查询语句作为整个单词进行查询,不做分词处理
复合查询
如:bool查询等。包含一个/多个字段类查询/符合查询语句
bool query
由一个/多个布尔子句组成,主要包含以下四个:
filter
只过滤符合条件的文档,不计算相关性得分,返回的相关性得分全部为0
ES会对filter进行智能缓存,因此执行效率较高,在做简单匹配查询且不考虑得分的时候推荐使用filter代替query
must
文档必须符合must中的所有条件,影响相关性得分
must_not
文档必须排除must_not中的所有条件
should
文档可以符合should中的条件,影响相关性得分,分为两种情况:
1、bool查询中只有should,不包含must的情况,满足任意一个条件即可
2、bool查询中既有should,又包含must的情况,文档不必满足should中的条件,但是如果满足的话则会增加相关性得分
Search的运行机制
Query阶段:搜索
Fetch阶段:获取
深度分页
问题:如何在数据分片存储的情况下, 获取前1000个文档?
答案:先从每个分片上获取前1000个文档, 然后由处理节点聚合所有分片的结果之后,再排序获取前1000个文档。
此时页数越深,处理的文档就越多,占用的内存就越大,耗时就越长。这就是深度分页问题。
为了尽量避免深度分页为题,ES通过设定index.max_result_window限定最多到10000条数据。
如何避免深度分页问题?
这个问题目前连google都没能解决,所以只能最大程度避免,通过唯一排序值定位每次要处理的文档数都控制在size内。
说白了就是限制分页数
分布式特性
ES支持集群模式,其好处主要有以下2个
可增大系统容量
提高了系统可用性
集群角色
主节点master
可修改cluster state的节点。一个集群仅一个
选举节点master-eligible
可以参与选举master的节点
配置为:node.master:true。默认所有节点都可以参与选举
协调节点cordinating
处理请求的节点。是所有节点的默认角色,且不能取消
路由请求到正确的节点处理,如:创建索引的请求到master节点
从节点data
存储数据的节点,默认所有节点都是data类型
配置为:node.data:true
副本和分片
提高系统可用性
为了提高系统的可用性,从两个角度进行考虑:
A、服务可用性:在2个/多个节点的情况下,允许1个/一部分节点停止服务,整个集群依然可以对外提供服务;
B、 数据可用性:引入副本(replication)解决1个/一部分节点停止,节点上数据也同时丢失的情况。此时每个节点都有完备数据。
增大系统容量
如何将数据分布到所有节点?答案:分片
什么是分片?
分片是ES能支持PB级别数据的基石
a、分片存储部分数据,可以分布于任意节点;
b、分片数在索引创建时指定,且后续不能更改,默认为5个;
c、有主分片和副本分片之分,以实现数据的高可用;
d、副本分片由主分片同步数据,可以有多个,从而提高数据吞吐量
集群的健康状态
Greed,绿色。表示所有主分片和副本分片都正常分配;
Yellow,黄色。表示所有主分片都正常分配,但有副本分片未分配
Red,红色。表示有主分片未分配
故障转移 Failover
1)什么是故障转移?
在一个多节点集群中的master节点突然宕机,此时集群缺少主节点,
剩余的节点组成新的集群,并将幸存副本分片转为主分片,同时在剩余节点生成副本分片,
并依然对外进行正常服务的情况,称为故障转移。
2)如何进行故障转移?
当其余节点发现定时ping主节点master无响应的时候,集群状态转为Red。
此时会发起master选举。称为master的新主节点发现有主分片没有进行分配,
会将继续工作的节点上的副本分片升级为主分片,此时集群状态转为Yellow。
之后,主节点会为对应节点生成未分配的副本分片,此时集群状态转为Green。
整个故障转移过程结束。
文档分布式存储
Document最终存储到分片上,那么文档的数据是如何选择要存储的分片的呢?
此时,就需要文档到分片的映射算法,routing路由
文档创建的流程
A、Client向node3发送创建文档请求
B、node3通过routing计算该文档存储在shard1上,查询cluster state后,确认主shard1在node2上,然后转发请求到node2
C、node2上的主shard1接收并执行创建文档的请求后,将同样的请求转发到副shard1,查询cluster state后,确认副shard1在node1,向node1发送请求
D、node1上的副shard1接收并执行创建文档的请求后, 通知主shard1结果
E、node2上的主shard1接收到副shard1创建文档成功的结果,通知node3创建成功
F、node3返回结果给Client
文档读取的流程
A、Client向node3发送读取文档doc1的请求
B、node3通过routing计算该doc1在shard1上,查询cluster state后,确认主shard1和副shard1的位置,然后以轮询的机制获取一个shard(比如这次是主shard1,下次就是副shard1)
C、本次是在node2上的主shard1接收到读取文档的请求,执行并返回结果给node3
D、node3返回结果给Client
文档批量读取的流程
A、Client向node3发送批量读取文档请求(bulk)
B、node3通过routing计算文档对应的所有shard,再以轮询的机制,按shard构建mget请求,通过发送给设计的shard
C、由shard返回文档结果
D、node3整合后返回结果到Client
脑裂问题
什么是脑裂问题?
在分布式系统中有一个经典的网络问题
当一个集群在运行时,作为master节点的node1的网络突然出现问题,无法和其他节点通信,出现网络隔离情况。
那么node1自己会组成一个单节点集群,并更新cluster state;同时作为data节点的node2和node3因为无法和node1通信,
则通过选举产生了一个新的master节点node2,也更新了cluster state。
那么当node1的网络通信恢复之后,集群无法选择正确的master。
如何解决脑裂问题?
解决方案也很简单:仅在可选举的master-eligible节点数 >= quorum的时候才进行master选举
简单说就是节点过半选举
Shards分片详解
1)倒排索引一旦生成,不能更改
优点
不用考虑并发写文件的问题,杜绝了锁机制带来的性能问题
文件不在更改,则可以利用文件系统缓存,只需载入一次,只要内存足够,直接从内存中读取该文件,性能高
利于生成缓存数据(且不需更改)
利于对文件进行压缩存储,节省磁盘和内存存储空间
缺点
在写入新的文档时,必须重构倒排索引文件,然后替换掉老倒排索引文件后,新文档才能被检索到,导致实时性差
2)解决文档搜索的实时性问题的方案
新文档直接生成新待排索引文件,查询时同时查询所有倒排索引文件,然后做结果的汇总即可,从而提升了实时性
3)Segment
Lucene中构建的单个倒排索引,多个Segment合在一起称为Index(Lucene中的Index),Lucene中的一个index对应ES中的shard分片
Segment写入磁盘的过程依然很耗时,可以借助文件系统缓存的特性。【先将Segment在内存中创建并开放查询,来进一步提升实时性】,这个过程在ES中被称为:refresh。
在refresh之前,文档会先存储到一个缓冲队列buffer中,refresh发生时,将buffer中的所有文档清空,并生成Segment
ES默认每1s执行一次refresh操作,因此实时性提升到了1s。这也是ES被称为近实时的原因(Near Real Time)
4)translog文件
当文档写入buffer时,同时会将该操作写入到translog中,
这个文件会即时将数据写入磁盘,在6.0版本之后默认每个要求都必须落盘,这个操作叫做fsync操作。
这个时间也是可以通过配置:index.translog.*进行修改的。
比如每五秒进行一次fdync操作,那么风险就是丢失这5s内的数据
这个操作解决了:在节点写入磁盘之前就发生了宕机,这时候内存中的segment丢失的问题
5)文档搜索实时性—flush(十分重要)
flush的功能,就是:将内存中的Segment写入磁盘,主要做如下工作:
A、将translog写入磁盘;
B、将index bufffer清空,其中的文档生成一个新的Segment,相当于触发一次refresh;
C、更新Commit Point文件并写入磁盘;
D、执行fsync落盘操作,将内存中的Segment写入磁盘;
E、删除旧的translog文件。
6)refresh与flush的发生时机
A、refresh:发生时机主要有以下几种情况:
a、间隔时间达到。
通过index.settings.refresh_interval设置,默认为1s。
b、index.buffer占满时。
通过indices.memory.index_buffer_size设置,默认JVM heap的10%,且所有shard共享。
c、flush发生时。会触发一次refresh。
B、flush:发生时机主要有以下几种情况:
a、间隔时间达到。
5.x版本之前,通过index.translog.flush_threshold_period设置,默认30min。
5.x版本之后,ES强制每30min执行一次flush,不能再进行更改。
b、translog占满时。
通过index.translog.flush_threshold_size设置,默认512m。且每个Index有自己的translog。
7)删除和更新文档
A、删除:
Segment一旦生成,就不能更改,删除的时候,Lucene专门维护一个.del文件,记录所有已删除的文档。
.del 文件 上记录的是文档在Lucene中的ID,在查询结果返回之前,会过滤掉.del 文件 中的所有文档。
B、更新:
先删除老文档,再创建新文档,两个文档的ID在Lucene中的ID不同,但是在ElasticSearch中ID相同。
8)Segment Merging(合并)
A、随着Segment的增多,由于每次查询的Segment数量也增多,导致查询速度变慢;
B、ES会定时在后台进行Segment merge的操作,减少Segment数量;
C、通过force_merge api可以手动强制做Segment的合并操作。
聚合分析
聚合分析,英文Aggregation,是ES除了搜索功能之外提供的针对ES数据进行统计分析的功能
聚合分析格式
#聚合分析格式:
GET my_index/_search
{
"size":0,
"aggs":{ #关键词
"":{ #自定义聚合分析名称,一般起的有意义
"":{ #聚合分析类型
"" #聚合分析主体
}
}
[,"aggs":{[]+}] #可包含多个子聚合分析
}
}
分类
Metric。指标分析类型,如:计算最值,平均值等
Bucket。分桶类型,类似于group by语法,根据一定规则划分为若干个桶分类
Pipeline。管道分析类型,基于上一级的聚合分析结果进行再分析
Matrix。矩阵分析类型
Metric聚合分析
min
max
avg
sum
cardinality
stats
Bucket聚合分析
Bucket,意为桶。即:按照一定规则,将文档分配到不同的桶中,达分类的目的。常见的有以下五类:
1)Terms。直接按term进行分桶,如果是text类型,按分词后的结果分桶
2)Range。按指定数值范围进行分桶
3)Date Range。按指定日期范围进行分桶
4)Histogram。直方图,按固定数值间隔策略进行数据分割
5)Date Histogram。日期直方图,按固定时间间隔进行数据分割
Pipeline聚合分析
针对聚合分析的结果进行再分析,且支持链式调用
聚合分析的作用范围
ES聚合分析默认作用范围是query的结果集
1)filter,为某个结合分析设定过滤条件,从而在不改变整体query语句的情况下修改范围
2)post_filter,作用于文档过滤,但在聚合分析之后才生效
3)global,无视query条件,基于所有文档进行分析
数据建模
1)ES是基于Luence以倒排索引为基础实现的存储体系,不遵循关系型数据库中的范式约定
2)Mapping字段相关设置
A、enabled。 true/false。仅存储,不做搜索或聚合分析是设为false。
B、index。 true/false。是否构建倒排索引。不需进行字段的检索的时候设为false。
C、index_options。 docs/freqs/positions/offsets。确定存储倒排索引的哪些信息。
D、norms。 true/false。是否存储归一化相关系数,若字段仅用于过滤和聚合分析,则可关闭。
E、doc_values。 true/false。是否启用doc_values,用于排序和聚类分析。默认开启。
F、field_data。 true/false。是否设text类型为fielddata,实现排序和聚合分析。默认关闭。
G、store。 false/true。是否存储该字段。
H、coerce。 true/false。 是否开启数值类型转换功能,如:字符串转数字等。
I、multifields。 多字段。灵活使用多字段特性来解决多样业务需求。
J、dynamic。 true/false/strict。控制mapping自动更新。
K、date_detection。 true/false。是否启用自定识别日期类型,一般设为false,避免不必要的识别字符串中的日期。
3)Mapping字段属性设定流程
A、是何种类型?
a、字符串类型。
需要分词,则设为text,否则设为keyword。
b、枚举类型。
基于性能考虑,设为keyword,即便该数据为整型。
c、数值类型。
尽量选择贴近的类型,如byte即可表示所有数值时,即用byte,而不是所有都用long。
d、其他类型。
如:布尔型,日期类型,地理位置类型等。
B、是否需要检索?
a、完全不需要检索、排序、聚合分析的字段。
enabled设为false。
b、不需检索的字段。
index设为false。
c、需检索的字段,可通过如下配置设定需要的存储粒度。
index_options 结合需要设定。
norms 不需归一化数据时可关闭。
C、是否需要排序和聚合分析?
当不需要排序和聚合分析功能时:
doc_values设为false。
field_data设为false。
D、是否需要另行存储?
store设为true。即可存储该字段的原始内容(且与_source无关),一般结合_source的enabled设为false时使用
ES中关联关系处理
ES不擅长处理关系型数据库中的关联关系,因为底层使用的倒排索引,如:文章表blog和评论表comment之间通过blog_id关联。在ES中可以通过两种方式变相解决:
①Nested Object
②Parent/Child
reindex
指重建所有数据的过程
①mapping设置变更,如:字段类型变化,分词器字典更新等
②index设置变更,如:分片数变化
③迁移数据
集群优化
写性能优化
写性能优化,主要还是index级别的设置优化
①Client:多线程写,批量写bulk;
②ES:在高质量数据建模的前提下,主要在refresh、translig和flush之间做文章。
1)降低refresh写入内存的频率
A、增大refresh_interval,降低实时性,增大每次refresh处理的文件数,默认1s。可以设为-1s,禁止自动refresh。
B、增大index buffer大小,参数为:indices.memory.index_buffer_size。此为静态参数,需设定在elasticsea.yml中,默认10%
2)降低translog写入磁盘频率,同时会降低容灾能力
A、index.translog.durability:设为async;
index.translog.sync_interval。设置需要的大小如:120s => 每120s才写一次磁盘。
B、index.translog.flush_threshold_size。默认512m。
即当translog大小超过此值,会触发一次flush,可以调大避免flush过早触发
3)在flush方面,从6.x开始,ES固定每30min执行一次,所以优化点不多,一般都是ES自动完成
4)其他
A、将副本数设置为0,在文档全部写完之后再加副本;
B、合理设计shard数,保证shard均匀地分布在所有node上,充分利用node资源:
index.routing.allocation.total_shards_per_node:限定每个索引在每个node上可分配的主副分片数,
读性能优化
1)高质量的数据建模
A、将需通过scripte脚本动态计算的值,提前计算好作为字段存入文档中;
B、尽量使数据模型贴近业务模型
2)根据不同数据规模设定不同的SLA(服务等级协议),万级数据和千万级数据和亿万级数据性能上肯定有差异;
3)索引配置优化
A、根据数据规模设置合理的分片数,可通过测试得到最适合的分片数;
B、分片数并不是越多越好
4)查询语句优化
A、尽量使用Filter上下文,减少算分场景(Filter有缓存机制,能极大地提升查询性能);
B、尽量不用scripte进行字段计算或算分排序等;
C、结合profile、explain API分析慢查询语句的症结所在,再去优化数据模型。
其他优化点
CURL命令的PUT和POST对比
PUT是幂等方法,而POST并不是。
PUT用于更新操作,POST用于新增操作比较合适。
PUT,DELETE操作是幂等的,所谓幂等就是指不管进行多少次操作,结果都一样。
POST操作不是幂等,比如常见的POST重复加载问题:当我们多次发出同样的POST请求后,其结果是创建出了若干的资源。
还有一点需要注意的是,创建操作可以使用POST,也可以使用PUT。
区别在于POST是作用在一个集合资源之上的(/articles),而PUT操作是作用在一个具体资源之上的(/articles/123),
比如说很多资源使用数据库自增主键作为标识信息,而创建的资源的标识信息到底是什么只能由服务端提供,这个时候就必须使用POST。
ElasticStack概述
特点
1)使用门槛低,开发周期短,上线快
2)性能好,查询快,实时展示结果
3)扩容方便,快速支撑增长迅猛的数据
ElasticStack各组件作用
1)ElasticSearch ====> 数据存储、查询和分析 (核心引擎)
2)LogStash + beats ====> 数据收集和处理 (类似于ETL)
3)Kibana ====> 数据探索与可视化分析
ElasticStack使用场景
1)搜索引擎
2)日志分析
3)指标分析
0 条评论
下一页