首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >ElasticSearch基础:从倒排索引说起,快速认知ES

ElasticSearch基础:从倒排索引说起,快速认知ES

作者头像
云深i不知处
发布于 2022-01-05 06:19:06
发布于 2022-01-05 06:19:06
4.1K00
代码可运行
举报
文章被收录于专栏:测试基础测试基础
运行总次数:0
代码可运行

ElasticSearch基础:从倒排索引说起,快速认知ES

1 ElasticSearch认知

ElasticSearch(简称ES)是什么?按照 ElasticSearch官网 的定义,Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎。

很官方,但也很晦涩。所以,接下来我们尝试比较直白地去描述它。

1.1 关于搜索

首先,需要弄明白下面几个问题:

  1. 什么是搜索?
  2. 为什么数据库不适合处理搜索?
  3. 什么是全文检索和Lucene?

提到搜索,人们会立刻联想到在百度、谷歌上输入关键词获取相关的内容的场景。但搜索不等于百度,大部分APP支持的站内搜索更加大行其道。

数据库是储存和查询数据的利器,那么数据库是否适合做搜索呢?答案是不合适。第一个原因是,当数据库存储了大量数据后,查询效率大幅降低。

另外有些搜索场景,数据库也是不支持的,例如在下表中,我们试图通过“中国足球”这个关键词搜索数据,数据库是无法查询到相应内容的。

id

name

1

中国男子足球队

2

中国男子田径队

3

中国女子排球队

4

中国女子跳水队

1.2 倒排索引

什么是倒排索引?倒排索引也叫反向索引,我们通常理解的索引是通过key寻找value,与之相反,倒排索引是通过value寻找key,故而被称作反向索引。

下面我们用一个简单的例子描述一下倒排索引的作用过程:

假如现在有三份数据文档,内容分别是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Doc 1:Java is the best programming language

Doc 2:PHP is the best programming language

Doc 3:Javascript is the best programming language

为了创建索引,ES引擎通过分词器将每个文档的内容拆成单独的词(称之为词条,或term),再将这些词条创建成不含重复词条的排序列表,然后列出每个词条出现在哪个文档,结果如下:

term

Doc 1

Doc 2

Doc 3

Java

is

the

best

programming

language

PHP

Javascript

这种结构由文档中所有不重复的词的列表构成,对于其中每个词都有至少一个文档与与之关联。这种由属性值来确定记录的位置的结构就是倒排索引,带有倒排索引的文件被称为倒排文件。

将上表转为更直观的图片来展示倒排索引:

其中,几个核心术语需要着重理解:

  1. 词条(term):索引里面最小的存储和查询单元,对于英文来说是一个词,对于中文来说一般指分词后的一个词。
  2. 词典(Term Dictionary):也叫字典,是词条的组合。搜索引擎的通常索引单位是单词,单词词典是文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息以及指向倒排所有的指针。
  3. 倒排表(Post list):一个文档通常由多个词组成,倒排表记录的是某个词在哪些文档里出现过及出现的位置。每个记录称为一个倒排项(Posting),倒排表记录的不单单是文档编号,还记录了词频等信息。
  4. 倒排文件(Inverted File):所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件被称之为倒排文件,倒排文件是存储倒排索引的物理文件。

词典和倒排表是 Lucene这种很重要的两种数据结构,是实现快速检索的重要基石。词典和倒排文件是分两部分存储的,词典在内存中而倒排文件存储在磁盘。

1.3 Lucene

至于Lucene,直白地说,它就是一个jar包,封装好了各种建立倒排索引、匹配索引进行搜索的各种算法。我们可以引入Lucene,基于它的API进行开发。

ElasticSearch就在Lucene的基础上实现的,对Lucene进行了良好的封装,简化开发,并提供了很多高级功能。

ElasticSearch生态

ElasticSearch 为快速检索和分析大数据而生,目前已形成丰富的生态。

例如目前比较流行的ELK体系:

  • Elasticsearch是位于Elastic堆栈核心的分布式搜索和分析引擎。
  • LogstashBeats有助于收集、聚合和丰富数据,并将其存储在Elasticsearch中。
  • Kibana使您能够以交互方式探索、可视化和共享对数据的见解,并管理和监视堆栈。

1.4 ES基本概念

要了解 Elasticsearch ,首先要先了解下面的几个专有名词:索引(Index)、类型(Type)、文档(Document)、映射(mapping)

既然 Elasticsearch 能够存储和查询数据,那么我们自然要将其和最具知名度的数据库-Mysql进行一番对比,两者之间可以通过下表做一个并不非常严谨的类比,主要是为了方便理解。

Mysql

Elasticsearch

索引(Index)

库(Database)

类型(Type)

表(Table)

文档(Document)

行(Row)

字段(Field)

列(Column)

映射(Mappings)

表结构(schema)

  • Index:索引,相当于关系数据库中的database概念,是一类数据的集合,是一个逻辑概念。
  • Type:类型,相当于数据库中的table概念,在6.0版本之前,一个Index中可以有多个type,7.0版本后彻底废弃多type,每个索引只能有一个type,即“ _doc”。这个概念就不用太关注了。
  • Document:文档,存储在ES中的主要实体叫文档,可以理解为关系型数据库中表的一行数据记录。每个文档由多个字段(field)组成。区别于关系型数据库的是,ES是一个非结构化的数据库,每个文档可以有不同的字段,并且有一个唯一标识。
  • Field:字段,存在于文档中,字段是包含数据的键值对,可以理解为Mysql一行数据的其中一列。
  • Mapping:映射,是对索引库中的索引字段及其数据类型进行定义,类似于关系型数据库中的表结构。ES默认动态创建索引和索引类型的Mapping。

ES和Mysql直观对比:

1.5 ES集群概念

Elasticsearch 设计上是天然支持分布式的,下面我们了解一下集群相关概念。

  • cluster:集群,一个ES集群由多个节点(node)组成, 每个集群都有一个共同的集群名称最为标识。
  • node:节点,一个ES实例即为一个节点,一台机器可以有多个节点。
  • shard:分片,如果某个索引包含大量数据,以至于一台机器无法存储,ES可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。这样,ES就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个shard都是一个最小工作单元,承载部分数据,具有一个lucene实例和完整的建立索引、处理请求的能力。
  • replica:副本,就是shard的冗余备份,它可以防止数据丢失以及shard异常时负责容错和负载均衡

在实际生产中,ES通常与Mysql等存储系统联合使用,例如下面这个设计:

2 SpringBoot集成ES

Springboot集成ES非常方便,只要三步操作:

1、pom.xml添加依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<dependency>
	<groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.8.0</version>
</dependency>
<dependency>
	<groupId>org.elasticsearch.client</groupId>
	<artifactId>elasticsearch-rest-client</artifactId>
	<version>7.8.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.8.0</version>
</dependency>

2、application.yml增加配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
elasticsearch:
  host: 11.50.36.97
  port: 9200

3、新建config类:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
@Data
public class ESConfig {

    private String host;

    private Integer port;

    @Bean(destroyMethod = "close")
    public RestHighLevelClient client(){
        return new RestHighLevelClient(RestClient.builder(new HttpHost(host, port)));
    }
}

写个测试方法测试一下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoApplication.class)
@Slf4j
public class BasicTest {
    @Autowired
    private RestHighLevelClient client;

	 /**
     * 添加索引
     *
     * @throws IOException
     */
    @Test
    public void addIndex() throws IOException {
        //1.使用client获取操作索引对象
        IndicesClient indices = client.indices();
        //2.具体操作获取返回值
        //2.1 设置索引名称
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("person");

        CreateIndexResponse createIndexResponse = indices.create(createIndexRequest, RequestOptions.DEFAULT);
        //3.根据返回值判断结果
        System.out.println(createIndexResponse);
    }
    
    /**
     * 查询所有的索引
     *
     * @throws IOException
     */
    @Test
    public void indexTest() throws IOException {
        GetAliasesRequest request = new GetAliasesRequest();
        GetAliasesResponse alias = client.indices().getAlias(request, RequestOptions.DEFAULT);

        Map<String, Set<AliasMetadata>> map = alias.getAliases();
        map.forEach((k, v) -> {
            if (!k.startsWith(".")) {
                System.out.println(k);
            }
        });
    }
}

3 ElasticSearch安装

3.1 下载与安装

下载地址:https://www.elastic.co/cn/downloads/elasticsearch

安装:

1、将压缩包上传到linux服务器到特定目录,比如 /export/test

2、解压压缩包:tar -zxvf elasticsearch-7.13.2-linux-x86_64.tar.gz

ES目录介绍:

  • bin:可执行文件在里面,运行es的命令就在这个里面,包含了一些脚本文件等
  • config:配置文件目录
  • JDKjava环境
  • lib:依赖的jar,类库
  • logs日志文件
  • modules:es相关的模块
  • plugins:可以自己开发的插件
  • data:自建目录,后面要用,用来放置索引

3.2 修改配置

首先,我们需要做一些系统配置,要使用有权限的用户,例如root用户。

1、配置用户

因为root用户不能直接运行ES,所以新增一个用户(如果有非root用户,直接用也可以)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
useradd es
passwd es 
chown -R es elasticsearch

2、设置最大句柄数(nofile)和最大进程数(nproc):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vim /etc/security/limits.conf

在末尾追加内容(已有的话忽略):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
*        soft       nofile        65536
*        hard       nofile        65536
*        soft       nproc         4096
*        hard       nproc         4096

3、调整vm.max_map_count的大小

max_map_count文件包含限制一个进程可以拥有的VMA(虚拟内存区域)的数量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vim /etc/sysctl.conf

在文尾追加(已有的话则忽略此步):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vm.max_map_count=262144

执行以下命令使该配置生效:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
sysctl -p

接下来,切换到刚刚创建的用户,修改ES配置文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
su es
vim config/elasticsearch.yml

主要修改以下几项:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 1. 修改集群名称
cluster.name: test-es
# 2. 修改当前的es节点名称
node.name: node-1
# 3. 修改data数据保存地址(按自己的实际路径填写)
path.data: /export/test/elasticsearch-7.13.2/data
# 4. 日志数据保存地址(按自己的实际路径填写)
path.logs: /export/test/elasticsearch-7.13.2/logs
# 5. 绑定es网络ip
network.host: 0.0.0.0
# 6. 修改初始化master节点
cluster.initial_master_nodes: ["node-1"]

启动es服务:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cd bin
./elasticsearch

访问 http://192.168.1.13:9200/,出现以下信息,表示es启动成功。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "name" : "node-1",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "vMavXuuVTbmqykZpDEM0zQ",
  "version" : {
    "number" : "7.13.2",
    "build_flavor" : "default",
    "build_type" : "zip",
    "build_hash" : "4d960a0733be83dd2543ca018aa4ddc42e956800",
    "build_date" : "2021-06-10T21:01:55.251515791Z",
    "build_snapshot" : false,
    "lucene_version" : "8.8.2",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

设置后台启动:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
./bin/elasticsearch -d

3.3 配置Kibana

下载地址:https://www.elastic.co/cn/downloads/kibana

Kibana是Java应用,解压即可。解压后,进入文件目录的config目录中,编辑kibana.yml文件,修改该项:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 指向我们安装好的ES服务地址
elasticsearch.hosts: ["http://11.50.36.97:9200/"]

然后,进入bin目录,双击kibana.bat 即可启动。

以上是ElasticSearch基础的内容,后续将持续添加更多内容,敬请关注!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/10/30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
AsyncTask解析
需要进度更新: onPreExecute() --> doInBackground() --> publishProgress() --> onProgressUpdate() --> onPostExecute()
用户1205080
2019/04/25
6600
Android | AsyncTask基础梳理
AsyncTask. 异步任务 目的:方便后台线程中操作后更新UI 封装并简化了异步操作 实现:Thread和Handler进行了封装 实质:Handler异步消息处理机制 参数是泛型:<Params,Progress,Result> UI操作:onPreExecute,onPostExecute 后台线程操作 doInBackground 输入输出:Params(入),Result(出) 进度显示:onProgressUpdate ANR(Application Not Responding)
凌川江雪
2019/11/12
6340
Android查缺补漏(线程篇)-- AsyncTask的使用及原理详细分析
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8515304.html 一、AsyncTask的使用 AsyncTask是一种轻量级的异步任务类,可以很方便的在线程池中执行异步任务,并且将进度和结果传递给主线程。其底层由Thread+handler实现。 AsyncTask是一个抽象的泛型类,其类的声明如下: public abstract class AsyncTask<Params, Progress, Result> 其中三个泛型
codingblock
2018/03/30
1.1K0
锦囊篇|一文摸懂AsyncTask
一般我们在代码中只用执行excute()的函数,在各个函数流程中给出相对应的操作。
ClericYi
2020/07/24
4500
锦囊篇|一文摸懂AsyncTask
AsyncTask源码深入解析
最近想写一篇关于源码解析的文章,发现AsyncTask代码量不多,可里面的东西却是很值得学习的,所以故那这来“开刀”
HelloJack
2018/08/28
4520
AsyncTask源码深入解析
AsyncTask 使用及封装实践
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/57409326
程序员徐公
2018/09/18
9860
AsyncTask 使用及封装实践
Android AsyncTask实现原理和使用技巧分享
我们写App都有一个原则,主线程不能够运行需要占用大量CPU时间片的任务,如大量复杂的浮点运算,较大的磁盘IO操作,网络socket等,这些都会导致我们的主线程对用户的响应变得迟钝,甚至ANR,这些会使应用的用户体验变差,但是有时又的确需要执行这些耗时的任务,那么我们通常可以使用AsyncTask或者new Thread 来处理,这样把任务放入工作线程中执行,不会占用主线程的时间片,所以主线程会及时响应用户的操作,如果使用new Thread来执行任务,那么如果需要中途取消任务执行或者需要返回任务执行结果,就需要我们自己维护很多额外的代码,而AsyncTask是基于concurrent架包提供的并发类实现的,上面的二个需求都已经帮我们封装了,这也是我们选择AsyncTask的原因。
三好码农
2018/09/11
8230
【Android 异步操作】AsyncTask 异步任务 ( 参数简介 | 方法简介 | 使用方法 | AsyncTask 源码分析 )
AsyncTask 构造函数作用 : 创建一个新的异步任务 , 该构造函数必须在 UI 主线程调用 ;
韩曙亮
2023/03/28
9640
asynctask使用_androidstudiohelloworld教程
这是Google Android 开发文档上关于AsyncTask的介绍,大概意思是AsyncTask设计为一个对于Thread和Handle的辅助类,主要让开发者方便的使用UI Thread和后台Thread的操作( 比如在后台线程下载文件,同时要在UI线程更新下载进度 )。同时这不是一个通用的多线程编程框架,他被设计为用于能够在 最多几秒的时间内返回结果的任务。
全栈程序员站长
2022/08/04
3890
Android 多线程的几种方式
如果您的App没有明确指定屏幕方向和configChanges时,当用户旋转屏幕的时候Activity就会重新启动,而这个时候您的异步加载数据的线程可能正在请求网络。当一个新的Activity被重新创建之后,就又重新启动了一个新的任务去请求网络,这样之前的一个异步任务不经意间就泄露了,假设你还在onPostExecute写了一些其他逻辑,这个时候就会发生意想不到异常。
码客说
2019/10/22
8590
Android多线程:AsyncTask使用教程(含实例讲解)
前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 继承Thread类 实现Runnable接口 Handler AsyncTask HandlerThread 今天,我将献上一份AsyncTask使用教程,希望大家会喜欢 Carson带你学多线程系列 基础汇总 Android多线程:基础知识汇总 基础使用 Android多线程:继承Thread类使用(含实例教程) Android多线程:实现Runnable接口使用(含实例教程) 复合使用 Android多线程:As
Carson.Ho
2022/03/25
9380
Android多线程:AsyncTask使用教程(含实例讲解)
AsyncTask源码解析
导语 AsyncTask对Android开发者来说并不陌生,当有耗时任务并涉及UI交互,AsyncTask可是处理异步任务的利器。AsyncTask使用也很方便,开发的时候多留意不要内存泄漏,一般处理方法就是把AsyncTask写成静态内部类的形式。 使用方法 new AsyncTask<Integer, Integer, Boolean>() { private int NUM = 0; @Override protected void
用户1269200
2018/02/01
8370
Android 多线程-----AsyncTask详解
本篇随笔将讲解一下Android的多线程的知识,以及如何通过AsyncTask机制来实现线程之间的通信。
杨奉武
2018/09/27
6360
Android 多线程-----AsyncTask详解
【Android 电量优化】电量优化 ( JobScheduler | JobService | AsyncTask )
① 获取 JobScheduler 服务 : 从 Context 对象中 , 调用 getSystemService 方法跨进程获取 ;
韩曙亮
2023/03/28
1.4K0
Android 多线程:这是一份详细的AsyncTask使用教程
下面,我将用1个实例讲解 具体如何使用 `AsyncTask`
Carson.Ho
2019/02/22
1.4K1
安卓异步任务AsyncTask
       Android4.0之后,网络访问这些都是要放在自己开的线程里,然后在主线程里进行访问的。就我所知的有两种方法。一种是自己new一个线程,然后通过Handler机制进行访问;另外一种是用异步任务AsyncTask的方法。
SmileNicky
2019/01/17
5230
Android开发笔记(四十九)异步任务处理AsyncTask
Thread+Handler方式虽然能够实现多线程的通信处理,但是写起代码来颇为繁琐,所以Android提供了AsyncTask这样一个轻量级的异步任务类,其内部封装好Thread+Handler,方便了码农的工作,类似已封装好的多线程处理类还有IntentService(具体见《Android开发笔记(四十一)Service的生命周期》)。AsyncTask适用于HTTP通信,包括下载、http调用等等。 AsyncTask是个模板类(AsyncTask<Params, Progress, Result>),继承它的新类需要指定模板的参数类型,模板参数说明如下: Params : 任务启动时的输入参数,比如http访问的url、请求参数等等。可设置为String类型或者自定义的数据结构 Progress : 任务执行的进度。可设置为Integer类型 Result : 任务执行完的结果。可设置为String类型或者自定义的数据结构 下面是要重写的方法,不能直接调用: doInBackground : 异步处理操作都放在该方法中,params参数对应execute方法的输入参数。该方法运行于分线程,所以不能操作UI,其他方法都能操作UI onPreExecute : 在doInBackground执行之前调用 onProgressUpdate : doInBackground方法中调用publishProgress时会触发该方法,通常用于处理过程中刷新进度条 onPostExecute : 在doInBackground执行完毕时调用,通常用于处理完毕后刷新展示页面 onCancelled : doInBackground方法中调用cancel时会触发该方法 下面是可直接调用的方法: execute : 开始执行异步处理任务。 executeOnExecutor : 以指定线程池模式开始执行任务。THREAD_POOL_EXECUTOR表示异步线程池,SERIAL_EXECUTOR表示同步线程池。默认是SERIAL_EXECUTOR。 publishProgress : 更新进度。该方法只能在doInBackground方法中调用,调用后会触发onProgressUpdate方法。 cancel : 取消任务。该方法调用后,doInBackground的处理立即停止,并且接着调用onCancelled方法,而不会调用onPostExecute方法。 get : 获取处理结果。 getStatus : 获取任务状态。PENDING表示还未执行,RUNNING表示正在执行,FINISHED表示执行完毕 isCancelled : 判断该任务是否取消。true表示取消,false表示未取消
aqi00
2019/01/18
1.1K0
Android多线程-AsyncTaskyi(一)
今天分析android的异步线程类HandlerThread与IntentService,它们都是android系统独有的线程类,而android中还有另一个比较重要的异步线程类AsyncTask。本文我们就来分析AsyncTask。
用户9253515
2021/12/08
7310
android异步任务asyntask详解
在Android中实现异步任务机制有两种方式,Handler和AsyncTask。 Handler模式需要为每一个任务创建一个新的线程,任务完成后通过Handler实例向UI线程发送消息,完成界面的更新,这种方式对于整个过程的控制比较精细,但也是有缺点的,例如代码相对臃肿,在多个任务同时执行时,不易对线程进行精确的控制。关于Handler的相关知识,前面也有所介绍,不清楚的朋友们可以参照一下。 为了简化操作,Android1.5提供了工具类android.os.AsyncTask,它使创建异步任务变得
xiangzhihong
2018/01/30
1.1K0
android异步任务asyntask详解
AsyncTask和Handler对比
1 ) AsyncTask实现的原理,和适用的优缺点 AsyncTask,是android提供的轻量级的异步类,可以直接继承AsyncTask,在类中实现异步操作,并提供接口反馈当前异步执行的程度(可以通过接口实现UI进度更新),最后反馈执行的结果给UI主线程. 使用的优点: l  简单,快捷 l  过程可控 使用的缺点: l  在使用多个异步操作和并需要进行Ui变更时,就变得复杂起来. 2 )Handler异步实现的原理和适用的优缺点 在Handler 异步实现时,涉及到 Handler, Looper,
欢醉
2018/01/22
1.3K0
推荐阅读
相关推荐
AsyncTask解析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验