学习目标 倒排索引是不变的优缺点 Elasticsearch持久化 Elasticsearch如何选择master Elasticsearch索引的过程 Elasticsearch搜索的过程 Elasticsearch更新/删除的过程 Elasticsearch是如何避免脑裂现象 游标查询scroll技术
倒排索引是不变的优缺点
代码语言:javascript复制优点:
1、不能修改就不用考虑多个进程同时修改的问题,不会加锁
2、不变性,导致从磁盘加载到内存中可以一直保留着,不用变化,提交查询性能
缺点:
1、不变性,导致要更新一个文档就要重建整个倒排索引,性能很差
es使用更多的索引来处理,理解将一个大的索引分成多个小的索引,
重建的时候就可以更快性能更高,段本身就是一个倒排索引
Elasticsearch持久化
代码语言:javascript复制https://blog.csdn.net/u010454030/article/details/79617468
Elasticsearch如何选择master
代码语言:javascript复制()Elasticsearch的选主是ZenDiscovery模块负责的,主要包含Ping(节点之间通过这个RPC来
发现彼此)和Unicast(单播模块包含一个主机列表以控制哪些节点需要ping通)这两部分;
(2)对所有可以成为master的节点(node.master: true)根据nodeId字典排序,
每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,
暂且认为它是master节点。
(3)如果对某个节点的投票数达到一定的值(可以成为master节点数n/2 1)并且该节点自己也选举自己,
那这个节点就是master。否则重新选举一直到满足上述条件。
Elasticsearch索引的过程
代码语言:javascript复制()协调节点默认使用文档ID参与计算(也支持通过routing),以便为路由提供合适的分片。
shard = hash(document_id) % (num_of_primary_shards)
(2)当分片所在的节点接收到来自协调节点的请求后,会将请求写入到Memory Buffer,然后定时(默认是每隔1秒)
写入到Filesystem Cache,这个从Momery Buffer到Filesystem Cache的过程就叫做refresh;
(3)当然在某些情况下,存在Momery Buffer和Filesystem Cache的数据可能会丢失,
ES是通过translog的机制来保证数据的可靠性的。其实现机制是接收到请求后,
同时也会写入到translog中,当Filesystem cache中的数据写入到磁盘中时,才会清除掉,这个过程叫做flush。
(4)在flush过程中,内存中的缓冲将被清除,内容被写入一个新段,段的fsync将创建一个新的提交点,
并将内容刷新到磁盘,旧的translog将被删除并开始一个新的translog。
flush触发的时机是定时触发(默认30分钟)或者translog变得太大(默认为512M)时。
Elasticsearch搜索的过程
代码语言:javascript复制一、在主分片或副本取回一个document(/index/type/id)
1)客户端发送请求到任意一个节点(协调节点),节点使用id计算属于哪个分片,并将请求转发给主分片或副本分片。
2)分片节点加载对应得document返回给协调节点。协调节点返回给客户端
读请求,为了平衡负载,请求节点会为每个请求选择不同的分片——它会循环所有分片副本
一个被索引的文档已经存在于主分片上却还没来得及同步到复制分片上。这时复制分片会报告文档未找到,主分片会成功返回文档。
二、分布式搜索
Elasticsearch搜索分为两个阶段: 查询阶段,取回阶段。
查询阶段:
1)当客户端向一个节点(协调节点)发起搜索请求(size=10,from=90),请求节点,建立一个优先队列(from size=100长度)
2)协调节点将请求转发给,所有的主分片(或者对应得副本)所在的节点。每个分片节点,在本地建立一个优先队
列(from size长度),然后在本地查询排序放在优先队列中
3)每个分片将查询的document id和排序的值返回给协调节点,协调节点将这些数据排序放在自己的优先队列中(第一步创建的空队列)。
查询阶段结束。
取回阶段:
在查询阶段我们辨别出那些满足搜索请求的document,但是还要取回document本身。
1)协调节点,辨别出那些是实际要取回的document(size=10,from=90,只取前10条),并且向相关分片发出GET请求。
2)每个分片节点加载document,并返回给协调节点
3)一旦所有的document都被取回,协调节点会将结果返回给客户端。
Elasticsearch更新/删除的过程
代码语言:javascript复制q
Elasticsearch是如何避免脑裂现象
代码语言:javascript复制q
游标查询scroll技术
代码语言:javascript复制scroll 查询 可以用来对 Elasticsearch 有效地执行大批量的文档查询,
而又不用付出深度分页那种代价。
ES的搜索是分2个阶段进行的,即Query阶段和Fetch阶段。
Query阶段比较轻量级,通过查询倒排索引,获取满足查询结果的文档ID列表。
而Fetch阶段比较重,需要将每个shard的结果取回,在协调结点进行全局排序。
通过From size这种方式分批获取数据的时候,随着from加大,
需要全局排序并丢弃的结果数量随之上升,性能越来越差。
而Scroll查询,先做轻量级的Query阶段以后,免去了繁重的全局排序过程。 它只是将查询结果集,
也就是doc id列表保留在一个上下文里, 之后每次分批取回的时候,
只需根据设置的size,在每个shard内部按照一定顺序(默认doc_id续),
取回这个size数量的文档即可。
由此也可以看出scroll不适合支持那种实时的和用户交互的前端分页工作,
其主要用途用于从ES集群分批拉取大量结果集的情况,一般都是offline的应用场景。
比如需要将非常大的结果集拉取出来,存放到其他系统处理,或者需要做大索引的reindex等等。
GET /old_index/_search?scroll=1m
{
"query": { "match_all": {}},
"sort" : ["_doc"],
"size": 100
}
scroll=1m 保持上下文为一分钟,一分钟内要处理完当前批。在再次查询的时候会报错
GET /_search/scroll
{
"scroll": "1m",
"scroll_id" : "xxxxxxxxxxxxxxxxxxxxx"
}
注意 scroll在查询过程中,当我们更新了数据,是没有用了,返回给用户还是旧了数据。 再次设置游标查询过期时间为一分钟。这个游标查询返回的下一批结果。 尽管我们指定字段 size 的值为1000,我们有可能取到超过这个值数量的文档。 当查询的时候, 字段 size 作用于单个分片,所以每个批次实际返回的文档数量最大为 size * number_of_primary_shards 。