[转]基于Elasticsearch分布式搜索引擎的架构原理

[转]基于Elasticsearch分布式搜索引擎的架构原理

http://www.mobabel.net/%E8%BD%AC%E5%9F%BA%E4%BA%8Eelasticsearch%E5%88%86%E5%B8%83%E5%BC%8F%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E7%9A%84%E6%9E%B6%E6%9E%84%E5%8E%9F%E7%90%86/

ES分布式架构及底层原理

https://segmentfault.com/a/1190000015256970

(1)倒排索引到底是啥?

要了解分布式搜索引擎,先了解一下搜索这个事儿吧,搜索这个技术领域里最入门级别的一个概念就是倒排索引。

我们先简单说一下倒排索引是个什么东西。

假如说你现在不用搜索引擎,单纯使用数据库来存放和搜索一些数据,比如说放了一些论坛的帖子数据吧,那么这个数据的格式大致如下:

idtitlecontent
1Java好用吗?Java是非常非常好的一门语言。。。。
2大家一起来学Java我这儿有一些很好的Java学习资源,比如说。。。
3一次Java面试经验去年这个时候,我学了Java,今年开始了面试。。。

很简单吧,假设有一个id字段标识了每个帖子数据,然后title字段是帖子的标题,content字段是帖子的内容。

那么这个时候,比如我们要是用数据库来进行搜索包含“Java”这个关键字的所有帖子,大致SQL如下:

咱们姑且不论这个数据库层面也有支持全文检索的一些特殊索引类型,或者数据库层面是怎么执行的,这个不是本文讨论的重点,你就看看数据库的数据格式以及搜索的方式就好了。

但是如果你通过搜索引擎类的技术来存放帖子的内容,他是可以建立倒排索引的。

也就是说,你把上述的几行数据放到搜索引擎里,这个倒排索引的数据大致看起来如下:

关键词     id

Java         [1, 2, 3]

语言         [1]

面试         [3]

资源         [2]

所谓的倒排索引,就是把你的数据内容先分词,每句话分成一个一个的关键词,然后记录好每个关键词对应出现在了哪些id标识的数据里。

那么你要搜索包含“Java”关键词的帖子,直接扫描这个倒排索引,在倒排索引里找到“Java”这个关键词对应的那些数据的id就好了。

然后你可以从其他地方根据这几个id找到对应的数据就可以了,这个就是倒排索引的数据格式以及搜索的方式,上面这种利用倒排索引查找数据的方式,也被称之为全文检索

(2)什么叫做分布式搜索引擎?

其实要知道什么叫做分布式搜索引擎,你首先得知道,假如我们就用一台机器部署一个搜索引擎系统,然后利用上述的那种倒排索引来存储数据,同时支持一些全文检索之类的搜索功能,那么会有什么问题?

其实还是很简单,假如说你现在要存储1TB的数据,那么放在一台机器还是可以的。

但是如果你要存储超过10TB,100TB,甚至1000TB的数据呢?你用一台机器放的下吗?

当然是放不下的了,你的机器磁盘空间是不够的。

大家看一下下面的图:

所以这个时候,你就得用分布式搜索引擎了,也就是要使用多台机器来部署搜索引擎集群。

比如说,假设你用的是Elasticsearch(后面简写为:ES)。

现在你总共有3TB的数据,那么你搞3台机器,每台机器上部署一个ES进程,管理那台机器上的1TB数据就可以了。

这样不就可以把3TB的数据分散在3台机器上来存储了?这不就是索引数据的分布式存储吗?

而且,你在搜索数据的时候,不就可以利用3台机器来对分布式存储后的数据进行搜索了?每台机器上的ES进程不都可以对一部分数据搜索?这不就是分布式的搜索?

是的,这就是所谓的分布式搜索引擎:把大量的索引数据拆散成多块,每台机器放一部分,然后利用多台机器对分散之后的数据进行搜索,所有操作全部是分布在多台机器上进行,形成了完整的分布式的架构。

同样,我们来看下面的图,直观的感受一下。

(3)Elasticsearch的数据结构

如果你要是使用Elasticsearch这种分布式搜索引擎,必须要熟悉他的一些专业的技术名词,描述他的一些数据结构。

比如说“index”这个东西,他是索引的意思,其实他有点类似于数据库里的一张表,大概对应表的那个概念。

比如你搞一个专门存放帖子的索引,然后他有id、title、content几个field,这个field大致就是他的一个字段。

然后还有一个概念,就是document,这个就代表了index中的一条数据。

下面就是一个document,这个document可以写到index里去,算是index里的一条数据。

而且写到es之后,这条数据的内容就会拆分为倒排索引的数据格式来存储。

idtitlecontent
1Java好用吗?Java是非常非常好的一门语言。。。。

(4)Shard数据分片机制

那么这个时候大家考虑一下,比如说你有一个index,专门存放论坛里的帖子,现在论坛里的帖子有1亿,占用了1TB的磁盘空间,这个还好说。

如果这个帖子有10亿,100亿,占用了10TB、甚至100TB的磁盘空间呢?

那你这个index的数据还能在一台机器上存储吗?答案明显是不能的。

这个时候,你必须得支持这个index的数据分布式存储在多台机器上,利用多台机器的磁盘空间来承载这么大的数据量。

而且,需要保证每台机器上对这个index存储的数据量不要太大,因为控制单台机器上这个index的数据量,可以保证他的搜索性能更高。

所以这里就引入了一个概念:Shard数据分片结构。每个index你都可以指定创建多少个shard,每个shard就是一个数据分片,会负责存储这个index的一部分数据。

比如说index里有3亿帖子,占据3TB数据。然后这个index你设置了3个shard。

那么每个shard就可以包含一个1TB大小的数据分片,每个shard在集群里的一台机器上,这样就形成了利用3台机器来分布式存储一个index的数据的效果了。

大家看下面的图:

现在index里的3TB数据分布式存储在了3台机器上,每台机器上有一个shard,每个shard负责管理这个index的其中1TB数据的分片。

而且,另外一个好处是,假设我们要对这个index的3TB数据运行一个搜索,是不是可以发送请求到3台机器上去?

3台机器上的shard直接可以分布式的并行对一部分数据进行搜索,起到一个分布式搜索的效果,大幅度提升海量数据的搜索性能和吞吐量。

(5)Replica多副本数据冗余机制

但是现在有一个问题,假如说3台机器中的其中一台宕机了,此时怎么办呢?

是不是这个index的3TB数据的1/3就丢失了?因为上面有1TB的数据分片没了。

所以说,还需要为了实现高可用使用Replica多副本数据冗余机制。

在Elasticsearch里,就是支持对每个index设置一个replica数量的,也就是每个shard对应的replica副本的数量。

比如说你现在一个index有3个shard,你设置对每个shard做1个replica副本,那么此时每个shard都会有一个replica shard。

这个初始的shard就是primary shard,而且primary shard和replica shard是绝对不会放在一台机器上的,避免一台机器宕机直接一个shard的副本也同时丢失了。

我们再来看下面的图,感受一下:

在上述的replica机制下,每个primary shard都有一个replica shard在别的机器上,任何一台机器宕机,都可以保证数据不会丢失,分布式搜索引擎继续可用。

Elasticsearch默认是支持每个index是5个primary shard,每个primary shard有1个replica shard作为副本。

(6)文末总结

好了,本文到这儿就结束了,再来给大伙简单小结。

我们从搜索引擎的倒排索引开始,到单机无法承载海量数据,再到分布式搜索引擎的存储和搜索。

然后我们以优秀的分布式搜索引擎ES为例,阐述了ES的数据结构,shard数据分片机制,replica多副本机制,解释了一下分布式搜索引擎的架构原理。

最后还是强调一下,在Java面试尤其是高级Java面试中,对于分布式搜索引擎技术的考察越来越重,所以这块技术的重要性,还是不容小觑的!

 

[source]面试请不要再问我分布式搜索引擎的架构原理!

Please follow and like us:

error0

 

Related Posts:

  1. [转]手把手教你搭建一个 Elasticsearch 集群
  2. [转]滴滴Elasticsearch多集群架构实践
  3. [转]分布式之elk日志架构的演进
  4. [转]日均5亿查询量,京东到家订单中心ES架构演进

es分布式架构原理

elasticsearch设计的理念就是分布式搜索引擎,底层实现还是基于Lucene的,核心思想是在多态机器上启动多个es进程实例,组成一个es集群。一下是es的几个概念:

  1. 接近实时
    es是一个接近实时的搜索平台,这就意味着,从索引一个文档直到文档能够被搜索到有一个轻微的延迟
  2. 集群(cluster)
    一个集群有多个节点(服务器)组成,通过所有的节点一起保存你的全部数据并且通过联合索引和搜索功能的节点的集合,每一个集群有一个唯一的名称标识
  3. 节点(node)
    一个节点就是一个单一的服务器,是你的集群的一部分,存储数据,并且参与集群和搜索功能,一个节点可以通过配置特定的名称来加入特定的集群,在一个集群中,你想启动多少个节点就可以启动多少个节点。
  4. 索引(index)
    一个索引就是还有某些共有特性的文档的集合,一个索引被一个名称唯一标识,并且这个名称被用于索引通过文档去执行搜索,更新和删除操作。
  5. 类型(type)
    type 在6.0.0已经不赞成使用
  6. 文档(document)
    一个文档是一个基本的搜索单元

总结:
es中,存储数据的基本单位就是索引,比如说es中存储了一些订单系统的销售数据,就因该在es中创建一个索引,order—index,所有的销售数据就会都写到这个索引里面去,一个索引就像数据库。而type就相当于每一张表,
一个index里面可以有多个type,而mapping就相当于表的结构定义,定义了什么字段类型等,你往index的一个type里添加一行数据就叫做一个document,每一个document有多个filed,每一个filed就代表这个document的一个字段的值。

  1. 分片(shards)

在一个搜索里存储的数据,潜在的情况下可能会超过单个节点的硬件的存储限制,为了解决这个问题,elasticsearch便提供了分片的功能,它可以将索引划分为多个分片,当你创建一个索引的时候,你就可以简单的定义你想要的分片的数量,每一个分片本身是一个全功能的完全独立的索引,可以部署到集群中的任何一个节点。分片的两个总要原因:
(1)它允许你水平切分你的内容卷
(2)它允许通过分片来分布和并执行操作来应对日益增长的执行量

  1. 复制(replica)
    在一个网络情况下,故障可能会随时发生,有一个故障恢复机制是必须的,为了达到这个目的,ES允许你制作一个或多个拷贝放入一个叫做复制分片或短暂的复制品中。复制对于以下两个主要原因很重要
    (1)高可用。它提供了高可用的以来防止分片或者节点宕机,为此,一个非常重要的注意点就是绝对不要讲一个分片的拷贝放在跟这个分片相同的机器上。
    (2)高并发。它允许你的分片可以提供超出自身吞吐量的搜索服务,搜索行为可以在分片所有的拷贝中并行执行。
    总之,一个完整的流程就是,ES客户端将一份数据写入primary shard,它会将分成成对的shard分片,并将数据进行复制,ES客户端取数据的时候就会在replica或primary 的shard中去读。ES集群有多个节点,会自动选举一个节点为master节点,这个master节点其实就是干一些管理类的操作,比如维护元数据,负责切换primary shard 和replica shard的身份之类的,要是master节点宕机了,那么就会重新选举下一个节点为master为节点。如果时非master宕机了,那么就会有master节点,让那个宕机的节点上的primary shard的身份转移到replica shard上,如果修复了宕机的那台机器,重启之后,master节点就会控制将缺失的replica shard 分配过去,同步后续的修改工作,让集群恢复正常。

es写入数据的过程

  1. 客户端选择一个node发送请求过去,这个node就是coordinating node (协调节点)
  2. coordinating node,对document进行路由,将请求转发给对应的node
  3. 实际上的node上的primary shard处理请求,然后将数据同步到replica node
  4. coordinating node,如果发现primary node和所有的replica node都搞定之后,就会返回请求到客户端

es读数据过程

查询,GET某一条的数据,写入某个document,这个document会自动给你分配一个全局的唯一ID,同时跟住这个ID进行hash路由到对应的primary shard上面去,当然也可以手动的设置ID

  1. 客户端发送任何一个请求到任意一个node,成为coordinate node
  2. coordinate node 对document进行路由,将请求转发到对应的node,此时会使用round-robin随机轮训算法,在primary shard 以及所有的replica中随机选择一个,让读请求负载均衡,
  3. 接受请求的node,返回document给coordinate note
  4. coordinate node返回给客户端

es搜索数据过程

  1. 客户端发送一个请求给coordinate node
  2. 协调节点将搜索的请求转发给所有的shard对应的primary shard 或replica shard
  3. query phase:每一个shard 将自己搜索的结果(其实也就是一些唯一标识),返回给协调节点,有协调节点进行数据的合并,排序,分页等操作,产出最后的结果
  4. fetch phase ,接着由协调节点,根据唯一标识去各个节点进行拉去数据,最总返回给客户端

写入数据的底层原理

  1. 数据先写入到buffer里面,在buffer里面的数据时搜索不到的,同时将数据写入到translog日志文件之中
  2. 如果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之中的数据持久化到磁盘之中
  3. 重复以上的操作,每次一条数据写入buffer,同时会写入一条日志到translog日志文件之中去,这个translog文件会不断的变大,当达到一定的程度之后,就会触发commit操作。
  4. 将一个commit point写入到磁盘文件,里面标识着这个commit point 对应的所有segment file
  5. 强行将OS cache 之中的数据都fsync到磁盘文件中去。
    解释:translog的作用:在执行commit之前,所有的而数据都是停留在buffer或OS cache之中,无论buffer或OS cache都是内存,一旦这台机器死了,内存的数据就会丢失,所以需要将数据对应的操作写入一个专门的日志问价之中,一旦机器出现宕机,再次重启的时候,es会主动的读取translog之中的日志文件的数据,恢复到内存buffer和OS cache之中。
  6. 将现有的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到磁盘,但是性能会比较差。
  7. 如果时删除操作,commit的时候会产生一个.del文件,里面讲某个doc标记为delete状态,那么搜索的时候,会根据.del文件的状态,就知道那个文件被删除了。
  8. 如果时更新操作,就是讲原来的doc标识为delete状态,然后重新写入一条数据即可。
  9. buffer每次更新一次,就会产生一个segment file 文件,所以在默认情况之下,就会产生很多的segment file 文件,将会定期执行merge操作
  10. 每次merge的时候,就会将多个segment file 文件进行合并为一个,同时将标记为delete的文件进行删除,然后将新的segment file 文件写入到磁盘,这里会写一个commit point,标识所有的新的segment file,然后打开新的segment file供搜索使用。

总之,segment的四个核心概念,refresh,flush,translog、merge

搜索的底层原理

查询过程大体上分为查询和取回这两个阶段,广播查询请求到所有相关分片,并将它们的响应整合成全局排序后的结果集合,这个结果集合会返回给客户端。

  1. 查询阶段

    1. 当一个节点接收到一个搜索请求,这这个节点就会变成协调节点,第一步就是将广播请求到搜索的每一个节点的分片拷贝,查询请求可以被某一个主分片或某一个副分片处理,协调节点将在之后的请求中轮训所有的分片拷贝来分摊负载。
    2. 每一个分片将会在本地构建一个优先级队列,如果客户端要求返回结果排序中从from 名开始的数量为size的结果集,每一个节点都会产生一个from+size大小的结果集,因此优先级队列的大小也就是from+size,分片仅仅是返回一个轻量级的结果给协调节点,包括结果级中的每一个文档的ID和进行排序所需要的信息。
    3. 协调节点将会将所有的结果进行汇总,并进行全局排序,最总得到排序结果。
  2. 取值阶段

    1. 查询过程得到的排序结果,标记处哪些文档是符合要求的,此时仍然需要获取这些文档返回给客户端
    2. 协调节点会确定实际需要的返回的文档,并向含有该文档的分片发送get请求,分片获取的文档返回给协调节点,协调节点将结果返回给客户端。

倒排索引

倒排索引就建立分词与文档之间的映射关系,在倒排索引之中,数据时面向分词的而不是面向文档的。

在海量数据中怎样提高效率

  1. filesystem cache
    ES的搜索引擎是严重的依赖底层的filesystem cache,如果给filesystem cache更多的内存,尽量让内存可以容纳所有的index segment file 索引数据文件
  2. 数据预热
    对于那些你觉得比较热的数据,经常会有人访问的数据,最好做一个专门的缓存预热子系统,就是对热数据,每隔一段时间,你就提前访问以下,让数据进入filesystem cache里面去,这样期待下次访问的时候,性能会更好一些。
  3. 冷热分离

关于ES的性能优化,数据拆分,将大量的搜索不到的字段,拆分到别的存储中去,这个类似于MySQL的分库分表的垂直才分。

  1. document的模型设计

不要在搜索的时候去执行各种复杂的操作,尽量在document模型设计的时候,写入的时候就完成了,另外对于一些复杂的操作,尽量要避免

  1. 分页性能优化

翻页的时候,翻得越深,每个shard返回的数据越多,而且协调节点处理的时间越长,当然是用scroll,scroll会一次性的生成所有数据的一个快照,然后每次翻页都是通过移动游标完成的。 api 只是在一页一页的往后翻

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值