前言

文本已收录至我的GitHub仓库,欢送Star:https://github.com/bin3923282...
种一棵树最好的工夫是十年前,其次是当初

Tips

面试指南系列,很多状况下不会去深挖细节,是小六六以被面试者的角色去回顾常识的一种形式,所以我默认大部分的货色,作为面试官的你,必定是懂的。

https://www.processon.com/vie...

下面的是脑图地址

叨絮

明天来看看Elasticsearch
而后上面是后面的文章汇总

  • 2021-Java后端工程师面试指南-(引言)
  • 2021-Java后端工程师面试指南-(Java根底篇)
  • 2021-Java后端工程师面试指南-(并发-多线程)
  • 2021-Java后端工程师面试指南-(JVM)
  • 2021-Java后端工程师面试指南-(MySQL)
  • 2021-Java后端工程师面试指南-(Redis)

Es其实用的很多,而且如果体量大点的话,基本上都须要应用到它,所以把握它还是很有必要的,那么咱们来一起看看吧

### 说说什么是Elasticsearch

  • Elasticsearch,基于lucene.分布式的Restful实时搜寻和剖析引擎(实时)
  • 分布式的实时文件存储,每个字段都被索引并可被搜寻
  • 高扩展性,可扩大至上百台服务器,解决PB级结构化或非结构化数据
  • Elasticsearch用于全文检索,结构化搜寻,剖析/合并应用

聊聊Elasticsearch的个性:

  • Elasticsearch没有典型意义的事务(无事务性)
  • Elasticsearch是一种面向文档的数据库
  • Elasticsearch没有提供受权和认证个性

什么是全文检索和Lucene?

全文检索,倒排索引

全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建设一个索引,指明该词在文章中呈现的次数和地位,当用户查问时,检索程序就依据当时建设的索引进行查找,并将查找的后果反馈给用户的检索形式。这个过程相似于通过字典中的检索字表查字的过程。全文搜寻搜索引擎数据库中的数据。

lucene
lucene,就是一个jar包,外面蕴含了封装好的各种建设倒排索引,以及进行搜寻的代码,包含各种算法。咱们就用java开发的时候,引入lucene jar,而后基于lucene的api进行去进行开发就能够了。

那你聊聊Elasticsearch的外围概念,就是咱们常常用的那些。

近实时
近实时,两个意思,从写入数据到数据能够被搜寻到有一个小提早(大略1秒);基于es执行搜寻和剖析能够达到秒级。

Cluster(集群)
集群蕴含多个节点,每个节点属于哪个集群是通过一个配置(集群名称,默认是elasticsearch)来决定的,对于中小型利用来说,刚开始一个集群就一个节点很失常

Node(节点)

集群中的一个节点,节点也有一个名称(默认是随机调配的),节点名称很重要(在执行运维治理操作的时候),默认节点会去退出一个名称为“elasticsearch”的集群,如果间接启动一堆节点,那么它们会主动组成一个elasticsearch集群,当然一个节点也能够组成一个elasticsearch集群。

Index(索引-数据库)
索引蕴含一堆有类似构造的文档数据,比方能够有一个客户索引,商品分类索引,订单索引,索引有一个名称。一个index蕴含很多document,一个index就代表了一类相似的或者雷同的document。比如说建设一个product index,商品索引,外面可能就寄存了所有的商品数据,所有的商品document。
Type(类型-表)
每个索引里都能够有一个或多个type,type是index中的一个逻辑数据分类,一个type下的document,都有雷同的field,比方博客零碎,有一个索引,能够定义用户数据type,博客数据type,评论数据type。

Document(文档-行)
文档是es中的最小数据单元,一个document能够是一条客户数据,一条商品分类数据,一条订单数据,通常用JSON数据结构示意,每个index下的type中,都能够去存储多个document。

Field(字段-列)
Field是Elasticsearch的最小单位。一个document外面有多个field,每个field就是一个数据字段。

shard
单台机器无奈存储大量数据,es能够将一个索引中的数据切分为多个shard,散布在多台服务器上存储。有了shard就能够横向扩大,存储更多数据,让搜寻和剖析等操作散布到多台服务器下来执行,晋升吞吐量和性能。每个shard都是一个lucene index。

replica
任何一个服务器随时可能故障或宕机,此时shard可能就会失落,因而能够为每个shard创立多个replica正本。replica能够在shard故障时提供备用服务,保证数据不失落,多个replica还能够晋升搜寻操作的吞吐量和性能。primary shard(建设索引时一次设置,不能批改,默认5个),replica shard(随时批改数量,默认1个),默认每个索引10个shard,5个primary shard,5个replica shard,最小的高可用配置,是2台服务器。

说说Elasticsearch乐观并发管制

Elasticsearch是分布式的。当文档被创立、更新或删除,文档的新版本会被复制到集群的其它节点。Elasticsearch即是同步的又是异步的,意思是这些复制申请都是平行发送的,并无序(out of sequence)的达到目的地。这就须要一种办法确保老版本的文档永远不会笼罩新的版本。
上文咱们提到index、get、delete申请时,咱们指出每个文档都有一个_version号码,这个号码在文档被扭转时加一。Elasticsearch应用这个_version保障所有批改都被正确排序。当一个旧版本呈现在新版本之后,它会被简略的疏忽。
咱们利用_version的这一长处确保数据不会因为批改抵触而失落。咱们能够指定文档的version来做想要的更改。如果那个版本号不是当初的,咱们的申请就失败了。
用version 来保障并发的程序一致性

聊聊text,keyword类型的区别

  • text:当一个字段是要被全文搜寻的,比方Email内容、产品描述,应该应用text类型。设置text类型当前,字段内容会被剖析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text类型的字段不用于排序,很少用于聚合。
  • keyword:keyword类型实用于索引结构化的字段,比方email地址、主机名、状态码和标签。如果字段须要进行过滤(比方查找已公布博客中status属性为published的文章)、排序、聚合。keyword类型的字段只能通过准确值搜寻到。

那你说说查问api返回的次要蕴含什么货色

hits
响应中最重要的局部是hits,它蕴含了total字段来示意匹配到的文档总数,hits数组还蕴含了匹配到的前10条数据。
hits数组中的每个后果都蕴含_index、_type和文档的_id字段,被退出到_source字段中这意味着在搜寻后果中咱们将能够间接应用全副文档。这不像其余搜索引擎只返回文档ID,须要你独自去获取文档。
每个节点都有一个_score字段,这是相关性得分(relevance score),它掂量了文档与查问的匹配水平。默认的,返回的后果中关联性最大的文档排在首位;这意味着,它是依照_score降序排列的。这种状况下,咱们没有指定任何查问,所以所有文档的相关性是一样的,因而所有后果的_score都是获得一个两头值1
max_score指的是所有文档匹配查问中_score的最大值。

took
took通知咱们整个搜寻申请破费的毫秒数。

shards
_shards节点通知咱们参加查问的分片数(total字段),有多少是胜利的(successful字段),有多少的是失败的(failed字段)。通常咱们不心愿分片失败,不过这个有可能产生。如果咱们蒙受一些重大的故障导致主分片和复制分片都故障,那这个分片的数据将无奈响应给搜寻申请。这种状况下,Elasticsearch将报告分片failed,但仍将持续返回残余分片上的后果。

timeout

time_out值通知咱们查问超时与否。个别的,搜寻申请不会超时。如果响应速度比残缺的后果更重要,你能够定义timeout参数为10或者10ms(10毫秒),或者1s(1秒)

聊聊shard&replica机制

  • index蕴含多个shard
  • 每个shard都是一个最小工作单元,承载局部数据,lucene实例,残缺的建设索引和解决申请的能力
  • 增减节点时,shard会主动在nodes中负载平衡
  • primary shard和replica shard,每个document必定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard
  • replica shard是primary shard的正本,负责容错,以及承当读申请负载
  • primary shard的数量在创立索引的时候就固定了,replica shard的数量能够随时批改
  • primary shard的默认数量是5,replica默认是1,默认有10个shard,5个primary shard,5个replica shard
  • primary shard不能和本人的replica shard放在同一个节点上(否则节点宕机,primary shard和正本都失落,起不到容错的作用),然而能够和其余primary shard的replica shard放在同一个节点上

ES是如何实现master选举的?

前置条件:

  • 只有是候选主节点(master:true)的节点能力成为主节点。
  • 最小主节点数(min_master_nodes)的目标是避免脑裂。

Elasticsearch 的选主是 ZenDiscovery 模块负责的,次要蕴含 Ping(节点之间通过这个RPC来发现彼此)和 Unicast(单播模块蕴含一个主机列表以管制哪些节点须要 ping 通)这两局部;
获取主节点的外围入口为 findMaster,抉择主节点胜利返回对应 Master,否则返回 null。

选举流程大抵形容如下:

  • 第一步:确认候选主节点数达标,elasticsearch.yml 设置的值 discovery.zen.minimum_master_nodes;
  • 第二步:对所有候选主节点依据nodeId字典排序,每次选举每个节点都把本人所晓得节点排一秩序,而后选出第一个(第0位)节点,暂且认为它是master节点。
  • 第三步:如果对某个节点的投票数达到肯定的值(候选主节点数n/2+1)并且该节点本人也选举本人,那这个节点就是master。否则从新选举始终到满足上述条件。

如何解决ES集群的脑裂问题

所谓集群脑裂,是指 Elasticsearch 集群中的节点(比方共 20 个),其中的 10 个选了一个 master,另外 10 个选了另一个 master 的状况。

当集群 master 候选数量不小于 3 个时,能够通过设置起码投票通过数量(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
当候选数量为两个时,只能批改为惟一的一个 master 候选,其余作为 data 节点,防止脑裂问题。

聊聊es的写入流程

Elasticsearch采纳多Shard形式,通过配置routing规定将数据分成多个数据子集,每个数据子集提供独立的索引和搜寻性能。当写入文档的时候,依据routing规定,将文档发送给特定Shard中建设索引。这样就能实现分布式了。

每个Index由多个Shard组成(默认是5个),每个Shard有一个主节点和多个正本节点,正本个数可配。但每次写入的时候,写入申请会先依据_routing规定抉择发给哪个Shard,Index Request中能够设置应用哪个Filed的值作为路由参数,如果没有设置,则应用Mapping中的配置,如果mapping中也没有配置,则应用_id作为路由参数,而后通过_routing的Hash值抉择出Shard(在OperationRouting类中),最初从集群的Meta中找出出该Shard的Primary节点。

申请接着会发送给Primary Shard,在Primary Shard上执行胜利后,再从Primary Shard上将申请同时发送给多个Replica Shard,申请在多个Replica Shard上执行胜利并返回给Primary Shard后,写入申请执行胜利,返回后果给客户端。

那你说说具体在 shard上的写入流程呗

在每一个Shard中,写入流程分为两局部,先写入Lucene,再写入TransLog。

写入申请达到Shard后,先写Lucene文件,创立好索引,此时索引还在内存外面,接着去写TransLog,写完TransLog后,刷新TransLog数据到磁盘上,写磁盘胜利后,申请返回给用户。这里有几个关键点:

和数据库不同,数据库是先写CommitLog,而后再写内存,而Elasticsearch是先写内存,最初才写TransLog,一种可能的起因是Lucene的内存写入会有很简单的逻辑,很容易失败,比方分词,字段长度超过限度等,比拟重,为了防止TransLog中有大量有效记录,缩小recover的复杂度和进步速度,所以就把写Lucene放在了最后面。

写Lucene内存后,并不是可被搜寻的,须要通过Refresh把内存的对象转成残缺的Segment后,而后再次reopen后能力被搜寻,个别这个工夫设置为1秒钟,导致写入Elasticsearch的文档,最快要1秒钟才可被从搜寻到,所以Elasticsearch在搜寻方面是NRT(Near Real Time)近实时的零碎。

每隔一段比拟长的工夫,比方30分钟后,Lucene会把内存中生成的新Segment刷新到磁盘上,刷新后索引文件曾经长久化了,历史的TransLog就没用了,会清空掉旧的TransLog。

Lucene缓存中的数据默认1秒之后才生成segment文件,即便是生成了segment文件,这个segment是写到页面缓存中的,并不是实时的写到磁盘,只有达到肯定工夫或者达到肯定的量才会强制flush磁盘。如果这期间机器宕掉,内存中的数据就丢了。如果产生这种状况,内存中的数据是能够从TransLog中进行复原的,TransLog默认是每5秒都会刷新一次磁盘。但这仍然不能保障数据安全,因为依然有可能最多失落TransLog中5秒的数据。这里能够通过配置减少TransLog刷磁盘的频率来减少数据可靠性,最小可配置100ms,但不倡议这么做,因为这会对性能有十分大的影响。个别状况下,Elasticsearch是通过正本机制来解决这一问题的。即便主分片所在节点宕机,失落了5秒数据,仍然是能够通过副原本进行复原的。

总结一下,数据先写入内存 buffer,而后每隔 1s,将数据 refresh 到 os cache,到了 os cache 数据就能被搜寻到(所以咱们才说 es 从写入到能被搜寻到,两头有 1s 的提早)。每隔 5s,将数据写入 translog 文件(这样如果机器宕机,内存数据全没,最多会有 5s 的数据失落),translog 大到肯定水平,或者默认每隔 30mins,会触发 commit 操作,将缓冲区的数据都 flush 到 segment file 磁盘文件中。

说说es的更新流程吧

Lucene中不反对局部字段的Update,所以须要在Elasticsearch中实现该性能,具体流程如下:

  • 到Update申请后,从Segment或者TransLog中读取同id的残缺Doc,记录版本号为V1。
  • 将版本V1的全量Doc和申请中的局部字段Doc合并为一个残缺的Doc,同时更新内存中的VersionMap。获取到残缺Doc后,Update申请就变成了Index申请。
  • 加锁。
  • 再次从versionMap中读取该id的最大版本号V2,如果versionMap中没有,则从Segment或者TransLog中读取,这里根本都会从versionMap中获取到。
  • 查看版本是否抵触(V1==V2),如果抵触,则回退到开始的“Update doc”阶段,从新执行。如果不抵触,则执行最新的Add申请。
  • 在Index Doc阶段,首先将Version + 1失去V3,再将Doc退出到Lucene中去,Lucene中会先删同id下的已存在doc id,而后再减少新Doc。写入Lucene胜利后,将以后V3更新到versionMap中。
  • 开释锁,局部更新的流程就完结了

详细描述一下ES搜寻的过程?

搜寻被执行成一个两阶段过程,即 Query Then Fetch;

Query阶段:
查问会播送到索引中每一个分片拷贝(主分片或者正本分片)。每个分片在本地执行搜寻并构建一个匹配文档的大小为 from + size 的优先队列。PS:在搜寻的时候是会查问Filesystem Cache的,然而有局部数据还在Memory Buffer,所以搜寻是近实时的。
每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到本人的优先队列中来产生一个全局排序后的后果列表。
Fetch阶段:
协调节点分别出哪些文档须要被取回并向相干的分片提交多个 GET 申请。每个分片加载并 丰盛 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回后果给客户端。

说说es的写一致性

咱们在发送任何一个增删改操作的时候,比如说put /index/type/id,都能够带上一个consistency参数,指明咱们想要的写一致性是什么?
put /index/type/id?consistency=quorum

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

聊聊 elasticsearch 深度分页以及scroll 滚动搜寻

深度分页
深度分页其实就是搜寻的深浅度,比方第1页,第2页,第10页,第20页,是比拟浅的;第10000页,第20000页就是很深了。
搜寻得太深,就会造成性能问题,会消耗内存和占用cpu。而且es为了性能,他不反对超过一万条数据以上的分页查问。那么如何解决深度分页带来的问题,咱们应该防止深度分页操作(限度分页页数),比方最多只能提供100页的展现,从第101页开始就没了,毕竟用户也不会搜的那么深,咱们平时搜寻淘宝或者京东也就看个10来页就顶多了。

滚动搜寻
一次性查问1万+数据,往往会造成性能影响,因为数据量太多了。这个时候能够应用滚动搜寻,也就是 scroll 。
滚动搜寻能够先查问出一些数据,而后再紧接着顺次往下查问。在第一次查问的时候会有一个滚动id,相当于一个锚标记 ,随后再次滚动搜寻会须要上一次搜寻滚动id,依据这个进行下一次的搜寻申请。每次搜寻都是基于一个历史的数据快照,查问数据的期间,如果有数据变更,那么和搜寻是没有关系的。

es在数据量很大的状况下如何进步性能

filesystem

es每次走fileSystem cache查问速度是最快的
所以将每个查问的数据50% 容量
= fileSystem cache 容量。

数据预热
数据预热是指,每隔一段时间,将热数据
手动在后盾查问一遍,将热数据刷新到fileSystem cache上

冷热拆散
相似于MySQL的分表分库
将热数据独自建设一个索引 调配3台机器只放弃热机器的索引
另外的机器放弃冷数据的索引,但有一个问题,就是当时必须晓得哪些是热数据 哪些是冷数据

不能够深度分页

跟产品经理说,你零碎不容许翻那么深的页,默认翻的越深,性能就越差。

相似于 app 里的举荐商品一直下拉进去一页一页的
相似于微博中,下拉刷微博,刷进去一页一页的,你能够用 scroll api

完结

es可能我本人用的也比拟少,就用来做一些搜寻,没有用来做bi,所以呢?也不是那么深刻吧,心愿对大家有帮忙,接下来温习下队列

日常求赞

好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是真粉

创作不易,各位的反对和认可,就是我创作的最大能源,咱们下篇文章见

微信 搜 "六脉神剑的程序人生" 回复888 有我找的许多的材料送给大家