ES分布式搜索,依赖了Lucene来提供搜索引擎功能,每个数据节点都是一个Lucene实例,通过将索引进行分片,写入和查询时候操作或查询对应分片,来达到水平扩展的能力

节点

Master node:负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点,分片分配等。 主节点并不需要涉及到文档级别的变更和搜索等操作。可以通过属性node.master进行设置。
Data node: 数据节点 增删改查、搜索、聚合
ES的master选举用的类bulk算法,没有用zk

shard

分片,位于Data Node节点,每个索引会有1到多个分片来水平拆分,将写入请求均分到不同的节点,提升TPS,查询时,也可以利用副本来提升查询效率
由于分片可能包含较多的数据,将全量的分片数据写入一个文件可能会使该文件较大,访问时耗时变长。同时为了利用缓存的使用,将分片切分为多个segment文件保存
当一个搜索请求达到分片时,会遍历所有的segment来搜索数据,segment过多会导致扫描效率降低,因此ES会将segment进行合并,减少segment数量

segment 分段

最小搜索单元,查询时,如果分片有多个segment,会遍历每一个segment来搜索数据

refresh

轻量级的写入和打开一个cache中的segment的操作叫做refresh,默认情况下,ES集群中的每个shard会每隔1秒自动refresh一次,将1秒内写入内存的新文档写入到文件系统缓存,并构成一个分段segment,这就是我们为什么说ES是近实时的搜索引擎而不是实时的,也就是说给索引插入一条数据后,我们需要等待1秒才能被搜到这条数据,这是es对写入和查询一个平衡的设置方式,这样设置既提升了es的索引写入效率同时也使得ES能够近实时检索数据
refresh并不会将segment落盘,也就是没有fsync操作,但translog 默认情况下落盘,用translog来保证数据不会直接丢失

为了保证数据不丢失,同时效率也较高,transLog 默认 index.translog.durability = request, 保证每次translog执行fsync,保证数据不丢失。这样,当节点挂断后,可以使用translog进行恢复

更新(Update)和删除(Delete)文档

ES文档不能更新,索引一定创建就不能修改,因此ES的update和delete操作,实际上步骤为:记录old doc被删除了,创建新doc

如何保证一致性

client -> 协调 node(版本5前) -> shard寻找主分片 -> real data node -> insert 并行将请求发送给副本分片 -> 响应成功
写入时,先将文档写入内存中,并写入translog中,此时文档还不能被索引

写一致

当集群中active shard 为集群大多数shard时,才能写入

put /index/type/id?consistency=quorum
consistency的值列表:

  • one:要求我们这个写操作,只要有一个primary shard是active活跃可用的,就可以执行
  • all:要求我们这个写操作,必须所有的primary shard和replica shard都是活跃的,才可以执行这个写操作
  • quorum:默认的值,要求所有的shard中,必须是大部分的shard都是活跃的,可用的,才可以执行这个写操作

one或all都太绝对化了,容错性/可用性太差,默认值为quorum,但仅当number_of_replicas时才生效
quorum 不齐全时,会wait直到timeout

replication=async | sync 异步同步

读一致性

默认情况下主备分片的数据是sync机制 当在主分片和副本分片的写操作都完成后,写操作才返回,这种情况下,任何分片的数据都是最新的
追求高索引吞吐率,即新增文档耗时尽量小时,可以考虑replication=async(异步)+ _preference = primary 的方案,这样搜索时直接查询主分片,当然,系统稳定性也降低了,异步机制也将产生数据一致性风险,一旦primary挂掉,则replica可能会丢失部分数据

通常情况可以让primary shard负责写,replica shard负责读,来实现读写分离
primary shard不能和自己的replica shard 放在一个节点中,因为这样无法容灾,如果持有主分片的节点挂掉了,一个副本分片就会晋升为主分片的角色。

查询的第一步是广播请求到索引分片。
查询请求到达协调节点后,第一步是广播请求到所有分片,广播给主分片或副本分片,同时保证同一个分片,要么广播给主分片,要么给副本分片之一,不会重复通知,协调节点将在之后的请求中轮询所有的分片或拷贝来分摊负载。
每个分片将会在本地构建一个优先级队列。如果客户端要求返回结果排序中从第from名开始的数量为size的结果集,则每个节点都需要生成一个from+size大小的结果集,因此优先级队列的大小也是from+size。分片仅会返回一个轻量级的结果给协调节点,包含结果集中的每一个文档的ID和进行排序所需要的信息。

横向扩展

  • 加机器,将导致集群分区重分配,如原本只有两台机器单机3分片,共6个分片,现在加了1台机器,集群将会重新平衡,每台机器上各2个分片
  • 数据的冗余越多,我们能处理的搜索吞吐量就越大
  • 在同样数量的节点上增加更多的复制分片并不能提高性能,因为这样做的话平均每个分片的所占有的硬件资源就减少了

重建索引

如果你想修改分析器或修改已有字段,可以通过重建索引来完成。通过scan-scroll api,读取_source,放入新的索引中即可,同时可以使用条件过滤来并行执行

GET /old_index/_search?search_type=scan&scroll=1m
{
	"query": {
		"range": {
			"date": {
				"gte":  "2014-01-01",
				"lt":   "2014-02-01"
			}
		}
	},
	"size":  1000
}

假如你继续在旧索引上做修改,你可能想确保新增的文档被加到了新的索引中。这可以通过重新运行重建索引程序来完成,但是记得只要过滤出上次执行后新增的文档就行了。

参考文档:

https://es.xiaoleilu.com/020_Distributed_Cluster/20_Add_failover.html

https://www.jianshu.com/p/61dd9fb7d785

https://blog.csdn.net/zkyfcx/article/details/79998197

posted on 2019-07-10 17:22  j.liu windliu  阅读(218)  评论(0编辑  收藏  举报