ElasticSearch

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

ElasticSearch

一、ES的概述

1. 介绍

    Elasticsearch是一个建立在全文搜索引擎 Apache Lucene™ 基础上的搜索引擎,可以说 Lucene 是当今最先进,最高效的全功能开源搜索引擎框架。它由Shay Banon开发并于2010年发布,现在是由Elasticsearch BV负责维护。Elasticsearch是一个实时分布式和开源的全文搜索和分析引擎。 它可以从RESTful Web服务接口访问,并使用JSON文档来存储数据。它是基于Java编程语言,这使Elasticsearch能够在不同的平台上运行。使用户能够以非常快的速度来搜索非常大的数据量。

2. 优点

  • Elasticsearch是基于Java开发的,这使得它在几乎每个平台上都兼容。
  • Elasticsearch是实时的,换句话说,一秒钟后,添加的文档可以在这个引擎中搜索得到。
  • Elasticsearch是分布式的,这使得它易于在任何大型组织中扩展和集成。
  • 通过使用Elasticsearch中的网关概念,创建完整备份很容易。 与Apache Solr相比,在Elasticsearch中处理多租户非常容易。
  • Elasticsearch提供了RESTful API接口(不管程序用什么语言开发,任何程序都可以访问)
  • Elasticsearch使用JSON对象作为响应,这使得可以使用不同的编程语言调用Elasticsearch服务器。
  • Elasticsearch支持几乎大部分文档类型。

3. 缺点

  • 在需要添加新数据与新字段的时候,如果ElasticSearch进行搜索是可能需要重新修改格式。之前的数据需要重新同步,对数据的管理有很多困难。
  • ES不是数据库,所以如果想要实现联表查询也会变得很麻烦。
  • ES不支持事物。

4. 使用场景

一般被拿来解决一些什么样的问题?

  • 数据库字段太多,查询太慢,索引没有办法再做优化;
  • 数据库一个count就拖死全表; 数据库的limit翻到几十几百万页后实在是太慢;
  • 数据库like实在太慢,每次like整个服务器cpu内存飙高,拖慢整个线上服务;
  • 想要对外/内提供db里的数据的全文检索服务;
  • 提供日志(程序运行)查询功能;

具体的使用场景

  • Stack Overflow(国外的程序异常讨论论坛),IT问题,程序的报错,提交上去,有人会跟你讨论和回答,全文检索,搜索相关问题和答案,程序报错了,就会将报错信息粘贴到里面去,搜索有没有对应的答案;
  • GitHub(开源代码管理),搜索上千亿行代码;
  • 电商网站,检索商品;
  • 日志数据分析,logstash采集日志,ElasticSearch进行复杂的数据分析(ELK技术,elasticsearch+logstash+kibana);

针对多表联查的场景,有两种解决方案:

  • 第一种:确定好要存入和显示的数据,在数据库层面先提前查询好,然后存入ES。例如:有两个表商品表和商品类别表,商品表中的商品类型在数据库中存的是id,往ES中就需要存储一个完整的数据,只需要一个索引即可。这样可以方便查询,两表只需在ES中查询一次即可。
  • 第二种:但是如果存在大批量的修改操作,数据库层面只需要一条sql语句即可修改,而在ES中需要修改多次。针对这种操作,就需要分开存储两个表在ES中(即在ES中开辟两个索引),这样查询数据需要查询两次,修改数据只需要修改一条数据即可。

5. 基本概念

5.1 Index(索引)

    Elastic 会索引所有字段,经过处理后写入一个反向索引(Inverted Index)。查找数据的时候,直接查找该索引。
    所以,Elastic 数据管理的顶层单位就叫做 Index(索引)。它是单个数据库的同义词。每个 Index (即数据库)的名字必须是小写。

5.2 Type(类型)

在 Index(索引)中,可以定义一个或多个类型。
类似于 数据库 的 Table,每一种类 型的数据存放在一起。
在这里插入图片描述
保存在某个 Index(索引)下,某种 Type(类型)的一个数据,Document(文档)是JSON格式的,Document 就像是 数据库 中某个 Table 里面每一行的数据,字段就是Document里的属性。

5.3 Document(文档)

保存在某个 Index(索引)下,某种 Type(类型)的一个数据,Document(文档)是JSON格式的,Document 就像是 数据库 中某个 Table 里面每一行的数据,字段就是Document里的属性。

6. 与数据库比较

在这里插入图片描述
在这里插入图片描述

7. 工作原理

一个集群至少有一个节点,而一个节点就是一个 Elasticsearch 进程,节点可以有多个默认索引,如果创建索引,那么索引将会有5个分片(primary shard 又称主分片)构成的,每一个主分片会有一个副本(replica shard 又称复制分片)。
在这里插入图片描述
上图是一个有3个节点的集群,主分片与对应的复制分片都不回在同一个节点内,这样有利于如果某个节点宕机,数据也不至于丢失。

实际上,一个分片就是一个 Lucene 索引,一个包含倒排索引的文件目录,倒排索引的结构使得 Elasticsearch 在不扫描全部文档的情况下,就能检索文档包含的特定关键字。

8. 倒排索引

Elasticsearch 使用的是一种称为倒排索引的结构,采用 Lucene 倒排索引作为底层。

这种结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。

例如,现在有两个文档,每个文档包含如下内容:

# 文档1包含的内容
Study every day, good good up to forever

# 文档2包含的内容
To forever, study every day, good good up

为了创建倒排索引,首先要将每个文档拆分成独立的词(或称为词条或者tokens),然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条出现在哪个文档。
在这里插入图片描述
如果搜索 to forever,只需查看包含每个词条的文档。
在这里插入图片描述
两个文档都匹配,但是第一个文档比第二个文档的匹配程度更高。

如果没有别的条件,这两个包含关键字的文档都将返回。

二、ES的安装部署

我们采用Docker容器来安装ES,首先需要安装Docker。

Docker中每一个容器都是独立运行的,相当于一个独立的linux系统,如果想便捷地修改容器内的文件,我们就需要把容器目录挂载到主机的目录上。容器端口类似,外界无法直接访问容器内部的端口,需要先将容器端口映射到linux主机端口上才能访问。
参考:Docker 安装文档

1. Linux安装Docker

1.1 删除老版本

sudo yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine

1.2 安装工具包并设置存储库

sudo yum install -y yum-utils

sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

1.3 安装docker引擎

sudo yum install docker-ce docker-ce-cli containerd.io

1.4 启动docker

sudo systemctl start docker

1.5 设置开机启动docker

#1. 检查docker版本
docker -v
#2. 查看docker已有镜像
sudo docker images
#3. 设置docker开机启动
sudo systemctl enable docker

1.6 设置国内镜像仓库

# 创建文件
sudo mkdir -p /etc/docker
# 修改配置, 设置镜像
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://vw9qapdy.mirror.aliyuncs.com"]
}
EOF

# 重启后台线程
sudo systemctl daemon-reload
# 重启docker
sudo systemctl restart docker

2. Docker安装Elasticsearch

2.1 下载镜像文件

# 存储和检索数据
docker pull elasticsearch:7.4.2

2.2 配置挂载数据文件夹

# 创建配置文件目录
mkdir -p /mydata/elasticsearch/config

# 创建数据目录
mkdir -p /mydata/elasticsearch/data

# 将/mydata/elasticsearch/文件夹中文件都可读可写
chmod -R 777 /mydata/elasticsearch/

# 配置任意机器可以访问 elasticsearch
echo "http.host: 0.0.0.0" >/mydata/elasticsearch/config/elasticsearch.yml

2.3. 启动Elasticsearch

命令后面的 \是换行符,注意前面有空格

docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e  "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v  /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2 
  • -p 9200:9200 -p 9300:9300:向外暴露两个端口,9200用于HTTP REST API请求,9300 ES 在分布式集群状态下 ES 之间的通信端口;
  • -e “discovery.type=single-node”:es 以单节点运行
  • -e ES_JAVA_OPTS="-Xms64m -Xmx512m":设置启动占用内存,不设置可能会占用当前系统所有内存
  • -v:挂载容器中的配置文件、数据文件、插件数据到本机的文件夹;
  • -d elasticsearch:7.6.2:指定要启动的镜像
    访问 IP:9200 看到返回的 json 数据说明启动成功。

2.4 设置 Elasticsearch 随Docker启动

# 当前 Docker 开机自启,所以 ES 现在也是开机自启
docker update elasticsearch --restart=always

三、配置图形界面

1. 配置可视化Kibana

1.1 下载镜像文件

# 可视化检索数据
docker pull kibana:7.4.2

1.2 启动可视化Kibana

docker run --name kibana \
-e ELASTICSEARCH_HOSTS=http://192.168.163.131:9200 \
-p 5601:5601 \
-d kibana:7.4.2

-e ELASTICSEARCH_HOSTS=http://192.168.163.131:9200 这里要设置成自己的虚拟机IP地址
浏览器输入192.168.163.131:5601 测试:

在这里插入图片描述

1.3 设置 Kibana 随Docker启动

# 当前 Docker 开机自启,所以 kibana 现在也是开机自启
docker update kibana --restart=always

四、ES使用入门

前面介绍说,Elasticsearch 都是通过 REST API 接口来操作数据的,那么下面接通过几个接口的请求来演示它的使用。

1. _cat 命令

1.1 查看所有节点

GET /_cat/nodes

在这里插入图片描述

1.2 查看ES健康状况

GET /_cat/health

在这里插入图片描述

1.3 查看主节点信息

GET /_cat/master

在这里插入图片描述

1.4 查看所有索引

GET /_cat/indices?v

在这里插入图片描述

2. 索引操作

2.1 查看所有的索引

GET /_cat/indices

在这里插入图片描述

2.2 添加索引

put /ems

在这里插入图片描述

2.3 删除索引

DELETE /ems

在这里插入图片描述

2.4 删除所有的索引(慎用)

DELETE /*

2.5 创建索引以及添加类型

es7去除了文档类型,默认是_doc,创建 ems/emp{name,age,birth}

PUT /ems
{
  "mappings": {
    "properties": {
      "id":{
        "type": "integer"
      },
      "name":{
        "type": "keyword"
      },
      "age":{
        "type": "integer"
      },
      "birth":{
        "type": "date"
      }
    }
  }
}

在这里插入图片描述

2.6 查看创建索引以及索引类型的映射

GET /ems  #可以查看到ems索引的所有信息
GET /ems/_mapping  #可以查看ems索引的映射信息

在这里插入图片描述

3. 文档操作

3.1 插入一条文档

插入一条文档put /索引/_doc/唯一id es7默认数据类型是doc

  • PUT添加文档需要携带id,如果存在该id则会进行修改操作,不存在则进行添加。
  • POST添加文档如果携带id会使用你带的id,不携带id则他会生成一个随机的id。id不存在则进行添加操作,否则进行修改操作。
PUT /ems/_doc/1
{
  "name":"张三",
  "age":24,
  "birth":"2021-04-26"
}

在这里插入图片描述

POST /ems/_doc/
{
  "name":"张三",
  "age":24,
  "birth":"2021-04-26"
}

在这里插入图片描述

3.2 查询文档中的一条记录

get/索引/_doc/文档id

GET /ems/_doc/1

在这里插入图片描述

3.3 根据id删除文档中一条记录

delete /索引/_doc/文档id

DELETE /ems/_doc/1

在这里插入图片描述

3.4 更新文档操作

delete /索引/_doc/文档id

#这种会删除原有数据,重新再次添加,会丢失数据。
POST /ems/_doc/1
{
  "name":"李四"
}

POST /ems/_doc/1
{
  "doc":{
    "name":"李四02"
  }
}

PUT /ems/_doc/1
{
  "doc":{
    "name":"李四03"
  }
}
#这种不会丢失数据,直接在原有的数据上修改
POST /ems/_update/1
{
  "doc":{
    "name":"李四"
  }
}

五、ES检索进阶

下面的请求都是在Kibana dev-tools 操作

1. DSL高级查询

1.1 查询所有的记录

GET /goods/_search
{
  "query": {
    "match_all": {}
  }
}

在这里插入图片描述

1.2 查询所有的记录并排序

GET /goods/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}

在这里插入图片描述

1.3 分页查询,每页记录数5个

GET /goods/_search
{
  "query": {
    "match_all": {}
  },
  "size": 5,
  "from": 0,
  "sort": [
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}

在这里插入图片描述

1.4 指定查询结果中返回指定字段

GET /goods/_search
{
  "query": {
    "match_all": {}
  },
  "_source": ["typeName","id"]
}

在这里插入图片描述

1.5 term 查询(基于关键字进行查询)

注意:text类型会进行分词,es默认使用的对于中文是单字分词器
例如小黑会拆分成小和黑,对于英文是按单词分.keywod、integer、date 不分词

1.5.1 查询出所有typeName包含java

GET /goods/_search
{
  "query": {
    "term": {
      "typeName": {
        "value": "java"
      }
    }
  }
}

在这里插入图片描述

1.6 范围查询价格大于等于100,小于等于200的商品

GET /goods/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 100,
        "lte": 200
      }
    }
  }
}

在这里插入图片描述

1.7 基于关键字的前缀查询,priex ,英文小写匹配大写,汉字只能单字匹配

GET /goods/_search
{
  "query": {
    "prefix": {
      "describe": {
        "value": "effective"
      }
    }
  }
}

在这里插入图片描述

1.8 通配符匹配? 用来匹配一个字符, * 匹配多个字符

GET /goods/_search
{
  "query": {
    "wildcard": {
      "describe": {
        "value": "*java*"
      }
    }
  }
}

在这里插入图片描述

1.9 基于多个id查询

GET /goods/_search
{
  "query": {
    "ids": {
      "values": [1386524724004339714,1386524723681378306]
    }
  }
}

在这里插入图片描述

1.10 模糊查询 fuzzy

GET /goods/_search
{
  "query": {
    "fuzzy": {
      "typeName": "cava"
    }
  }
}

在这里插入图片描述

模糊查询 fuzzy 做大模糊的错误必须在0-2之间
注意:搜索关键词长度为2,不允许存在模糊;如果你的长度在3-5之间允许一次模糊;如果你的长度大于5,最多允许的模糊在0-2之间

1.11 布尔查询 可以组合进行查询

#must:意味着条件都必须满足
#should:满足一个条件即可
#not must:必须不满足任何一个条件

GET /goods/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "typeName": {
              "value": "java"
            }
          }
        },
        {
          "term": {
            "describe": {
              "value": "零基础"
            }
          }
        }
      ]
    }
  }
}

1.12 多字段查询

#1)如果搜索的字段分词,他会对query进行先分词后搜索
#2).如果搜索的字段不分词,他会直接使用query整体进行搜索
#3).建议fields里放入可分词的字段
GET /goods/_search
{
  "query": {
    "multi_match": {
      "query": "java",
      "fields": ["typeName","describe"]
    }
  }
}

在这里插入图片描述

1.13 多字段分词查询

GET /goods/_search
{
  "query": {
    "query_string": {
      "default_field": "describe",
      "query": "冰箱"
    }
  }
}

在这里插入图片描述

1.14 过滤存在指定字段的文档

GET /goods/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match_all": {}
        }
      ],
      "filter": {
        "exists": {
          "field": "describe"
        }
      }
    }
  }
}

在这里插入图片描述

1.15 精确查询-基本数据类型(非文本)

# 查找匹配 price 为 98.0 的数据 非文本推荐使用 term
GET /goods/_search
{
  "query": {
    "match": {
      "price": "98.0"
    }
  }
}

在这里插入图片描述

1.16 模糊查询-文本字符串

# 查找匹配 typeName 包含 二手 的数据
#match即全文检索,对检索字段进行分词匹配,
#会按照响应的评分 _score 排序,原理是倒排索引。
GET /goods/_search
{
  "query": {
    "match": {
      "typeName": "二手"
    }
  }
}

在这里插入图片描述

1.17 精确匹配-文本字符串

# 查找 typeName 为 二手笔记本 的数据。
GET /goods/_search
{
  "query": {
    "match": {
      "typeName": "二手笔记本"
    }
  }
}

在这里插入图片描述

1.18 match_phrase-短语匹配

#将需要匹配的值当成一整个单词(不分词)进行检索
# 这里会检索 typeName 匹配包含短语 笔记本 的数据
GET /goods/_search
{
  "query": {
    "match_phrase": {
      "typeName": "笔记本"
    }
  }
}

在这里插入图片描述

1.19 term-精确检索

#精确查询typeName为java的
GET /goods/_search
{
  "query": {
    "term": {
      "typeName": {
        "value": "java"
      }
    }
  }
}

在这里插入图片描述

term用于精确检索(避免使用 term 查询文本字段) 非文本字段精确匹配推荐用term;

1.20 聚合操作

#聚合操作,搜索typeName中包含空调的所有商品的价格分布以及平均价格
#txt没法聚合 必须加.keyword精确替代
GET /goods/_search
{
  "query": {
    "match": {
      "typeName": "空调"
    }
  },
  "aggs": {
    "priceAgg": {
      "terms": {
        "field": "price",
        "size": 10
      }
    },
    "priceAvg":{
      "avg": {
        "field": "price"
      }
    }
  },
  "size": 0
}

#"aggs": {                               ---聚合关键字
#    "priceAgg": {                       ---聚合名为priceAgg(自定义)
#      "terms": {                        ---聚合类型为term
#        "field": "price",               ---聚合字段为price
#        "size": 10                      ---取聚合后前十个数据
#      }
#    },
#    "priceAvg":{                        ---聚合名为priceAvg(自定义)
#      "avg": {                          ---聚合类型为avg 求平均值
#        "field": "price"                ---聚合字段为price
#      }
#    }
#  },
#  "size": 0                             ---不显示命中结果,只看聚合信息

在这里插入图片描述

1.21 映射操作

1.21.1 创建索引映射
#创建索引并指定属性的映射规则(相当于新建表并指定字段和字段类型)
PUT /my_index
{
  "mappings": {
    "properties": {
      "age":{
        "type": "integer"
      },
      "email": {
        "type": "keyword"
      },
      "name": {
        "type": "text"
      }
    }
  }
}
1.21.2 给已有映射增加字段
#2.给已有映射增加字段
# 这里的 "index": false,表明新增的字段不能被检索。默认是true
PUT /my_index/_mapping
{
  "properties": {
    "employee-id": {
      "type": "keyword",
      "index": false
    }
  }
}

1.21.3 查看映射
#3.查看映射
GET /my_index/_mapping

#查看某一个字段的映射----查看email的映射
GET /my_index/_mapping/field/email

在这里插入图片描述

1.21.4 更新映射

对于已经存在的字段映射,我们不能更新。更新必须创建新的索引,进行数据迁移。
数据迁移方式:迁移方式分为两种,一种是7和7之后去掉type的情况,一种是包含type 迁移的情况。
对于我们的测试数据,是包含 type 的索引 my_index。
现在我们创建新的索引 newindex 并修改一些字段的类型来演示当需要更新映射时的数据迁移操作。

#1. 创建新的映射规则
PUT /newindex
{
  "mappings": {
    "properties": {
      "age":{
        "type": "integer"
      },
      "email": {
        "type": "text"
      },
      "name": {
        "type": "text"
      },
      "gender": {
        "type": "keyword"
      }
    }
  }
}
#2. 进行数据迁移
POST _reindex
{
  "source": {
    "index": "my_index"
  },
  "dest": {
    "index": "newindex"
  }
}

1.22 高亮搜索结果

#查询包含Java编程思想关键字的进行高亮显示
GET /goods/_search
{
  "query": {
    "match_phrase": {
      "describe": "Java编程思想"
    }
  },
  "highlight": {
    "pre_tags": ["<font color='red'>"],
    "post_tags": ["</font>"],
    "fields": {
      "describe": {}
    }
  }
  
}

在这里插入图片描述

1.23 批量查询并修改某个字段的值

#利用script脚本批量进行修改
POST /goods/_doc/_update_by_query
{
  "query": {
    "match_all": {}
  },
  "script": {
        "inline": "ctx._source['typeName'] = 'javc'"
  }
}

在这里插入图片描述

六、ES的分词器

1.1 为什么要是用分词器

Analyzer(分词器)的作用是把一段文本中的词按一定规则进行切分。默认的分词器一般都是针对于英文,

例如:whitespace tokenizer遇到空白字符时分割文本。它会将文本“Quick brown fox!”分割为[Quick,brown,fox!]。

对于中文我们需要安装额外的分词器来进行分词。否则中文会一个字一个字的进行拆分,非常不友好。

1.2 安装IK分词器

1.2.1 下载

IK 分词器属于 Elasticsearch 的插件,所以 IK 分词器的安装目录是 Elasticsearch 的 plugins 目录,在我们使用Docker启动 Elasticsearch 时,已经将该目录挂载到主机的 /mydata/elasticsearch/plugins 目录。
IK 分词器的版本需要跟 Elasticsearch 的版本对应,当前选择的版本为 7.4.2,下载地址为:Github Release 或访问:镜像地址

# 进入挂载的插件目录 /mydata/elasticsearch/plugins
cd /mydata/elasticsearch/plugins

# 安装 wget 下载工具
 yum install -y wget

# 下载对应版本的 IK 分词器(这里是7.4.2)
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip

这里已经在挂载的 plugins 目录安装好了 IK分词器。现在我们进入到 es 容器内部检查是否成功安装。

# 进入容器内部
docker exec -it elasticsearch /bin/bash

# 查看 es 插件目录
ls /usr/share/elasticsearch/plugins

# 可以看到 elasticsearch-analysis-ik-7.4.2.zip

所以我们之后只需要在挂载的目录/mydata/elasticsearch/plugins下进行操作即可。

1.2.2 解压

# 进入到 es 的插件目录
cd /mydata/elasticsearch/plugins

# 解压到 plugins 目录下的 ik 目录
unzip elasticsearch-analysis-ik-7.4.2.zip -d ik

# 删除下载的压缩包
 rm -f elasticsearch-analysis-ik-7.4.2.zip 

# 修改文件夹访问权限`在这里插入代码片`
chmod -R 777 ik/

1.2.3 查看安装的ik插件

# 进入 es 容器内部
docker exec -it elasticsearch /bin/bash

# 进入 es bin 目录
cd /usr/share/elasticsearch/bin

# 执行查看命令  显示 ik
elasticsearch-plugin list

# 退出容器
exit

# 重启 Elasticsearch
docker restart elasticsearch

#重启docker  
systemctl restart docker

1.2.4 测试ik分词器

首先测试默认的分词器

GET /_analyze
{
  "text": "我是王贝塔"
}

在这里插入图片描述
测试ik分词器的效果

GET _analyze
{
   "analyzer": "ik_smart", 
   "text":"我是王贝塔"
}

在这里插入图片描述
这里对于默认词库中没有的词,不会有词语的组合,所以我们可以通过配置自定义词库或远程词库来实现对词库的扩展。

1.2 自定义扩展分词库

现有ik分词器无法将这个词切分成一个关键词,但是又希望某个词成为关键词。例如:我想让王贝塔三个字不分开。
在这里插入图片描述

1.2.1 配置扩展词典

#进入ik的配置目录
cd /mydata/elasticsearch/plugins/ik/config

查看目录结构
在这里插入图片描述

#打开IKAnalyzer.cfg.xml 配置文件
vim IKAnalyzer.cfg.xml

在这里插入图片描述
我们将扩展文件写在ext_dict位置
在这里插入图片描述
因为需要utf-8编码,我们只需要拷贝一个当前文件夹下的文件然后进行修改

cp stopword.dic ext.dic

在这里插入图片描述

#然后在里面添加你需要分词的词语即可
vim ext.dic 

在这里插入图片描述

#之后重启ES服务
docker restart elasticsearch 

再次分词,结果如下:
在这里插入图片描述

同理不需要分词的内容,我们只需按照上面配置配置到stopext.dic中即可。
可在此处配置远程项目地址,实现动态修改。

七、相关配置

1. ES集群配置

在单台ES服务器节点上,随着业务量的发展索引文件慢慢增多,会影响到效率和内存存储问题等。

我们可以采用ES集群,将单个索引的分片到多个不同分布式物理机器上存储,从而可以实现高可用、容错性等。

ES集群中索引可能由多个分片构成,并且每个分片可以拥有多个副本。通过将一个单独的索引分为多个分片,我们可以处理不能在一个单一的服务器上面运行的大型索引,简单的说就是索引的大小过大,导致效率问题。不能运行的原因可能是内存也可能是存储。由于每个分片可以有多个副本,通过将副本分配到多个服务器,可以提高查询的负载能力。

此处我们以三台机器来搭建集群环境。

1.1 设置Elasticsearch挂载目录

#存放配置文件的文件夹
sudo mkdir -p /mydata/elasticsearch/node-1/config
sudo mkdir -p /mydata/elasticsearch/node-2/config
sudo mkdir -p /mydata/elasticsearch/node-3/config

#存放数据的文件夹
sudo mkdir -p /mydata/elasticsearch/node-1/data
sudo mkdir -p /mydata/elasticsearch/node-2/data
sudo mkdir -p /mydata/elasticsearch/node-3/data

#存放运行日志的文件夹
sudo mkdir -p /mydata/elasticsearch/node-1/log
sudo mkdir -p /mydata/elasticsearch/node-2/log
sudo mkdir -p /mydata/elasticsearch/node-3/log
#存放IK分词插件的文件夹
sudo mkdir -p /mydata/elasticsearch/node-1/plugins
sudo mkdir -p /mydata/elasticsearch/node-2/plugins
sudo mkdir -p /mydata/elasticsearch/node-3/plugins
#授予权限
sudo chmod 777 /mydata/elasticsearch/node-1/data
sudo chmod 777 /mydata/elasticsearch/node-2/data
sudo chmod 777 /mydata/elasticsearch/node-3/data

sudo chmod 777 /mydata/elasticsearch/node-1/plugins
sudo chmod 777 /mydata/elasticsearch/node-2/plugins
sudo chmod 777 /mydata/elasticsearch/node-3/plugins

sudo chmod 777 /mydata/elasticsearch/node-1/log
sudo chmod 777 /mydata/elasticsearch/node-2/log
sudo chmod 777 /mydata/elasticsearch/node-3/log

sudo chmod 777 /mydata/elasticsearch/node-1/config
sudo chmod 777 /mydata/elasticsearch/node-2/config
sudo chmod 777 /mydata/elasticsearch/node-3/config

1.2 生成目录结构

.
├── node-1
│   ├── config
│   │   └── elasticsearch.yml
│   ├── data
│   │   └── nodes
│   │       └── 0
│   │           ├── node.lock
│   │           └── _state
│   │               ├── manifest-3.st
│   │               ├── node-3.st
│   │               ├── _o.cfe
│   │               ├── _o.cfs
│   │               ├── _o.si
│   │               ├── segments_11
│   │               └── write.lock
│   ├── log
│   └── plugins
├── node-2
│   ├── config
│   │   └── elasticsearch.yml
│   ├── data
│   │   └── nodes
│   │       └── 0
│   │           ├── node.lock
│   │           └── _state
│   │               ├── manifest-4.st
│   │               ├── node-4.st
│   │               ├── _r.cfe
│   │               ├── _r.cfs
│   │               ├── _r.si
│   │               ├── segments_11
│   │               └── write.lock
│   ├── log
│   └── plugins
└── node-3
    ├── config
    │   └── elasticsearch.yml
    ├── data
    │   └── nodes
    │       └── 0
    │           ├── node.lock
    │           └── _state
    │               ├── manifest-1.st
    │               ├── _n.cfe
    │               ├── _n.cfs
    │               ├── node-1.st
    │               ├── _n.si
    │               ├── segments_11
    │               └── write.lock
    ├── log
    └── plugins


1.3 编写elasticsearch.yml配置文件

#进入es的node-1配置文件中
cd /mydata/elasticsearch/node-1/config/

#创建elasticsearch.yml配置文件
vi elasticsearch.yml

将下列配置添加到elasticsearch.yml中

#集群名称
cluster.name: my-es
#当前该节点的名称
node.name: node-1
#是不是有资格竞选主节点
node.master: true
#是否存储数据
node.data: true
#最大集群节点数
node.max_local_storage_nodes: 3
#给当前节点自定义属性(可以省略)
#node.attr.rack: r1
#数据存档位置
path.data: /usr/share/elasticsearch/data
#日志存放位置
path.logs: /usr/share/elasticsearch/log
#是否开启时锁定内存(默认为是)
#bootstrap.memory_lock: true
#设置网关地址,我是被这个坑死了,这个地址我原先填写了自己的实际物理IP地址,
#然后启动一直报无效的IP地址,无法注入9300端口,这里只需要填写0.0.0.0
network.host: 0.0.0.0
#设置其它结点和该结点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址,设置当前物理机地址,
#如果是docker安装节点的IP将会是配置的IP而不是docker网管ip
network.publish_host: 10.64.57.162
#设置映射端口
http.port: 9200
#内部节点之间沟通端口
transport.tcp.port: 9300
#集群发现默认值为127.0.0.1:9300,如果要在其他主机上形成包含节点的群集,如果搭建集群则需要填写
#es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点,也就是说把所有的节点都写上
discovery.seed_hosts: ["10.64.57.162:9300","10.64.57.162:9301","10.64.57.162:9302"]
#当你在搭建集群的时候,选出合格的节点集群,有些人说的太官方了,
#其实就是,让你选择比较好的几个节点,在你节点启动时,在这些节点中选一个做领导者,
#如果你不设置呢,elasticsearch就会自己选举,这里我们把三个节点都写上
cluster.initial_master_nodes: ["node-1","node-2","node-3"]
#在群集完全重新启动后阻止初始恢复,直到启动N个节点
#简单点说在集群启动后,至少复活多少个节点以上,那么这个服务才可以被使用,否则不可以被使用,
gateway.recover_after_nodes: 2
#删除索引是是否需要显示其名称,默认为显示
#action.destructive_requires_name: true
#进入es的node-2配置文件中
cd /mydata/elasticsearch/node-2/config

#创建elasticsearch.yml配置文件
vi elasticsearch.yml

将下列配置添加到elasticsearch.yml中

#集群名称
cluster.name: my-es
#当前该节点的名称
node.name: node-2
#是不是有资格竞选主节点
node.master: true
#是否存储数据
node.data: true
#最大集群节点数
node.max_local_storage_nodes: 3
#给当前节点自定义属性(可以省略)
#node.attr.rack: r1
#数据存档位置
path.data: /usr/share/elasticsearch/data
#日志存放位置
path.logs: /usr/share/elasticsearch/log
#是否开启时锁定内存(默认为是)
#bootstrap.memory_lock: true
#设置网关地址,我是被这个坑死了,这个地址我原先填写了自己的实际物理IP地址,
#然后启动一直报无效的IP地址,无法注入9300端口,这里只需要填写0.0.0.0
network.host: 0.0.0.0
#设置其它结点和该结点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址,设置当前物理机地址,
#如果是docker安装节点的IP将会是配置的IP而不是docker网管ip
network.publish_host: 10.64.57.162
#设置映射端口
http.port: 9201
#内部节点之间沟通端口
transport.tcp.port: 9301
#集群发现默认值为127.0.0.1:9300,如果要在其他主机上形成包含节点的群集,如果搭建集群则需要填写
#es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点,也就是说把所有的节点都写上
discovery.seed_hosts: ["10.64.57.162:9300","10.64.57.162:9301","10.64.57.162:9302"]
#当你在搭建集群的时候,选出合格的节点集群,有些人说的太官方了,
#其实就是,让你选择比较好的几个节点,在你节点启动时,在这些节点中选一个做领导者,
#如果你不设置呢,elasticsearch就会自己选举,这里我们把三个节点都写上
cluster.initial_master_nodes: ["node-1","node-2","node-3"]
#在群集完全重新启动后阻止初始恢复,直到启动N个节点
#简单点说在集群启动后,至少复活多少个节点以上,那么这个服务才可以被使用,否则不可以被使用,
gateway.recover_after_nodes: 2
#删除索引是是否需要显示其名称,默认为显示
#action.destructive_requires_name: true
#进入es的node-2配置文件中
cd /mydata/elasticsearch/node-3/config

#创建elasticsearch.yml配置文件
vi elasticsearch.yml

将下列配置添加到elasticsearch.yml中


#集群名称
cluster.name: my-es
#当前该节点的名称
node.name: node-3
#是不是有资格竞选主节点
node.master: true
#是否存储数据
node.data: true
#最大集群节点数
node.max_local_storage_nodes: 3
#给当前节点自定义属性(可以省略)
#node.attr.rack: r1
#数据存档位置
path.data: /usr/share/elasticsearch/data
#日志存放位置
path.logs: /usr/share/elasticsearch/log
#是否开启时锁定内存(默认为是)
#bootstrap.memory_lock: true
#设置网关地址,我是被这个坑死了,这个地址我原先填写了自己的实际物理IP地址,
#然后启动一直报无效的IP地址,无法注入9300端口,这里只需要填写0.0.0.0
network.host: 0.0.0.0
#设置其它结点和该结点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址,设置当前物理机地址,
#如果是docker安装节点的IP将会是配置的IP而不是docker网管ip
network.publish_host: 10.64.57.162
#设置映射端口
http.port: 9202
#内部节点之间沟通端口
transport.tcp.port: 9302
#集群发现默认值为127.0.0.1:9300,如果要在其他主机上形成包含节点的群集,如果搭建集群则需要填写
#es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点,也就是说把所有的节点都写上
discovery.seed_hosts: ["10.64.57.162:9300","10.64.57.162:9301","10.64.57.162:9302"]
#当你在搭建集群的时候,选出合格的节点集群,有些人说的太官方了,
#其实就是,让你选择比较好的几个节点,在你节点启动时,在这些节点中选一个做领导者,
#如果你不设置呢,elasticsearch就会自己选举,这里我们把三个节点都写上
cluster.initial_master_nodes: ["node-1","node-2","node-3"]
#在群集完全重新启动后阻止初始恢复,直到启动N个节点
#简单点说在集群启动后,至少复活多少个节点以上,那么这个服务才可以被使用,否则不可以被使用,
gateway.recover_after_nodes: 2
#删除索引是是否需要显示其名称,默认为显示
#action.destructive_requires_name: true

1.4 创建镜像

#创建镜像
docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d -p 9200:9200 -p 9300:9300 -v /mydata/elasticsearch/node-1/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /mydata/elasticsearch/node-1/plugins:/usr/share/elasticsearch/plugins -v /mydata/elasticsearch/node-1/data:/usr/share/elasticsearch/data -v /mydata/elasticsearch/node-1/log:/usr/share/elasticsearch/log --name es-node-1 elasticsearch:7.4.2



docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d -p 9201:9201 -p 9301:9301  -v /mydata/elasticsearch/node-2/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml  -v /mydata/elasticsearch/node-2/plugins:/usr/share/elasticsearch/plugins   -v /mydata/elasticsearch/node-2/data:/usr/share/elasticsearch/data -v /home/elasticsearch/node-2/log:/usr/share/elasticsearch/log --name es-node-2 elasticsearch:7.4.2




docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d -p 9202:9202 -p 9302:9302  -v /mydata/elasticsearch/node-3/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /mydata/elasticsearch/node-3/plugins:/usr/share/elasticsearch/plugins -v /mydata/elasticsearch/node-3/data:/usr/share/elasticsearch/data/ -v /mydata/elasticsearch/node-3/log:/usr/share/elasticsearch/log --name es-node-3 elasticsearch:7.4.2

1.5 验证集群结果

http://10.64.57.162:9201/_cat/nodes?pretty

在这里插入图片描述

注意:如果需要配置IK中文分词器,需要在每个节点的plugs文件夹下下载一个IK分词器,请参照IK分词器配置过程。

2. ElasticSearch分页搜索时会出现一下异常信息

Caused by: ElasticsearchException[Elasticsearch exception [type=illegal_argument_exception, reason=Result window is too large, from + size must be less than or equal to: [10000] but was [10285]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.]] 

这是因为ES默认支持的最大条数就是10000条,深度分页导致总条数超过10000,就会报这个错。我们可以根据业务进行相关调整。

###########配置ES默认支持的最大条数为15000############
PUT goods/_settings
{
  "index.max_result_window":15000
}

3. 配置集群中遇到的问题

OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
{"type": "deprecation", "timestamp": "2021-04-28T02:26:18,981Z", "level": "WARN", "component": "o.e.d.c.s.Settings", "cluster.name": "my-es", "node.name": "node-1", "message"                                    : "[transport.tcp.port] setting was deprecated in Elasticsearch and will be removed in a future release! See the breaking changes documentation for the next major version." }
{"type": "deprecation", "timestamp": "2021-04-28T02:26:19,056Z", "level": "WARN", "component": "o.e.d.c.s.Settings", "cluster.name": "my-es", "node.name": "node-1", "message"                                    : "[node.max_local_storage_nodes] setting was deprecated in Elasticsearch and will be removed in a future release! See the breaking changes documentation for the next major v                                    ersion." }
{"type": "server", "timestamp": "2021-04-28T02:26:19,185Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "node name                                     [node-1], node ID [hmFzzrNjRLu4kdFhMNYYgg], cluster name [my-es]" }
{"type": "server", "timestamp": "2021-04-28T02:26:19,185Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "version[7.                                    4.2], pid[1], build[default/docker/2f90bbf7b93631e52bafb59b3b049cb44ec25e96/2019-10-28T20:40:44.881551Z], OS[Linux/4.18.0-240.22.1.el8_3.x86_64/amd64], JVM[AdoptOpenJDK/OpenJ                                    DK 64-Bit Server VM/13.0.1/13.0.1+9]" }
{"type": "server", "timestamp": "2021-04-28T02:26:19,186Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "JVM home [                                    /usr/share/elasticsearch/jdk]" }
{"type": "server", "timestamp": "2021-04-28T02:26:19,186Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "JVM argume                                    nts [-Xms1g, -Xmx1g, -XX:+UseConcMarkSweepGC, -XX:CMSInitiatingOccupancyFraction=75, -XX:+UseCMSInitiatingOccupancyOnly, -Des.networkaddress.cache.ttl=60, -Des.networkaddress                                    .cache.negative.ttl=10, -XX:+AlwaysPreTouch, -Xss1m, -Djava.awt.headless=true, -Dfile.encoding=UTF-8, -Djna.nosys=true, -XX:-OmitStackTraceInFastThrow, -Dio.netty.noUnsafe=tr                                    ue, -Dio.netty.noKeySetOptimization=true, -Dio.netty.recycler.maxCapacityPerThread=0, -Dio.netty.allocator.numDirectArenas=0, -Dlog4j.shutdownHookEnabled=false, -Dlog4j2.disa                                    ble.jmx=true, -Djava.io.tmpdir=/tmp/elasticsearch-5133258163291923947, -XX:+HeapDumpOnOutOfMemoryError, -XX:HeapDumpPath=data, -XX:ErrorFile=logs/hs_err_pid%p.log, -Xlog:gc*,                                    gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m, -Djava.locale.providers=COMPAT, -Des.cgroups.hierarchy.override=/, -Xms512m, -Xmx512m, -Di                                    o.netty.allocator.type=unpooled, -XX:MaxDirectMemorySize=268435456, -Des.path.home=/usr/share/elasticsearch, -Des.path.conf=/usr/share/elasticsearch/config, -Des.distribution                                    .flavor=default, -Des.distribution.type=docker, -Des.bundled_jdk=true]" }

{"type": "server", "timestamp": "2021-04-28T02:26:24,126Z", "level": "INFO", "component": "o.e.x.s.a.s.FileRolesStore", "cluster.name": "my-es", "node.name": "node-1", "messa                                    ge": "parsed [0] roles from file [/usr/share/elasticsearch/config/roles.yml]" }
{"type": "server", "timestamp": "2021-04-28T02:26:24,543Z", "level": "INFO", "component": "o.e.x.m.p.l.CppLogMessageHandler", "cluster.name": "my-es", "node.name": "node-1",                                     "message": "[controller/105] [Main.cc@110] controller (64 bit): Version 7.4.2 (Build 473f61b8a5238b) Copyright (c) 2019 Elasticsearch BV" }
{"type": "server", "timestamp": "2021-04-28T02:26:24,909Z", "level": "DEBUG", "component": "o.e.a.ActionModule", "cluster.name": "my-es", "node.name": "node-1", "message": "U                                    sing REST wrapper from plugin org.elasticsearch.xpack.security.Security" }
{"type": "server", "timestamp": "2021-04-28T02:26:25,321Z", "level": "INFO", "component": "o.e.d.DiscoveryModule", "cluster.name": "my-es", "node.name": "node-1", "message":                                     "using discovery type [zen] and seed hosts providers [settings]" }
{"type": "server", "timestamp": "2021-04-28T02:26:25,928Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "initialize                                    d" }
{"type": "server", "timestamp": "2021-04-28T02:26:25,928Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "starting .                                    .." }
{"type": "server", "timestamp": "2021-04-28T02:26:26,023Z", "level": "INFO", "component": "o.e.t.TransportService", "cluster.name": "my-es", "node.name": "node-1", "message":                                     "publish_address {10.64.57.162:9300}, bound_addresses {0.0.0.0:9300}" }
{"type": "server", "timestamp": "2021-04-28T02:26:26,029Z", "level": "INFO", "component": "o.e.b.BootstrapChecks", "cluster.name": "my-es", "node.name": "node-1", "message":                                     "bound or publishing to a non-loopback address, enforcing bootstrap checks" }
ERROR: [1] bootstrap checks failed
[1]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
{"type": "server", "timestamp": "2021-04-28T02:26:26,035Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "stopping .                                    .." }
{"type": "server", "timestamp": "2021-04-28T02:26:26,047Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "stopped" }
{"type": "server", "timestamp": "2021-04-28T02:26:26,047Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "closing ..                                    ." }
{"type": "server", "timestamp": "2021-04-28T02:26:26,058Z", "level": "INFO", "component": "o.e.n.Node", "cluster.name": "my-es", "node.name": "node-1", "message": "closed" }
{"type": "server", "timestamp": "2021-04-28T02:26:26,060Z", "level": "INFO", "component": "o.e.x.m.p.NativeController", "cluster.name": "my-es", "node.name": "node-1", "messa                                    ge": "Native controller process has stopped - no new native processes can be started" }

解决办法:通过查看日志docker logs es-node-1 找到了

max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

这句话的意思是虚拟内存空间太小了,至少需要262144这么多,意思是elasticsearch拥有的内存权限太小,得扩大

#切换到root用户修改配置sysctl.conf
vi /etc/sysctl.conf


#添加下面配置:
vm.max_map_count=655360
#并执行命令
sysctl -p

然后重启ES的服务即可。

4. ES中的对象数组类型处理问题

对于对象以及数组类型的测试,ES中不会识别,会默认会将其进行扁平化处理。可能会造成数据查询的差异。

4.1 创建映射规则以及添加数据

PUT my-index-000001/_doc/1
{
  "group" : "fans",
  "user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

4.2 构建查询条件测试

下面这个查询需要搜索Alice Smith 很显然 我们两个条件都不满足,应该查询不出来数据,但是ES不认识数组和对象类型,会将其进行扁平化处理。

GET my-index-000001/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}

在这里插入图片描述

4.3 解决办法

#先删除映射
DELETE my-index-000001

#重新添加映射
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested" 
      }
    }
  }
}

再次添加数据进行测试

#添加数据
PUT my-index-000001/_doc/1
{
  "group" : "fans",
  "user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}
#查询first为Alice last为Smith的用户
GET my-index-000001/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}

在这里插入图片描述
此时就不会查询出结果了。

注意:数组和对象类型必须用nested类型,否则ES会将其进行扁平化处理,会造成查询的数据错乱。

八、测试与传统数据库检索对比

前提:事先准备好1W条数据表方便进行测试,本次测试数据13000条。

1. Oracle的全文索引

1.1 设置Oracle的全文索引

--设置词法分析器
--BEGIN
--ctx_ddl.create_preference ('goods_chinese_lexer', 'chinese_lexer');
--END;


--全文索引创建格式
--CREATE INDEX "indexname" ON "tablename" ("fieldname")
--INDEXTYPE IS "CTXSYS"."CONTEXT" PARAMETERS ('lexer cms_chinese_lexer sync(on commit)');

--为数据库表GOODS创建全文索引
--CREATE INDEX "GOODS_DESCRIBE_INDEX" ON "GOODS" ("DESCRIBE")
--INDEXTYPE IS "CTXSYS"."CONTEXT" PARAMETERS ('lexer cms_chinese_lexer sync(on commit)');

1.2 查询描述中包含java关键字的数据

select * from Goods where contains(describe,'java')>0

在这里插入图片描述

测试结果:最快11ms,最慢350ms。

2. ES的全文检索

前提:需要先将Oracle中的数据导入到ES中,13000条数据大概需要20多秒
在这里插入图片描述

2.1 查询描述中包含java关键字的数据

GET /goods/_search
{
  "query": {
    "match_phrase": {
      "describe": "java"
    }
  }
}

在这里插入图片描述

测试结果:最快0ms,最慢2ms。

代码测试删除1.3w数据 时间 3313ms 3s左右
代码测试添加1.3w数据 时间 60881ms 60s左右
代码测试更新1.3w数据 时间 2876ms 2s左右

九、ES数据同步方案

1. 同步双写

这是一种最为简单的方式,在将数据写到数据库时,同时将数据写到ES,实现数据的双写。

  • 优点:业务逻辑简单,好实现。
  • 缺点:硬编码,有需要写入数据库的地方都需要添加写入ES的代码;业务强耦合;存在双写失败丢数据风险;性能较差:本来数据库的性能就不是很高,再加写一个ES,系统的性能必然会下降。

说明:双写失败风险,包括以下3种:
ES系统不可用;应用系统和ES之间的网络故障;应用系统重启,导致系统来不及写入ES等。针对这种情况,有数据强一致性要求的,就必须双写放到事物中来处理,但是一旦用上事物,则性能下降更加明显。

2. 异步双写(MQ方式)

针对第一种同步双写的性能和数据丢失问题,可以考虑引入MQ,从而形成了异步双写的方案:由于MQ的性能基本比oracle高出一个数量级,所以性能可以得到显著的提高。

  • 优点:性能高;不存在丢数据问题。
  • 缺点:依然存在业务强耦合:依然存在复杂度增加:系统中增加了mq的代码,;可能存在时延问题:程序的写入性能提高了,但是由于MQ的消费可能由于网络或其它原因导致用户写入的数据不一定可以马上看到,造成延时。

3. 异步双写(Worker方式)

上面两种方案中都存在硬编码问题,也就是有任何对mysq进行增删改查的地方要么植入ES代码,要么替换为MQ代码,代码的侵入性太强。

如果对实时性要求不高的情况下,可以考虑用定时器来处理,具体步骤如下:

数据库的相关表中增加一个字段为timestamp的字段,任何crud操作都会导致该字段的时间发生变化;原来程序中的CURD操作不做任何变化;增加一个定时器程序,让该程序按一定的时间周期扫描指定的表,把该时间段内发生变化的数据提取出来;逐条写入到ES中。

  • 优点:不改变原来代码,没有侵入性、没有硬编码;没有业务强耦合;不改变原来程序的性能;Worker代码编写简单不需要考虑增删改查。
  • 缺点:时效性较差,由于定时器工作周期不可能设在秒级,所以实时性没有上面2中好;对数据库有一定的轮询压力,一种改进方法是将轮询放到压力不大的重库上。

4. 线程池实现异步双写

可以利用Completefuture来实现异步任务,让数据库的crud操作和ES操作异步执行。

Elasticsearch问题解决:unknown setting [xpack.security.transport.ssl.enabled] please check that any requi Elasticsearch问题解决:unknown setting [xpack.security.transport.ssl.enabled] please check that any required plugins are installed 今天有个小伙伴说Elasticsearch从高版本的java客户端换成原生的TransportClient后,连不上ES集群了,我查看并测试了这个问题。 一、查看现有集群信息 我使用他提供的ES集群链接信息,在服务器上看了一下集群的基本信息,发现es是7.10 阅读详情

相关推荐

ElasticSearch Linux单点和集群配置

Part4:ElasticSearch环境 4.1 相关概念 4.1.1 单机&集群 单台ElasticSearch服务器提供服务,往往都有最大的负载能力,超过这个阈值,服务器的性能就会大大降低甚至不可用,所以生产环境中,一般都是运行在指定服务器集群中。 除了负载能力,单点服务器也存在其他问题 单台机器存储容量有限 单服务器容易出现单点故障,无法实现高可用 单服务的并发处理能力有限 配置服务器集群时,集群中节点数量没有限制,大于等于2个节点就可以看做是集群了。一般出于高性能及高可用方面来考虑

qq_41649001的博客 771

elasticsearch.yml

centos7下面的ES(elasticsearch)安装的配置文件

828华为云征文|使用Flexus X实例集成ES搜索引擎

Flexus X实例是华为云推出的一款面向中小企业和开发者的柔性算力云服务器。Flexus X实例作为新一代云服务器,旨在为用户提供更加灵活和高效的计算资源管理方式。它具备多项独特优势,如柔性算力设计、智能感知业务负载、可灵活自定义vCPU内存配比等,以满足多样化的业务需求。包含有:柔性算力设计、智能感知业务负载、可灵活自定义vCPU内存配比、高性能、丰富的公共镜像、智能识别和全面的安全防护等特点,可以说是非常全面了

qq_53317005的博客 2094

记录安装ELK踩坑记录

记录下这次安装部署ELK踩坑记录 安装的elasticsearch是6.4.1,kibana-6.4.1 将elasticsearch-6.4.1.tar.gz上传的机器之后,解压,然后 # cd elasticsearch-6.4.1/bin //进入目录 # ./elasticsearch -d //启动es,-d是后台启动 # curl localhost:9200 //检验e...

nicodeme的专栏 1168

elasticsearch2.4.1安装配置中设置transport端口号无效

一开始设的三个节点的端口号分别为6666,6667,6668,单节点启动后日志显示的还是9300端口号后来发现 transport.tcpport 这条配置是无效的(看下图)只能在自动发现节点配三个默认的端口号9300,9301,9302,哪个节点先起来哪个就是9300(能用端口不被占就行)...

myCity_NJ 2839

详解最热门搜索引擎——ES

一、产生背景 ​ 互联网发展早期的时候,对于一般的公司储存的数据量不是那么的大,所以很多公司更倾向于使用数据库去存储和查询数据,如:现在去MySQL中查询数据,大概的查询方式就是:select * from table where filed like “%XXX%”或者其他方式,但是,如果我们在查询的时候没有用到或命中数据库建立的索引话,则会扫描整张表,即便是MySQL做过单表查询能力优化,但是他的极限也只在400万左右,且还会经常出现超时现象,让后为了解决这些问题,。很多公司就开始对数据库

会编程的小郑 1万+

Elasticsearch搜索引擎

本篇博客系统地介绍了Elasticsearch 7.14.0在windows环境下安装、基本使用、Springboot集成Elasticsearch以及ELK搭建。

weixin_44490884的博客 1496

Linux安装elasticsearch搜索引擎并配置

`-v es-plugins:/usr/share/elasticsearch/plugins`:挂载逻辑卷,绑定es的插件目录。- `-v es-data:/usr/share/elasticsearch/data`:挂载逻辑卷,绑定es的数据目录。- `-v es-logs:/usr/share/elasticsearch/logs`:挂载逻辑卷,绑定es的日志目录。- `--network es-net` :加入一个名为es-net的网络中,与elasticsearch在同一个网络中。

m0_74939895的博客 1763

ES(elasticsearch)搜索引擎 结合java 使用

ES(elasticsearch)搜索引擎 结合java 使用 官方文档地址: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/7.x/java-rest-high.html 重点概念: 文件索引块是因为使用了倒排索引 倒排索引: 例如 文件a 中有 单词 java php ,文件b中有 java php python ,文件c 中有java , python 那么 单词对应的文件为: java :a ,b,c

qq_42011565的博客 4757

ElasticSearch 认识和安装ES

es是一个分布式、高性能的搜索引擎,广泛应用于大数据检索、日志分析、实时搜索等场景。与传统数据库相比,ElasticSearch 对于大规模数据的处理具有显著优势,特别是模糊查询、分词分析、语义理解等复杂搜索任务。本章内容主要是介绍了 Elasticsearch 的基础知识、它的起源以及如何安装和配置 Elasticsearch 和 Kibana。安装过程中使用 Docker 是一种方便快捷的方式,可以轻松启动单机模式的 Elasticsearch 服务,并结合 Kibana 进行可视化操作。

2301_80093566的博客 1734

ES 分布式搜索引擎【一】

分布式搜索引擎elasticsearch、kibana、IK分词器的安装与使用。

m0_52861684的博客 1649

分布式搜索引擎elasticsearch基本使用3

因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。

weixin_43956070的博客 1383

分布式搜索引擎ES-elasticsearch入门

正排索引:相当于文档中的一条条记录;例子:汉语值得学习;汉语是语言;汉语学习视频;倒排索引:起源于实际应用中需要根据属性的值来查询记录。这种索引表的每一项都包括一个属性值和包含该属性值得各个记录地址。由于不是根据记录来确定属性,而是根据属性来确定记录的位置。可以记录文档的ids,词频跟位置例子:汉语值得学习;汉语是语言;汉语学习视频;单词文档ids词频TF;位置POS汉1,2,3语1,2,3值得11:1:<3>学习1,3是21:1;<3>言2。

TOMORROW6COME的博客 2014

ElasticSearch全文搜索引擎

Lucene是apache下的一个开源的全文检索引擎工具包(一堆jar包)。它为软件开发人员提供一个简单易用的工具包(类库),以方便的在小型目标系统中实现全文检索的功能。Lucene适用于中小型项目 ,ES适用于中大型项目(它底层是基于lucene实现的)虽然全文搜索领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。但是,Lucene只是一个库。

2201_75971147的博客 3202

elasticsearch(ES)简介及安装-----笔记

ES是一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容。ES结合kibana、Logstash、Beats,也就是elastic stack(ELK)。被广泛应用在日志数据分析、实时监控等领域。elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。kibana负责数据可视化,elasticsearch负责存储、计算、搜索数据,logstash\Beats负责数据抓取。elasticsearch底层实现是Lucene计术。

weixin_44846205的博客 2349

分布式搜索引擎elasticsearch基本使用1

什么是elasticsearch?一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能什么是elastic stack(ELK)?是以elasticsearch为核心的技术栈,包括beats、Logstash、kibana、elasticsearch什么是Lucene?是Apache的开源搜索引擎类库,提供了搜索引擎的核心API分词器的作用是什么?创建倒排索引时对文档分词用户搜索时,对输入的内容分词IK分词器有几种模式?ik_smart:智能切分,粗粒度。

weixin_43956070的博客 1252

分布式搜索引擎 elasticsearch

分布式搜索引擎 elasticsearch 第一部分 1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 例如: 在GitHub搜索代码 在电商网站搜索商品 在百度搜索答案 在打车软件搜索附近的车 1.1.2.ELK技术栈 elasticsearch结合kibana、Logstash、Beats,也就是elasti

KYGALYX的博客 3822
上一篇: LeeCode-24-两两交换链表中的节点
下一篇: ShardingSphere 分库分表
wangbeita
博客等级 码龄10年 9粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值