ElasticSearch快速入门

2023年 7月 19日 52.3k 0

本文着力于介绍ES入门级的知识,目的是让大家能懂得基本使用,能应用到工作中;并产生兴趣,进而愿意去学习ES的深层设计思想和细节。

更深的ES框架设计思想和细节,欢迎关注后续文章。

一.ES是什么

ElasticSearch(后文简称ES)是一款稳定高效的近实时的分布式搜索和分析引擎。它的底层基于Lucene(一款强大的搜索和分析引擎),在Lucene基础上提供了友好的RESTful风格的交互方式。ES开箱即用,上手容易,性能优秀。

官网给了ES的几个典型使用场景:

  • 日志管理、系统指标检测和可视化

  • 卓越的搜索体验,支持文档,地理数据等各种内容

  • 交互式调查和自动威胁检测

目前ES在各大IT公司都有广泛的应用,比如Github拿来检索代码库,eBay拿来检索商品数据。当然数据量如果大到一定程度,ES的性能就可能不够了。

那么可能有同学就问了,mysql不是也可以做搜索吗?为啥要用es来做呢?原因是mysql的性能就满足不了需求,在模糊查询的情况下,mysql的索引发挥不了作用,查找很慢。

而ES就是专门做搜索的,它有几个突出的优点:

  • 搜索速度快(近实时)

  • 搜索到的数据可以进行评分,这样我们只需要返回评分高的数据给用户就行了(就像大家用搜索引擎一样,估计大部分都不会去点开第二页)。评分机制

  • 关键字不需要很准确也可以搜出相关的结果

一句话,Made For Search!

二.基本概念

上面我们讲到,ES是支持分布式的,所以它也支持集群。我们先了解下ES的一些基本组件。

  • Node(节点):进行数据存储,参与搜索和排序的单个实例。每个Node都有自己的唯一标识名

  • Cluster(集群):一个或多个Node组成的集合,人多力量大。ES具有自发现的能力,会自动寻找网络上配置在相同集群中的节点共同组成一个集群

  • Document(文档):ES中信息存储和检索的最小单位,以json的形式存储。

  • Field(字段):每个文档包含多个字段,类比可以想象json文件也有多个字段。

  • Index(索引):一些具有相似特征的文档的集合。

  • Type(类型):Type是Index的逻辑类别分区,相当于一个index可以有多个type分区。不过从6.0.0之后,ES废弃了Type的概念。

  • Shard(分片):当Index存储大量数据时,可能会超过单个节点的硬件限制,ES提供了把索引垂直切分为分片的机制,这样就可以跨分片分发和并行化操作,提高性能和吞吐量。

  • Replica(副本):ES提供了将分片复制为一个或多个副本的功能,这样在复杂多变的网络环境中出现故障后也能快速地恢复。

Node和Cluster是服务相关的概念,一般接触过分布式的同学都会多少有些了解。Document、Index、Type、Field跟数据库的概念也可以对应上

image.png

三.ES集群

我们先看一个ES集群的架构图,

image

ES集群中的每个节点都会有两个配置项:

  • node.master:表示节点是否具有成为主节点的资格。主节点负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等,而并不需要涉及到文档级别的变更和搜索等操作。

  • node.data:表示节点是否能存储数据,处理文档变更,搜索等

针对这两个参数的配置不同,某个节点可能会有四种角色:

  • node.master为true:主节点,不处理数据

  • node.master和node.data都为true:主节点,同时也处理数据

  • node.data为true:数据节点

  • node.master和node.data都不为true:称为协调节点,不管理集群,也不维护数据,主要用作负载均衡。主节点和数据节点都拥有协调节点的能力。

ES给分片提供了Replicas机制,分片分为主分片和副分片,数据写入的时候是写到主分片,副本分片会复制主分片的数据,读取的时候主副分片都可以读。Index需要分成多少个主副分片可以通过配置设置。但是有一个强制要求:一个主分片至少有一个副分片,且主分片P0对应的副分片R0不能跟P0同时处于一个node上。当某个节点挂了,这个节点上的主分片也就挂了,那么master node就会把主分片对应的副分片提拔为主分片。

对于主分片来说,一个文档只会存在一个主分片上面,那么怎么定位这个存储了文档的分片呢?根据公式来算的。

shard = hash(routing) % number_of_primary_shards

routing是拿来定位分片的可变值,默认是文档id。routing的选择非常重要,能显著提升ES使用性能。对应到我们C端ES来说,文档id是product_id,routing是shop_id,这是因为使用场景大多是店铺相关。

number_of_primary_shards是主分片的数量,这个是创建索引的时候就要确定好的。

所以协调节点的作用,就是根据公式计算出每个请求的具体需要处理的分片。

  • 对于写操作(如写入文档),协调节点会路由到对应的主分片进行写入,然后复制到副本分片中。主副节点都写入成功之后,返回给客户端结果。

image

  • 对于读操作(如读取某个文档),通过round-robin随机轮训算法随机寻找主副分片中的一个,进行读取操作。

  • 对于搜索操作(如根据条件搜索),协调节点会把命令转发到所有的主分片或副分片,每一个分片将自己搜索的结果返回给协调节点,由协调节点进行数据的合并,排序,分页等操作,产出最后的结果。

四.搜索原理

4.1 倒排索引

前面我们说到了,ES是为搜索而生,那么为什么他可以做到那么高的搜索性能呢,主要是因为他使用了Lucene的倒排索引技术。

假设我们有这样几条数据。

docId name age sex desc
1 Ada 18 women rich and smart
2 Carla 20 women rich and tough
3 John 18 man beautiful

那么这样每一行都是一个document,每个document都有一个docId。

从docId去查询到这一条记录,我们称为是正排索引。而通过姓名,年龄,性别这些参数去查询到对应的docId,就叫做倒排索引。

在这个例子中,建立的倒排索引就是

name
Ada [1]
Carla [2]
John [3]
age
18 [1,3]
20 [2]
sex
man [3]
woman [1,2]

这样如果我们想找男性且年龄为18的,就可以求交集得到docId为3。

而对于desc这种长端的文本,es会采用分词技术,拆解为单个有意义的词组,同样建立倒排索引

desc
rich [1,2]
smart [1]
tough [2]
beautiful [3]

我们将倒排索引的查询项称为term,如Ada,man等。将对应查出来的docId list称为posting list。

但是,因为每个字段可能都有不同的取值,index规模大了以后,term的规模也会很大,这就需要ES能较快的查询到term。

4.2 ES Term查询

假设我们有很多个term,比如:

Carla,Sara,Elin,Ada,Patty,Kate,Selena

如果按照这样的顺序排列,找出某个特定的term一定很慢,因为term没有排序,需要全部过滤一遍才能找出特定的term。排序之后就变成了:

Ada,Carla,Elin,Kate,Patty,Sara,Selena

这样我们可以用二分查找的方式,比全遍历更快地找出目标的term。这个就是 term dictionary。

但是term dictionary可能会非常大,没办法放在内存中,只能放在硬盘中分块存储。于是,es采用了trie树来记录term的前缀,称为term index。

通过term index可以快速的定位到某个term dictionary的某个offset,然后从这个位置再往后查找。再加上一些压缩技术,term index的尺寸可能是所有term的尺寸的几十分之一,从而可以将term index缓存到内存中。

查询方式为:

image

注:数值类型的范围查找,并没有使用倒排索引,可以参考range原理

五.基本使用

5.1 搭建集群

5.1.1 搭建ES集群

接下来我们从0到1搭建一个集群,方便后续的练习。我这里使用的是公司的开发机,使用docker编排容器,es版本为7.8.1。

1.首先我们需要在开发机上安装docker,可参考 docker安装

2.安装好docker后,我们需要先拉取es的镜像。

docker pull elasticsearch:7.8.1

3.配置网络

为了模拟我们的es是独立服务器,我们可以使用docker网络IP指定隔离;docker 创建容器时默认采用的bridge网络,自行分配IP,不允许我们自己指定。而在实际部署中,我们需要指定容器IP,不允许其自行分配IP,尤其是搭建集群时,固定IP时必须的。所以我们可以创建自己的bridge网络:mynet,创建容器的时候指定网络为mynet并指定IP即可

#查看网络模式 
docker network ls
#创建一个新的bridge网络-mynet
docker network create --driver bridge --subnet=172.18.12.0/16 --gateway=172.18.1.1 mynet
#查看网络详情
docker network inspect mynet
#以后使用--network=mynet --ip 172.18.12.x 指定IP

image

4.接下来我们可以编写两个脚本,用于部署es的master节点和data节点。

创建三个master节点

for port in $(seq 1 3);
do
mkdir -p ~/es/docker_es/elasticsearch/master-${port}/config
mkdir -p ~/es/docker_es/elasticsearch/master-${port}/data
chmod -R 777 ~/es/docker_es/elasticsearch/master-${port}
cat

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论