大家都知道搜索搜引擎是什么,例如我们接触比较多的 百度、Google、必应、360搜索、淘宝搜索、京东搜索等等很多只要能搜索就可以被称为搜索引擎。以下是比较官方的说法。

搜索引擎(Search Engine)是根据一定的策略、运用特定的计算机程序去搜集信息,在对信息进行组织和处理后,为用户提供检索服务,将用户检索相关的信息展示给用户的一套系统。

搜索引擎的组成

搜索引擎一般由索引组件搜索组件所组成。下图中展示了索引组件和搜索组件的工作流程。


索引组件为上图中红色框部分

搜索组件为上图中绿色框部分

索引组件: 获取数据Acquire Content-->建立文档Build Document-->文档分析Analyze Document-->文档索引(Index Document)

搜索组件: 用户搜索接口Search User Interface-->建立查询Build Query(将用户键入的信息转换为可处理的查询对象)-->搜索查询Run Query-->展现结果Render Results

为什么索引组件的工作流程是由下往上呢? 举例:例如淘宝,当我们在淘宝中搜索一件商品的时候,在能搜索到的前提下,那它这个商品肯定是提前要存储到淘宝的存储库当中,淘宝卖家把一件衣服上架到了淘宝平台,这就叫做 Raw Content(原始内容);当衣服存储到淘宝的存储库当中呢,搜索引擎就开始获取这件衣服的图片信息和标题内容等,获取到的内容会被存为文档才能供搜索引擎使用,这个叫 Acquire Content获取内容;存为文档之后,一般来说,一句话或者一条信息都可以作为一个文档,但是现在需要建立文档 Build Document,建立文档的过程是向单个文档插入权重值,目的是为了在搜索引擎搜索的时候进行排序,当然是权值越高越容易被搜索到了哈,不然不会出现SEO的。文件建立成功后,搜索引擎还不能直接对文本进行索引呢,还需要将文档即文本内容分割成独立的元素,可以理解为切片、分词等,把一句话拆分成了好多个字或者说字节;这个步骤为 Analyzer Document文档分词,切词过后,文档就要被加上索引列表啦,即我们搜索的时候,通过索引会给你搜索到1-10的数字、搜索2的时候会给你搜索到2-20的数字等,这就叫做添加索引 Idenx Document。这一系列统统被称为索引组件来完成的工作,接下来就等着被搜索引擎搜索吧。

淘宝的搜索框就是我们的用户搜索界面 Search User Interface,当我们在search interface输入东西去搜索内容的时候浏览器会把你输入的内容转换为HTML或Ajax的格式提交给搜索引擎服务器,即淘宝的搜索引擎服务器,由浏览换转换你输入内容的步骤叫做建立查询Build Query;当查询建立后,淘宝的搜索引擎就会拿着你输入的内容去存储库中寻找相匹配的内容,会直接查询上述步骤中已经建立好的索引,此步骤叫做搜索查询 Run Query;搜索到相匹配内容后,就要通过界面展现给你,淘宝的搜索引擎拿到数据后返回到你的浏览器当中,一次完整的搜索就此完成,此步骤叫做Render Results展现结果

索引是一种数据结构,它允许对它存储在其中的单词进行快速随机访问。当需要从大量文本中快速检索文本目标时,必须首先将文本内容转换成能够进行快速搜索的格式,以建立针对文本的索引数据结构,此即为索引过程。

那当前使用较多的搜索引擎无疑是Elasticsearch,下面来看一下Elasticsearch的原理及基本概念

Elasticsearch介绍

Elasticserch是一个开源且分布式、RESTful风格的搜索引擎和数据分析引擎,由Java编写,它的内部使用的是Apache Lucene做索引功能,Elasticsearch建立在一个全文的搜索引擎库“Apache Lucene”基础之上,作为Elastic Stack的核心,它集中存储你的数据。Elasticsearch不仅仅只是一个全文搜索引擎,它还可以用作全文检索、结构化搜索、分析以及这三个功能的组合。

1.全文检索:一个分布式的实时文档存储,每个字段都可以被索引与搜索2.结构化搜索:能胜任上百个服务节点的扩展,并支持PB级别的结构化或者非结构化数据3.分析:一个分布式实时分析搜索引擎

Elasticsearch的基本概念

Elasticsearch的基本概念大致可以分为以下几点:ClusterNodeIndexShardsReplicasDocument。下面简单介绍这几种概念:

Cluster

集群是一个或多个节点的集合,它们共同保存整个数据,并提供跨所有节点的联合索引和搜索功能。集群由唯一名称标识,默认情况下为"elasticsearch"。此名称很重要,因为如果节点设置为按名称加入集群,则该节点只能是集群的一部分。确保不要在不同的环境中用相同集群名称,否则最终会导致节点加入错误的集群。每个集群都要有自己唯一的集群名称。

Node

节点是作为集群一部分的单个服务器,存储数据并参与集群的索引和搜索功能。与集群一样,节点由名称标识,默认情况下,该名称是在启动时分配给及节点的随机通用唯一标识符(UUID)。如果不需要默认值,可以定义所需的任何节点名称。此名称对于管理目的非常重要,可以在其中识别网络中的哪些服务器与Elasticsearch集群中的哪些节点相对应。可以将节点配置按集群名称加入特定集群。默认情况下,每个节点都设置为加入一个名为elasticsearch的集群,这意味着如果你在网络上启动了许多节点并且假设它们可以相互发现,它们将自动形成并加入一个名为elasticsearch的集群。在单个集群中,可以拥有任意数量的节点。此外,如果网络上当前没有其它Elasticsearch节点在运行,则默认情况下启动单个节点将形成一个名为elasticsearch的新节点集群。

Index

索引是具有某些类似特征的文档集合。例如,你可以拥有客户数据的索引,产品目录的另一个索引以及订单数据的另一个索引。索引由名称标识(必须全部为小写),并且此名称用于在对其中的文档执行索引,搜索,更新和删除操作时引用索引。在单个集群中,你可以根据需要定义任意数量的索引。Index 体现了逻辑空间的概念,每个索引都有自己的 Mapping 定义,用于定义包含文档的字段名称和字段类型。

索引的 Mapping 与 Settings

Mapping 定义文档字段的类型Setting 定义不同的数据分布

索引元数据内包含 Mapping 和 Setting

索引元数据 一个完整的索引元数据包含Mapping信息Setting信息。

{ "movies" : { #索引名称 "aliases" : { }, #索引别名
Mapping元数据 "mappings" : { #Mapping设置 "properties" : { "@version" : { #Version为字段名称,字段为写到es中自定义的字段 "type" : "text", #Version字段名称处的字段类型,这里为字符串,在es中为 text "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "genre" : { #gener字段类型 "type" : "text", #类型为字符串 "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "id" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "title" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "year" : { #year字段类型 "type" : "long" #year字段类型为数值,数值在es中为 long } } },
Setting元数据 "settings" : { #Setting设置 "index" : { "creation_date" : "1575518947108", #创建索引的时间戳 "number_of_shards" : "1", #索引的分片数量 "number_of_replicas" : "1", #索引的副本数量 "uuid" : "r4qFegpeSmCnxmJzYVPO6w", #索引的UUID,具备唯一性 "version" : { #版本信息 "created" : "7040099" #版本信息创建时间 }, "provided_name" : "movies" } } }}

Document

文档是可以建立索引的基本信息单元,是所有可搜索数据的最小单位,。例如,你可以为单个客户创建一个文档,为单个产品创建另一个文档,为单个订单创建另一个文档。这些文档会被序列化成 JSON 格式,保存在 Elasticsearch 的分片中,因为Elasticsearch用JSON(JavaScript对象表示法)表示,格式为 Key=>Value,这是一种无处不在的internet数据交换格式。在索引中,可以存储任意数量的文档。Key在Elasticsearch被称为字段名称 Value在Elasticsearch中被称为字段值。每个字段Key都有对应的字段类型 (字符串text/数值long/布尔boolean/日期date/二进制binary/范围类型range)等。。。字段类型我们可以自己定义,也可以先插入文档后通过 Elasticsearch 自动推算字段类型。每个文档都有一个 Unique ID,你可以通过创建文档时指定,或者通过 Elasticsearch 自动生成。

文档的Metadata元数据

 { "_index": "movies", #文档所属的索引名称 "_type": "_doc", #文档所属的类型名称 "_id": "288", #文档唯一 ID "_version": 1, #文档版本信息 "_score": 0, #相关性打分 "_source": { #文档的原始 Json 数据 "year": 1994, #字段year:字段值1994 "id": "288",  "title": "Natural Born Killers", "@version": "1", "genre": [ "Action", "Crime", "Thriller" ] }}

Shards & Replicas

一个索引可能存储大量数据,这些数据可以超过单个节点的硬件限制。例如一个包含10条文档占用1TB磁盘空间的索引显然不适合在单个节点上,肯定会很慢而且不能单独来处理单个节点的搜索请求。为了解决这个问题,Elasticsearch提供了将你的索引细分为多个碎片或者叫分片的能力。在创建索引时,可以简单的定义所需的分片数量。每个分片本身就是一个功能完全独立的索引“索引”,可以驻留在集群中的任何节点上。分片之所以重要,主要由两个原因:

它允许水平地分割/扩展内容卷它允许你夸分片(可能在多个节点上)分布和并行操作,从而提高性能和吞吐量

在一个网络环境中随时都可能出现故障,强烈推荐有容灾机制。Elasticsearch允许你将一个或多个索引分片复制到其它地方,这被称之为副本。复制之所以重要,有两个主要原因:

它在分片/节点出现故障时提供高可用性。因此,副本分片永远不会在从中复制的原始/主分片相同的节点上分配。它允许你扩展搜索量/吞吐量,因为可以在所有副本上并行执行搜索

在Elasticsearch7开始,创建的索引默认是一个主分片和一个副本分片,在Elasticsearch5和6中,每个索引默认分配了5个主分片和1个副本分片。

总而言之,每个索引可以拆分多个分片。索引也可以复制为零(表示没有副本)或更多次。一旦被复制,每个索引都将具有主分片(被复制的原始分片)和副本分片(主分片的副本)。在创建索引时,可以为每个索引定义分片和副本的数量。创建索引后,你可以随时动态的更新副本的数量,但不能更改事后分片的数量。除非Reindex。

一个分片是一个运行的 Lucene 的实例。 主分片数在索引创建时指定,后续不允许修改,除非 Reindex 副本不可以和主分片在同一台ES实例中,否则会报 “yellow”

分片的设定

1.分片数设置过小导致后续无法增加节点实现水平扩展。单个分片的数据量太大,导致数据重新分配耗时。2.分片数设置过大影响搜索结果的相关性打分,影响统计结果的准确性。单个节点上过多的分片,会导致资源浪费,同时也会影响性能。

Elasticsearch原理概述

在一次搜索中,Elasticsearch原理如下



图示,两个ES节点组成的Elasticsearch Cluster,每个主机上都有两个分片,分别为主分片和副本分片。以上图讲解的是ES集群面对用户请求的响应操作。

请求处理流程: 假如用户请求的读read到Node1来请求数据,一般我们由副本分片来处理,主分片能读能写,但是我们一般是要求主分片是处理写操作,而副本分片来进行读操作,我们的Node1接收到读请求后,自己主机处理一部分请求,另外一部分请求转发给Node2的副本分片来处理,结果处理后Node2返回一部分结果给Node1,Node1再把自己返回的请求和Node2返回给自己的请求进行整合后返回给应用程序。在ES集群中,所有节点都可以接收到来自于应用程序的请求,只不过是有接收应用程序的主机自己处理了一部分请求,而另一部分请求代理转发给集群中的其它节点处理。

注意:读请求可以发给副本分片,但是写请求只能由主分片来处理,当然主分片也可以处理读请求。

Elasticserch的由来

多年前,一个叫做Shay Banon的刚结婚不久的失业开发者,由于妻子要去伦敦学习厨师,他便跟着也去了。在他找工作的过程中,为了给妻子构建一个食谱的搜索引擎,他开始构建一个早期版本的Lucene。直接基于Lucene工作会比较困难,所以Shay开始抽象Lucene代码以便Java程序员可以在应用中添加搜索功能。他发布了他的第一个开源项目,叫做“Compass”。后来Shay找到一份工作,这份工作处在高性能和内存数据网格的分布式环境中,因此高性能的、实时的、分布式的搜索引擎也是理所当然需要的。然后他决定重写Compass库使其成为一个独立的服务叫做Elasticsearch。第一个公开版本出现在2010年2月,在那之后Elasticsearch已经成为Github上最受欢迎的项目之一,代码贡献者超过300人。一家主营Elasticsearch的公司就此成立,他们一边提供商业支持一边开发新功能,不过Elasticsearch将永远开源且对所有人可用。

据说:Shay的妻子依旧等待着她的食谱搜索……


©著作权归作者所有:来自51CTO博客作者mob604756edd67c的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. C数组实现静态链表及常用操作(模拟无指针编程语言数组实现链表)
  2. 在Ubuntu系统上使用kubeadm部署v1.20版的Kubernetes集群
  3. 用户行为分析模型实践(一)—— 路径分析模型
  4. 大数据成神之路-Java高级特性增强(ConcurrentSkipListMap)
  5. web前端技术分享之:Canvas框架之Konva.js --元素节点的事件
  6. 面试官再问你优先级队列,请把这篇文章丢给他
  7. 删除链表中重复的节点
  8. 2021-03-14:手写代码:单链表冒泡排序。
  9. 掌握这几个技巧,以后用MySQL查询总比别人快一步!

随机推荐

  1. Android创建桌面快捷方式
  2. Android软件开发常用系统控件(一) TextView
  3. 第十四周实验报告:实验四 Android程序设计
  4. listview android:cacheColorHint,listSe
  5. 解决 android如何设置全屏模式
  6. android实现TextView多行文本滚动
  7. android Fragment与Activity交互,互相发数
  8. Android TextView实现跑马灯效果
  9. Android探索之旅 | Android(安卓)Studio
  10. 2018年60个实用Android框架排行榜