Elasticsearch

Elasticsearch

第一章 基础概念

1.1 基本概念

  • nrt

接近实时搜索,索引有1秒的延迟

  • index

    存储数据的索引

  • cluster

    代表一个集群,去中心化节点

  • document

    索引的实体

  • mapping

    文档写进索引之前都会先进行分析,如何将输入的文本分割为词条、哪些词条又会被过滤

  • type

    每个文档都有与之对应的类型

  • shard

    索引分片,分片的数量只能在索引创建前指定,并且索引创建后不能更改,默认情况下,Elasticsearch中的每个索引分配5个主分片和1个复制

  • replicas

    分片副本,副本的作用一是提高系统的容错性,提高es的查询效率,es会自动对搜索请求进行负载均衡

  • river

    同步数据到es中

  • discovery

    ES节点自动发现机制,基于p2p的系统,先通过广播寻找存在的节点,然后通过多播协议来进行数据通信,支持点对点的交互

  • gateway

    ES索引的持久化存储方式,es默认是先把索引存放到内存中,当内存满了时再持久化到硬盘

  • Transport

    内部节点或集群与客户端的交互方式,默认内部是使用tcp协议进行交互其它方式可以通过插件方式集成

1.2 角色分类

  • masternode

    元数据的处理,索引操作功能的分配

  • datanode

    负责数据相关操作,比如分片的 CRUD,以及搜索和整合操作,消耗CPU IO 内存

  • Client node

    路由请求的作用,实际上可以看做负载均衡器,如果请求不是很多的业务,这个可以不加

第二章 Discovery

2.1 集中节点的自动发现

ZenDiscovery
	ZenPing
		UnicastZenPing
			一个节点使用发现机制来发现其他节点的过程
	Unicast
		传播的路由器

2.2 master节点的选举

Bully算法
	机制
		进程向所有编号比它大的进程发送一个election消息
			如果无人响应,那么当前进程获胜
			如果编号比他大的进程响应,则由响应者接管选举工作,当前进程工作完成
			【 任何一个时刻,一个进程只能从编号比他小的进程接受election消息】
		 任何一个时刻,一个进程只能从编号比他小的进程接受election消息
	问题
		假死现象,导致系统极度不稳定
算法优化
	把所有可以成为master的节点按照nodeid进行排序
	然后选出第一个节点,暂且认为它是master节点
	对某个节点的投票数达到一定的值(可以成为master节点数n/2+1)
	如果当前节点也是选举自己,那么当前节点就是master,否则重新选举
脑裂问题
	把候选master节点最小值设置为可以成为master节点数为quornm
		一般quornm=(n/2+1)
			大于集群节点数量的一半

2.3 节点错误侦查

FaultDetection
	MasterFaultDetection
		每个节点ping到master,进行错误检测
	NodesFaultDetection
		node会比较自己的version和另外master的version;如果比别人的小,就会stop掉自己的nodesFD和masterFD,然后rejoin进集群
		如果version比别人的大,那么当前node仍然是master,它会向另一个master发出rejoin指令
	概要

2.4 负责state的维护和管理

负责State的下发/维护集群状态/配置的更新
	当集群创建好,且选举了master
		ClusterState
			同步最新状态

第三章 Gateway

3.1 功能

数据持久化方式,集群在启动的时候,恢复数据,只恢复索引级,不包括shard级

3.2 存储文件

state,元数据信息

集群层面元信息
	MetaData
		settings, templates
索引层面元信息
	IndexMetaData
		numberOfShards,mappings
		MappingMetaData
分片层面元信息
	ShardStateMetaData
		version,indexUUID,primary

index: lucene生成的索引的文件

Translog:产生的事务日志

优化参数配置
	index.translog.interval
		默认5s。时间过长,会超出下面阈值比较大。
	index.translog.flush_threshold_ops 
		超过多少条日志后需要flush,默认Int的最大值
	index.translog.flush_threshold_period
		定时flush,默认30m 可动态设置
	index.translog.flush_threshold_size
		translog 大小超过多少后flush,默认512m 

3.3 数据恢复

recovery

ES集群可能会有整体重启的情况,比如需要升级硬件、升级操作系统或者升级ES大版本。重启所有结点可能带来的一个问题: 某些结点可能先于其他结点加入集群, 先加入集群的结点可能已经可以选举好master,并立即启动了recovery的过程,由于这个时候整个集群数据还不完整,master会指示一些结点之间相互开始复制数据。 那些晚到的结点,一旦发现本地的数据已经被复制到其他结点,则直接删除掉本地“失效”的数据。 当整个集群恢复完毕后,数据分布不均衡,显然是不均衡的,master会触发rebalance过程,将数据在节点之间挪动。整个过程无谓消耗了大量的网络流量;合理设置recovery相关参数则可以防范这种问题的发生。

参数讲解

gateway.expected_nodes
gateway.expected_master_nodes
gateway.expected_data_nodes
以上三个参数是说集群里一旦有多少个节点就立即开始recovery过程。 不同之处在于,第一个参数指的是master或者data都算在内,而后面两个参数则分指master和data node。在期待的节点数条件满足之前, recovery过程会等待gateway.recover_after_time (默认5分钟) 这么长时间,一旦等待超时,则会根据以下条件判断是否启动:
gateway.recover_after_nodes
gateway.recover_after_master_nodes
gateway.recover_after_data_nodes

实例配置

gateway.expected_data_nodes: 10
gateway.recover_after_time: 5m
gateway.recover_after_data_nodes: 8

那么集群5分钟以内10个data node都加入了,或者5分钟以后8个以上的data node加入了,都会立即启动recovery过程。

核心实现类

实现类
	GatewayMetaState
		读取恢复数据
	GatewayService
		生成内容路由信息
	GatewayAllocator
		执行数据路由

3.4 悬空索引

DanglingIndicesState
	如果一个新的maste节点启动,并位感知到其他旧节点存储的索引信息,这时候添加旧节点会导入索引数据,避免数据被删除
	一个旧的索引可以直接copy它的data目录到一台新机器,然后将新机器加入集群,这时候数据就会导入集群,带replica满足要求后(,就可以把机器移除了DanglingIndicesState
	如果一个新的maste节点启动,并位感知到其他旧节点存储的索引信息,这时候添加旧节点会导入索引数据,避免数据被删除
	一个旧的索引可以直接copy它的data目录到一台新机器,然后将新机器加入集群,这时候数据就会导入集群,带replica满足要求后(,就可以把机器移除了

3.5 恢复流程

主分片恢复
	把当前translog做成快照,重放每条记录
	调用标准的index来操作创新或更新doc来恢复
	再处理recovery过程中新写入的数据
副本分片恢复
	对比分段信息,如果syncid相同且doc文档数量相同,就跳过,否则复制整个分段
	把当前 translog 做快照,发送所有的 translog operation 到对端节点
	RecoverySource
		主分片是数据源头
	RecoveryTarget
		分片数据是目标

3.6 慢的原因

副本分片恢复的第一阶段,各节点单独执行分段合并逻辑,合并后的分段基本不会相同,所以拷贝 lucene 分段是最耗时的

解决方案

先执行 synced flush,
	syncd flush 并且本身也可能比较慢,因为我们常常为了优化写入速度而加大 translog 刷盘周期,也会延长 translog 恢复阶段时间
	只对冷索引有效,对于热索引(5分钟内有更新的索引)没有作用

优化方案

对比序号
	global checkpoint
		主分片负责维护global checkpoint,
	local checkpoint
		local checkpoint代表当前分片已写入成功的最新位置,
	基于6.0之后的版本
 > 关于checkpoint需要仔细琢磨一下.....

3.7 分片路由

触发机制

节点增,删
手工route
副本数量改变
集群重启

类型

创建索引
	allocators负责找出所有分片数最少的节点列表,并按分片数量进行升序排序
	分片数量最少的节点会被优选选择
	ders依次遍历allocators给出的节点, 并判断是否把分片分配到该节点
已有索引
	要区分主分片还是副本分片
	. 对于主分片, allocators只允许把主分片指定在已经拥有该分片完整数据的节点上
	而对于副本分片, allocators则是先判断其他节点上是否已有该分片的数据的拷贝

3.8 分片决策

AllocationDecider
	SameShardAllocationDecider
		避免主副分片分片到同一个节点
	AwarenessAllocationDecider
		感知分配器,尽量分散存储shard
	ThrottlingAllocationDecider
		recovery阶段的限速配置
			cluster.routing.allocation.node_concurrent_recoveries
			cluster.routing.allocation.node_initial_primaries_recoveries
			cluster.routing.allocation.node_concurrent_incoming_recoveries
			cluster.routing.allocation.node_concurrent_outgoing_recoveries
	ConcurrentRebalanceAllocationDecider
		rebalance并发控制
	DiskThresholdDecider
		根据磁盘空间进行决策分配
	RebalanceOnlyWhenActiveAllocationDecider
		所有shard都处在active状态下,才可以执行rebalance操作
	FilterAllocationDecider
		通过接口动态设置的过滤器
			index
				index.routing.allocation.require
				index.routing.allocation.include.
				index.routing.allocation.exclude.*
			cluster
				cluster.routing.allocation.require.*
				cluster.routing.allocation.include.*
				cluster.routing.allocation.exclude.*
		require必须的,include包含,exclude不包含
	ReplicaAfterPrimaryActiveAllocationDecider
		保证只有在主分片分配完,才能进行副分片分配
	ClusterRebalanceAllocationDecider
		通过集群中active的shard状态来决定是否可以执行rebalance

3.9 路由基础数据以及结构

allocation
	功能
		哪个分片应该分配给哪些节点
		哪个分片作为主分片,哪个作为副分片
	BalancedShardsAllocator
		PrimaryShardAllocator
			主分片分配
		ReplicaShardAllocator
			副分片分配
	GatewayAllocator
		组合使用上面的两个,实现真正分片路由
	AllocationService
		reroute
			真正路由的方法
	基础数据结构
		IndexRoutingTable
			索引路由表
		RoutingNode
			路由节点信息
		RoutingTable
			路由表信息
		ShardRouting
			分片路由信息
	路由算法
		shard = hash(routing) % number_of_primary_shards
			routing,默认就是docid
			主分片

第四章 写入机制

4.1 核心思想

先写入Lucene,再写入TransLog
为什么不先写日志?
	Lucene的内存写入会有很复杂的逻辑,很容易失败
	避免TransLog中有大量无效记录,减少recover的复杂度和提高速度

4.2 写特性

可靠性
	或者是持久性,数据写入系统成功后,数据不会被回滚或丢失
一致性
	数据写入成功后,再次查询时必须能保证读取到最新版本的数据,不能读取到旧数据
原子性
	一个写入或者更新操作,要么完全成功,要么完全失败,不允许出现中间状态
隔离性
	多个写入操作相互不影响
实时性
	写入后是否可以立即被查询到
性能
	写入性能,吞吐量

4.3 ClientNode

Ingest Pipeline
	对原始文档做一些处理,比如HTML解析,自定义的处理,具体处理逻辑可以通过插件来实现
Auto Create Index
	判断当前Index是否存在,如果不存在,则需要自动创建Index,这里需要和Master交互
Set Routing
	设置路由条件
		如果Request中指定了路由条件,则直接使用Request中的Routing
		否则使用Mapping中配置的,如果Mapping中无配置,则使用默认的_id字段值。
Construct BulkShardRequest
	同一个Shard中的请求聚集在一起,构建BulkShardRequest,每个BulkShardRequest对应一个Shard
 Send Request To Primary
	将每一个BulkShardRequest请求发送给相应Shard的Primary Node

4.4 PrimayNode

1 Index or Update or Delete
	循环执行每个Single Write Request,对于每个Request选择不同的逻辑来处理
2 Translate Update To Index or Delete
	Update操作的特有步骤
		会通过GetRequest查询到已经存在的同_id Doc
		(如果有)的完整字段和值(依赖_source字段),然后和请求中的Doc合并
		获取到读到的Doc版本号,记做V1。
 3 Parse Doc
	这里会解析Doc中各个字段。生成ParsedDocument对象,同时会生成uid Term
4 Update Mapping
	有个自动更新Mapping的功能,就在这一步生效
 Get Sequence Id and Version
	则会从SequenceNumber Service获取一个sequenceID和Version
	SequenceID在Shard级别每次递增1,SequenceID在写入Doc成功后,会用来初始化LocalCheckpoint
5 Add Doc To Lucene
	索引写入LUCENE,此时索引文件是保存在内存中,对查询不可见
6 Write Translog
	写完Lucene的Segment后,会以keyvalue的形式写TransLog,Key是_id,Value是Doc内容
	当查询的时候,如果请求是GetDocByID,则可以直接根据_id从TransLog中读取到,满足NoSQL场景下的实时性要去
7 Renew Bulk Request
	这里会重新构造Bulk Request,原因是前面已经将UpdateRequest翻译成了Index或Delete请求
	不需要再执行Update逻辑,一是保证Replica中逻辑更简单,性能更好,二是保证同一个请求在Primary和Replica中的执行结果一样
8 Flush Translog
	这里会根据TransLog的策略,选择不同的执行方式,要么是立即Flush到磁盘,要么是等到以后再Flush
	Flush的频率越高,可靠性越高,对写入性能影响越大
9 Send Requests To Replicas
	将刚才构造的新的Bulk Request并行发送给多个Replica,然后等待Replica的返回,等待多个Replica成功返回后,Primary Node才会返回用户
	具体需要多少Replica Node返回,可以通过配置或者请求参数设置
10 Receive Response From Replicas
	Replica中请求都处理完后,且满足最小Replica返回数后,会更新Primary Node的LocalCheckPoint

4.5 Replica Node

和Primary Node逻辑基本一致,缺少最后两步

4.6 核心类

1 ActionModule
	RestBulkAction
		TransportAction
			TransportShardBulkAction
			TransportReplicationAction
2 PrimaryOperationTransportHandler
3 ReplicaOperationTransportHandler

第五章 查询机制

5.1 概括

类型
	支持ES
	支持NOSQL数据库
形式
	1 Get
		通过ID查询特定Doc
			查询的时候是先查询内存中的TransLog,如果找到就立即返回
			如果没找到再查询磁盘上的TransLog
			如果还没有则再去查询磁盘上的Segment
	2 Search
		通过Query查询匹配Doc
			查询的时候是一起查询内存和磁盘上的Segment,最后将结果合并后返回
	保证NoSQL场景下的实时性要求。

5.2 阶段分类

1	query_and_fetch
		第一阶段查询到匹配的DocID
2	query_then_fetch
		第二阶段再查询DocID对应的完整文档
3	dfs_query_then_fetch
		先收集所有Shard中的TF和DF值,然后将这些值带入请求中
		再次执行query_then_fetch,这样算分的时候TF和DF就是准确的
	查询的优势是算分更加精准,但是效率会变差

5.3 实现机制

第一阶段的Query Phase请求,则会调用SearchService的executeQueryPhase方法
第二阶段的Fetch Phase请求,则会调用SearchService的executeFetchPhase方法 

5.4 Client Node

1 Get Remote Cluster Shard
	判断是否需要跨集群访问,如果需要,则获取到要访问的Shard列表。
2 Get Search Shard Iterator
	获取当前Cluster中要访问的Shard,勾出要访问完整的shard列表
3 For Every Shard:Perform
	遍历每个Shard,对每个Shard执行后面逻辑
4 Send Request To Query Shard
	将查询阶段请求发送给相应的Shard
5 Merge Docs
	异步等待返回结果,然后对结果合并
		维护一个Top N大小的优先级队列,每当收到一个shard的返回,就把结果放入优先级队列做一次排序,直到所有的6 Shard都返回。
	分页查询
		search_after
			返回的总数据量只是和Shard个数以及本次需要的个数有关,和历史已读取的个数无关
		深度分页
			通过scroll来实现
				本质类似于游标
				不能逆行查询,往返查询
					只能查询下一页
6 Send Request To Fetch Shard
	选出Top N个Doc ID后发送Fetch Shard给这些Doc ID所在的Shard,最后会返回Top N的Doc的内容

5.5 Query Phase

1 Create Search Context
	创建Search Context,之后Search过程中的所有中间状态都会存在Context中
 2 Parse Query
	解析Query的Source,将结果存入Search Context
3 Get From Cache
	判断请求是否允许被Cache,如果允许,则检查Cache中是否已经有结果
4 Add Collectors
	收集查询结果,实现排序,自定义结果集过滤和收集等
		FilteredCollector
			先判断请求中是否有Post Filter,Post Filter用于Search,Agg等结束后再次对结果做Filter,希望Filter不影响Agg结果。如果有Post Filter则创建一个FilteredCollector,加入Collector List中。
		PluginInMultiCollector
			判断请求中是否制定了自定义的一些Collector,如果有,则加入Collector List。
		MinimumScoreCollector
			:判断请求中是否制定了最小分数阈值,如果指定了,则创建MinimumScoreCollector加入Collector List中,在后续收集结果时,会过滤掉得分小于最小分数的Doc
		EarlyTerminatingCollector
			判断请求中是否提前结束Doc的Seek,如果是则创建EarlyTerminatingCollector,加入Collector List中。在后续Seek和收集Doc的过程中,当Seek的Doc数达到Early Terminating后会停止Seek后续倒排链
		CancellableCollector
			判断请求中是否提前结束Doc的Seek,如果是则创建EarlyTerminatingCollector,加入Collector List中。在后续Seek和收集Doc的过程中,当Seek的Doc数达到Early Terminating后会停止Seek后续倒排链
5 lucene::search
	调用Lucene中IndexSearch的search接口,执行真正的搜索逻辑
6 rescore
	根据Request中是否包含rescore配置决定是否进行二阶段排序,如果有则执行二阶段算分逻辑,会考虑更多的算分因子
7 suggest::execute()
	如果有推荐请求,则在这里执行推荐请求
8 aggregation::execute()
	如果含有聚合统计请求,则在这里执行

5.6 Fetch Phase

当Client Node选择出最终Top N的结果后,再对最终的Top N读取Doc内容
	ExplainFetchSubPhase
	DocValueFieldsFetchSubPhase
	ScriptFieldsFetchSubPhase
	FetchSourceSubPhase
	VersionFetchSubPhase
	MatchedQueriesFetchSubPhase
	HighlightPhase
	ParentFieldSubFetchPhase
	【通过插件的形式注册自定义的功能】

5.7 SearchPhase

AggregationPhase
	聚合查询
DfsPhase
	三阶段查询
FetchPhase
	二阶段查询
QueryPhase
	一阶段查询
RescorePhase
	二次加分查询
SuggestPhase
	推荐查询

第六章 性能优化

6.1 注意点总结

1 索引标记删除的标志,并不会立马被删除,而是在索引段合并的时候,才会真正删除标记删除的数据
2 集群角色:主节点,数据节点,预处理节点,协调节点,部落节点
3 bully算法,对节点id进行排序,取id值最大的节点作为master
4 副本分配恢复数据,允许从本地的translog进行回放恢复
5 master节点维护,同步副本列表 in-sync-copies
6 Primay Terms:由主节点分配给每个主分片,每次主分片发生变化的时候,进行递增
7 Sequence Numbers:主分片记录每个写操作的唯一标记
8 Global CK:全局检查点,避免进行全量数据对比,只对比有差异化的数据
9 不建议缓存第一次查询结果,等待翻页命中,而是重新检索一次
10 6.X版本用TslogDeletionPolicy,使用快照替代translog.view

6.2 常用API

_stats
	返回节点或者集群的状态信息
_tasks
	返回ES中在执行的任务
_cat/thread pool
	返回ES使用的各类线程
	线程种类:generic,index,search,get,bulk,snapshot,warmer,refresh,listener,same,management,flush,fetch_shard_started,fetch_shard_store
_nodes
	返回节点所有信息
	/hot_threads
		返回当前节点的热点线程
allocation/explain
	节点分片计划

6.3 写入速度优化

1 加大translog flush间隔
	降低iops,writeblock
2 加大index refresh间隔
	降低IO
3 调整bulk请求
4 优化磁盘间的任务均匀情况
5 优化节点间的任务分布
6 优化lucene层建立索引的整个过程
7 为文件系统cache预留足够多的内存

6.4 读取速度优化

1 为文件系统cache预留足够多的内存
3 使用更快的硬件
4 预索引数据
4 优化日期搜索
5 为只读索引执行force-merge
6 预热文件系统cache
7 转换查询表达式
8 调节搜索请求中的batch_reduce_size
	协调节点可以在指定分片数据返回,就先进行数据的聚合
9 利用自适应副本提升ES响应速度
	ARS算法
		节点未完成的搜索请求数,系统中数据节点的数量,响应时间,搜索线程池中队列中等待的任务数量,数据节点上的搜索服务时间等
10 适当的降低副本数量,避免多次跨网络查询

6.5 其它注意点

15 配置Linux OOM KIiller
	linux 会把进程占用多的内存给kill
		设置进程的oom_score_adj的值,越小越不容易被误杀
16 避免热索引分片不均
17 429状态码
	由于写入端的并发过大导致的,建议适当降低写入并发
18 了解你的搜索计划
	利用profile api分析会命中拿些分片
19 慢日志
	慢索引日志
	慢搜索日志

第七章 常用架构

7.1 冷热节点架构

Master节点
	负责处理集群的管理以及加强状态的整体稳定性
Hot节点
	完成集群内所有的索引工作
	保存近期的一些频繁被查询的索引
	服务器需要强大的SSD存储来支撑
Warm节点
	处理大量的而且不经常访问的只读索引而设计的
	索引是只读的,Warm节点倾向于挂载大量磁盘(普通磁盘)来替代SSD

7.2 日志统计架构

Elasticsearch
	存储日志数据,查询数据
Logstash
	对日志进行采集
Kiban
	对索引数据进行可视化图表展示
Filebeat
	对日志进行各种条件的过滤

你可能感兴趣的:(架构师技术大全)