es不需要集成第三方服务就可以完成分布式特性。
1) ES支持集群模式,是一个分布式系统,其好处主要有两个:
2)ES集群由多个es实例组成
运行如下命令可以快速启动一个es节点的实例,集群是通过集群名来保证节点是属于哪一个集群的。改变下面的node.name,path.data,http.port就可以在一台机器启动多个节点。
bin/elasticsearch
-Ecluster.name=my_cluster -Epath.data=my_cluster_node1 -Enode.name=node1
-Ehttp.port=5100 -d
# -d 表示以后台进程的方式运行
es 集群相关的数据称为 cluster state,主要记录如下信息:
如下图中,实心的五角心就是master节点,空心的就其他节点。
处理请求的节点称为coordinating节点,该节点为所有节点的默认角色,不能取消;路由请求到正确的节点处理,比如创建索引的请求到master节点。
存储数据的节点称为 data节点,默认节点都是data类型,相关配置:node.data: true
如果集群只有一个节点停止服务,该节点停止,集群就停止服务。但是如果集群有多个节点,一个节点挂了;会重新生成新的master节点。
分片就是把一条数据切分成几片,所以分片可以提供扩容,但并不是分的越多越好,要看具体情况分片。
如何将数据分布到所有节点上?
引入分片(Shard)解决问题
分片是ES支持PB级数据的基石,特点:
- 分片存储了部分数据,可以分布于任意节点上
- **分片数在索引创建时指定且后续不允许再更改,默认为5个**
- 分片有主分片和副本分片之分,以实现数据的高可用
- 副本分片的数据由主分片同步,可以有多个,从而提高读取的吞吐量
归纳:一个索引分片建立好了就不能更改,但是后期可以增加节点,增加节点没有办法提高已经建立好索引数据容量(分片已经定了),不过可以提高该索引的吞吐量。
如下红色圈表示的,实线表示主分片,虚线表示副分片;一一对应;如下建了book,index_01连个索引;book索引是5个shards分片(分成2份),一个replica副本,所以一共十个分片;index_01有3个shards分片(三份),一个replica副本,所以一共6个分片;
问题解决:
分片数的设定非常重要,需要提前规划好
通过如下api可以查看集群健康状况,包括以下三种:
三种状态只是代表分片的工作状态,并不是代表整个es集群是否能够对外提供服务
Rest api获取状态:GET _cluster/health
脑裂问题,英文为split-brain,是分布式系统中的经典网络问题,如下图所示:
- node2与node3会重新选举master,比如node2成为了新master,此时会更新cluster state
- node1自己组成集群后,也会更新cluster state
- 同一个集群有两个master,而维护不同的cluster state,网络恢复后无法选择正确的master
解决方案:
解决方案为仅在可选举master-eligible节点数据大于等于quorum时才可以进行master选举
quorum = master-eligible 节点数/2 + 1,例如 3个master-eligible节点时,quorum为2。
解决:设置config/elasticsearch.yml参数配置 discovery.zen.mininum_master_nodes为quorum即可避免脑裂
doc1 是如何存储到分片P1的呢?选择P1的依据是什么呢?
需要文档到分片的映射算法
目的:
使得文档均匀分布在所有分片上,以充分利用资源
算法:
随机选择或者round-robin算法
不可取:因为维护文档到分片的映射关系,成本巨大
如上倒排索引不能更改,如果重新再替换实时性受到影响。所以新文档直接生成新的倒排索引文件,查询的时候同时查询所有的倒排文件,然后对查询结果做汇总计算即可。
- Lucene采用了这种方案,它构建的单个倒排索引称为segment,合在一起称为Index(Lucene中的名称),
- 与ES中的Index概念不同,ES中的一个Shard对应一个Lucene Index。
- Lucene会有一个专门的文件来记录所有的segment信息,称为 Commit Point
refresh发生的时机主要有以下几种情况:
- 间隔时间达到时,通过index.settings.refresh_interval来设定,默认是1秒
- index.buffer占满时,其大小通过indices.memory.index_buffer_size设置, 默认为jvm heap的10%
- flush发生时也会发生refresh
flush发生的时机主要有以下几种情况:
- 间隔时间达到时,默认是30分钟,5.x之前可以通index.translog.flush_threshold_period修改;之后发布的版本无法设置
- translog占满时,其大小可以通过index.translog.flush_threshold_size控制,默认是512MB;每个index有自己的translog
随着segment的增多,由于一次查询的segment数增多,查询速度会变慢
es会定时在后台进行segment merge的操作,减少segment的 数量
通过force_merge api可以手动强制做segment merge的操作
Search执行的时候实际分两个步骤运行的 Query阶段,Fetch阶段
node3根据Query阶段获取到文档Id列表对应的shard上获取文档详情数据
例子:
你通过关键字“hello”查询,含有这个字母的文档;如果有多个分片,返回结果的排序也许并不是按照你想要的排序结果排序,因为不同分片在Query阶段对于这个hello会生成不同的评分值,然后按照评分制排序。
评分因素:
1)text类型 单词出现频率越高 评分越高
2)匹配度完整度越高评分越高
记住几点:
解决index的扩容问题使用ES的:reindenx;即重新创建一个index, 再把原来数据导入到新的index,然后删掉老的index,ES内部提供方案解决。