一、基本概念 elasitcsearch是一个分布式搜索引擎,底层实现是基于Lucene的,核心思想是在多台服务器上启动多个es进程实例组成一个es集群,基本概念如下: 1、接近实时的(NRT):ES是一个接近实时的搜索平台,这意味着,从索引一个文档直到文档能够被搜索到,只有轻微的延迟。 2、集群(cluster):一个集群有多个节点(服务器或实例进程)组成,通过索引的节点一起保存全部数据并且通过联合索引和搜索功能的节点的集合,每个集群有一个唯一的名称标识。 3、节点(node):一个节点就是一台服务器或一个进程实例,是你集群的一部分,存储数据,并且参与集群和搜索功能,一个节点可以通过配置特点的名称来加入特定的集群。 4、索引(index):一个索引就是有某些共有特性的文档的集合,一个索引被一个名称唯一标识,并且这个名称被用于索引通过文档去执行搜索、更新和删除等操作。 5、类型(type):type在6.0后逐渐被抛弃了。 6、文档(document):一个文档就是一个基本的搜索单元。
总结:ES中存储数据的基本单位就是索引,比如说存储一些订单系统的销售数据,就因此在ES中创建一个索引,order=index。所有的销售数据就会都写到这个索引里去,一个索引就像一个数据库,二type就相当于表。一个索引可以有多个type。而mapping就相当于表的结构。往index的一个type里添加一行数据就叫做document,每个document有多个field,每一个field就代表这个document的一个字段值。 7、分片(shards):单台机器无法存储大量数据,为解决这个问题,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个shard都是一个lucene index。 8、副本(replica):任何一个服务器随时可能故障或宕机,此时shard可能就会丢失,因此可以为每个shard创建多个replica副本。replica可以在shard故障时提供备用服务,保证数据不丢失,多个replica还可以提升搜索操作的吞吐量和性能。primary shard(建立索引时一次设置,不能修改,默认5个),replica shard(随时修改数量,默认1个),默认每个索引10个shard,5个primary shard,5个replica shard,最小的高可用配置,是2台服务器。副本两个主要原因: (1)、高可用。它提供了高可用来防止分片或者节点宕机,主分片和副本分片绝对不能再同一台服务器上。 (2)、高并发。允许你的分片提供超出自身吞吐量的搜索服务。搜索行为可以在所有主分片和副本中并行执行。
总之,一个完整的流程就是,ES客户端将一份数据写入primary shards,主分片写入完成后会将所有的文档拷贝到副本分片中。客户端在读取数据时,会从主分片primary shard和副本分片replica shard中去读。 ES有多个节点,会自动选举一个节点为master节点,master节点其实就是干一些管理类的工作,比如为何元数据,负责切换primary shard和replica shard的身份之类。要是master节点宕机,集群就会选举下一个节点为master节点。如果是非master节点宕机了,那么master节点,就会让那个宕机节点上的primary shard的转移到replica shard上,如果修复了那台宕机的服务器,重启后,master节点就会控制将缺失的replica shard分配过去然后同步分片,让整个集群恢复正常。
二、写入数据的过程 2.1、简单流程:
- 客户端选择一个node发送请求过去,这个node就是coordinating node (协调节点)
- coordinating node,对document进行路由,将请求转发给对应的node
- 实际上的node上的primary shard处理请求,然后将数据同步到replica node
- coordinating node,如果发现primary node和所有的replica node都搞定之后,就会返回请求到客户端
备注:这个路由简单的说就是取模算法,比如说现在有3台服务器,这个时候传过来的id是5,那么5%3=2,就放在第3台服务器
2.2、写入数据的底层原理:
- 数据文档会先写入到buffer里面,在buffer里面的数据是搜索不到的,同时也会将数据写入到translog日志文件之中
- 如果buffer快满了,或是一段时间之后(定时),就会将buffer数据refresh到一个新的OS cache之中,然后每隔1秒,就会将OS cache的数据写入到segment file之中,但是如果每一秒钟没有新的数据到buffer之中,就会创建一个新的空的segment file,只要buffer中的数据被refresh到OS cache之中,就代表这个数据可以被搜索到了。当然可以通过restful api 和Java api,手动的执行一次refresh操作,就是手动的将buffer中的数据刷入到OS cache之中,让数据立马搜索到,只要数据被输入到OS cache之中,buffer的内容就会被清空了。同时进行的是,数据到shard之后,就会将数据写入到translog之中,每隔5秒将translog之中的数据持久化到磁盘之中
- 重复以上的操作,每次一条数据写入buffer,同时会写入一条日志到translog日志文件之中去,这个translog文件会不断的变大,当达到一定的程度之后,就会触发commit操作。
- 将一个commit point写入到磁盘文件,里面标识着这个commit point 对应的所有segment file
- 强行将OS cache 之中的数据都fsync到磁盘文件中去。 解释:translog的作用:在执行commit之前,所有的而数据都是停留在buffer或OS cache之中,无论buffer或OS cache都是内存,一旦这台机器死了,内存的数据就会丢失,所以需要将数据对应的操作写入一个专门的日志问价之中,一旦机器出现宕机,再次重启的时候,es会主动的读取translog之中的日志文件的数据,恢复到内存buffer和OS cache之中。
- 将现有的translog文件进行清空,然后在重新启动一个translog,此时commit就算是成功了,默认的是每隔30分钟进行一次commit,但是如果translog的文件过大,也会触发commit,整个commit过程就叫做一个flush操作,我们也可以通过ES API,手动执行flush操作,手动将OS cache 的数据fsync到磁盘上面去,记录一个commit point,清空translog文件 补充:其实translog的数据也是先写入到OS cache之中的,默认每隔5秒之中将数据刷新到硬盘中去,也就是说,可能有5秒的数据仅仅停留在buffer或者translog文件的OS cache中,如果此时机器挂了,会丢失5秒的数据,但是这样的性能比较好,我们也可以将每次的操作都必须是直接fsync到磁盘,但是性能会比较差。
- 如果时删除操作,commit的时候会产生一个.del文件,里面讲某个doc标记为delete状态,那么搜索的时候,会根据.del文件的状态,就知道那个文件被删除了。
- 如果时更新操作,就是讲原来的doc标识为delete状态,然后重新写入一条数据即可。
- buffer每次更新一次,就会产生一个segment file 文件,所以在默认情况之下,就会产生很多的segment file 文件,将会定期执行merge操作
- 每次merge的时候,就会将多个segment file 文件进行合并为一个,同时将标记为delete的文件进行删除,然后将新的segment file 文件写入到磁盘,这里会写一个commit point,标识所有的新的segment file,然后打开新的segment file供搜索使用。
三、ES查询过程 3.1、查询过程 1、客户端发送一个请求给coodinate node. 2、协调节点将搜索的请求转发给所有的shard分片对应的主分片或副本分片。 3、query phase:被选中的shard将自己的搜索结果(就是唯一标识)返回给协调节点,由协调节点进行数据的合并、排序、分页等操作。 4、fetch phase:接下来由协调节点,根据唯一标识也就是搜索结果去各个节点上进行拉取数据,然后返回给客户端。
3.2、查询的原理 查询大体上分为两个节点:query和fetch两个阶段,广播查询请求到所有的相关分片,并将他们的响应整合成全局排序后的结果结合,并把这个结果集合返回给客户端。
1、query阶段
1.当一个节点接收到一个搜索请求,这这个节点就会变成协调节点,第一步就是将广播请求到搜索的每一个节点的分片拷贝,查询请求可以被某一个主分片或某一个副分片处理,协调节点将在之后的请求中轮训所有的分片来分摊负载。
2.每一个分片将会在本地构建一个优先级队列,如果客户端要求返回结果排序中从from 名开始的数量为size的结果集,每一个节点都会产生一个from+size大小的结果集,因此优先级队列的大小也就是from+size,分片仅仅是返回一个轻量级的结果给协调节点,包括结果级中的每一个文档的ID和进行排序所需要的信息。
3.协调节点将会将所有的结果进行汇总,并进行全局排序,汇总得到排序结果。
2、取值阶段
1.查询过程得到的排序结果,标记处哪些文档是符合要求的,此时仍然需要获取这些文档返回给客户端
2.协调节点会确定实际需要的返回的文档,并向含有该文档的分片发送get请求,分片获取的文档返回给协调节点,协调节点将结果返回给客户端
四、更新过程 4.1、document的全量替换
1.这个就是用新的数据全部覆盖以前的数据
2.重新创建一个document并把原来的标记为delete
3.partial update, 就是制定需要更新的字段.
备注:全量更新是把数据找出来,然后在java代码中进行修改,然后在放进去 partial部分是直接提交需要修改的字段然后直接修改,在一个shard中进行,内部也是全量替换. 4.2、强制创建 就是不管原来的数据,直接强制创建一个新的。 4.3、删除过程 当要进行删除document的时候,只是把它标记为delete,当数据到达一定的时候再进行删除, 有点像JVM中标记清除法