ElasticSearch集群安装及Java客户端使用
1、传统模式安装
1.1 ElasticSearch安装
下载Es安装包
ElasticSearch的官方地址:https://www.elastic.co/guide/en/elasticsearch/reference/master/index.html
1.2 ES图形化管理界面安装
- 下载head https://github.com/mobz/elasticsearch-head
- 下载Node.js https://nodejs.org/en/download 安装完成 在cmd窗口执行node -v查看node.js的版本号 检查是否安装成功
- 安装grunt
通过node.js的包管理器npm安装grunt为全局,grunt是基于Node.js的项目构建工具
npm install -g grunt-cli
4)执行 npm install (不执行该命宁 使用grunt server命令会报错)
npm install
5)elasticsearch-head解压目录下打开命宁窗口
执行 grunt server 启动服务
访问http://localhost:9100 (elasticsearch-head服务端口)
6、配置ElasticSearch跨域访问 修改 config/elasticsearch.yml 文件
代码语言:javascript复制http.cors.enabled: true
http.cors.allow-origin: "*"
需要重启ES服务
7、在head页面输入链接的ElasticSearch地址,点击连接按钮
2 容器化安装
2.1 ElasticSearch安装
这里使用docker docker compose 搭建Elasticsearch集群
2.1.1 环境准备
docker、docker-compose环境安装,参考官网安装:https://docs.docker.com/compose/install/
运行:
代码语言:javascript复制#docker安装
curl -sSL https://get.daocloud.io/docker | sh
#docker-compose安装
curl -L
https://get.daocloud.io/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m`
> /usr/local/bin/docker-compose
chmod x /usr/local/bin/docker-compose
#查看安装结果
docker-compose -v
2.1.2 创建elasticsearch
数据、日志存放目录
代码语言:javascript复制#创建数据/日志目录 这里我们部署3个节点
mkdir /root/app/elasticsearch/data/{node0,node1,node2} -p
mkdir /root/app/elasticsearch/logs/{node0,node1,node2} -p
cd /root/app/elasticsearch
#权限
chmod 0777 data/* -R && chmod 0777 logs/* -R
#防止JVM报错
echo vm.max_map_count=262144 >> /etc/sysctl.conf
sysctl -p
2.1.3 基于elasticsearch的官方镜像,制作一个集成了IK分词器的新镜像
Es默认的分词器,在中文的分词上并不友好,会将语句每个字进行分词作为索引,所以在使用Term关键字查询的时候多个汉字无法命中文档。这个时候就需要一个合理的分词规则,将一个完整的语句划分为多个比较复合表达逻辑的独立的词条。IK分词器在是一款基于词典和规则的中文分词器,所以这里将IK分词器集成到elasticsearch中。集成IK分词器有两种方式:
方式一: 执行docker exec命令进入容器,下载IK分词器zip包https://github.com/medcl/elasticsearch-analysis-ik/releases,然后解压复制到elasticsearch的插件目录,然后重启容器即可,但是这样需要在集群里的每个容器都执行一遍,后续容器销毁了,创建新的容器还需要重复来一遍,费事费力,果断放弃。
方式二: 基于elasticsearch的官方镜像,制作一个集成了IK分词器的新镜像,这样后续只要基于这个新镜像创建的新容器就自带了IK分词器,这里需要注意,由于elasticsearch每次版本变动比较大,所以在集成IK分词器时要注意版本对应
2.1.3.1 编写DockerFile
代码语言:javascript复制FROM docker.elastic.co/elasticsearch/elasticsearch:7.4.0
#作者
MAINTAINER GongLJ >
RUN sh -c '/bin/echo -e "y" | /usr/share/elasticsearch/bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.0/elasticsearch-analysis-ik-7.4.0.zip'
2.1.3.2 构建镜像
代码语言:javascript复制docker build --tag=elasticsearch-ik-custom:7.4.0 .
2.1.4 创建docker-compose编排文件
代码语言:javascript复制version: '2.2'
services:
es01:
image: elasticsearch-ik-custom:7.4.0
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- http.cors.enabled=true
- http.cors.allow-origin=*
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./data/node0:/usr/share/elasticsearch/data
- ./logs/node0:/usr/share/elasticsearch/logs
ports:
- 9200:9200
networks:
- elastic
es02:
image: elasticsearch-ik-custom:7.4.0
container_name: es02
environment:
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- http.cors.enabled=true
- http.cors.allow-origin=*
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./data/node1:/usr/share/elasticsearch/data
- ./logs/node1:/usr/share/elasticsearch/logs
networks:
- elastic
es03:
image: elasticsearch-ik-custom:7.4.0
container_name: es03
environment:
- node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- http.cors.enabled=true
- http.cors.allow-origin=*
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- ./logs/node2:/usr/share/elasticsearch/data
- ./logs/node2:/usr/share/elasticsearch/logs
networks:
- elastic
networks:
elastic:
driver: bridge
参数说明:
- 集群名称:cluster.name=es-docker-cluster
- 节点名称:node.name=es01
- 是否可作为主节点:node.master=true
- 是否存储数据:node.data=true
- 锁定进程的物理内存地址避免交换(swapped)来提高性能:bootstrap.memory_lock=true
2.1.4 创建并启动服务
代码语言:javascript复制#启动
docker-compose up -d
#查看
docker-compose ps
2.1.5 安装Head插件
可参考我的博客:博客地址 CSDN地址
ElasticSearch的相关概念
1 概述
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(ducoment)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之能搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、排序、过滤。Elasticsearch比传统关系型数据库如下。
代码语言:javascript复制关系型数据库 -> Databases -> Tables -> Rows -> Colums
ElasticSearch -> Indices -> Types ->Documents -> Fields
2 ElasticSearch的核心概念
2.1 索引 index
一个索引就是有相似特征的文档集合,比如用户数据索引、订单数据索引、商品数据索引。
一个索引由一个全为小写字母的名字标识,我们在对应这个索引文档中进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个群集中可以定义任意多个索引。
2.2 类型type
在一个索引中,你可以定义一个或多个类型,一个类型是你的索引的一个逻辑上的分类,其语义完全由你来定。通常,会为具有一组共同字段的文档定义一个类型,比如说,我们订单数据索引中我们把订单信息作为一个类型,订单相关的物流信息做为一个类型。
2.3 字段field
相当于是数据表的字段,对文档根据不同的属性进行的分类标识
2.4 映射 mapping (表结构)
mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其他的就是处理es里面的数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立隐射才能对性能更好。
2.5 文档 document
一个文档是一个可被索引的基础单元。文档以JSON格式来表示,而JSON是一个到处存在的互联网数据交互格式。
在一个index/type里面,你可以存储任意多的文档。
ElasticSearch基本操作
1 ElasticSearch语法
mapping字段详解
名称 | 作用描述 |
---|---|
type | 字段数据类型,可选值参考" type可选类型" |
analyzer | 指定分词器,一般使用最大分词:ik_max_word |
index | 该字段是否会被索引和可查询 默认true |
store | 默认情况false,其实并不是真没有存储,_source字段里会保存一份原始文档 |
normalizer | 字段标准化规则;如把所有字符转为小写 |
boost | 字段权重;用于查询时评分,关键字段的权重就会高一些,默认都是1;另外查询时可临时指定权重 |
coerce | 清理脏数据:1,字符串会被强制转换为整数 2,浮点数被强制转换为整数 |
copy_to | 自定_all字段;指定某几个字段拼接成自定义 |
doc_values | true 加快排序、聚合操作,但需要额外存储空间;默认true,对于确定不需要排序和聚合的字段可false |
dynamic | 默认true, #新字段动态添加 true:无限制 false:数据可写入但该字段不保留 ‘strict’:无法写入抛异常 |
enabled | 默认true, 是否会被索引,但都会存储;可以针对一整个_doc |
fielddata | 默认false,针对text字段加快排序和聚合.此项官网建议不开启,非常消耗内存 |
eager_global_ordinals | 默认true,是否开启全局预加载,加快查询;此参数只支持text和keyword,keyword默认可用,而text需要设置fielddata属性 |
format | 格式化 此参数代表可接受的时间格式"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" |
ignore_above | 100 指定字段索引和存储的长度最大值,超过最大值的会被忽略 |
ignore_malformed | 默认 false,插入文档时是否忽略类型 默认是false 类型不一致无法插入 |
index_options | docs . docs(索引文档号) freqs(文档号 词频) positions(文档号 词频 位置,通常用来距离查询) offsets(文档号 词频 位置 偏移量,通常被使用在高亮字段) |
fields | 可以对一个字段提供多种索引模式,使用text类型做全文检索,也可使用keyword类型做聚合和排序 |
norms | true 用于标准化文档,以便查询时计算文档的相关性。建议不开启 |
null_value | 可以让值为null的字段显式的可索引、可搜索 |
position_increment_gap | 0,词组查询时可以跨词查询 既可变为分词查询 默认100 |
properties | 嵌套属性,例如该字段是音乐,音乐还有歌词,类型,歌手等属性 |
search_analyzer | 查询分词器;一般情况和analyzer对应 |
similarity | 用于指定文档评分模型,参数有三个 BM25 : ES和Lucene默认的评分模型 classic: TF/IDF评分 boolean:布尔模型评分 |
term_vector | 默认 “no” ,不存储向量信息 yes : term存储 (term存储) with_positions (term 位置) with_offsets (term 位置) with_positions_offsets(term 位置 偏移量) 对快速高亮fast vector highlighter能提升性能,但开启又会加大索引体积,不适合大数据量用 |
type 可选类型
类型 | 具体值 |
---|---|
整数类型 | integer,long,short,byte |
浮点类型 | double,float,half_float,scaled_float |
逻辑类型 | boolean |
日期类型 | date |
范围类型 | range |
二进制类型 | binary |
数组类型 | array |
对象类型 | nested |
地理坐标类型 | geo_point |
地理地图 | geo_shape |
IP类型 | ip |
范围类型 | completion |
令牌计数类型 | token_count |
附件类型 | attachment |
抽取类型 | percolator |
2 通过HTTP请求创建
2.1 仅创建索引
请求方式选择 PUT
请求链接在URL一级目录输入需要创建的索引
比如我们船舰一个shop的索引
http://127.0.0.1:9200/shop
2.2 创建索引的同时创建mapping 以及分片复制参数
传入body参数执行
代码语言:javascript复制{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1,
"refresh_interval": "30s"
},
"mappings": {
"properties": {
"shopid": {
"type": "text",
"store": false,
"index": true
},
"shopname": {
"type": "text",
"store": false,
"index": true
},
"shopdesc": {
"type": "text",
"store": false,
"index": true
}
}
}
}
postman截图
4.2.3 删除索引库
请求方式选择Delete
请求链接如:http://127.0.0.1:9200/shop 删除shop索引
4.2.3 向索引库中添加文档
请求方式选 POST
单条插入:
请求url : http://127.0.0.1:9200/shop/_doc/1 (索引/"_doc"/文档id)
或者http://127.0.0.1:9200/shop/_doc
文档id为Es中的文档主键id,不指定的情况下Es会给我们生成一个唯一的随机字符串,如 BU7pG24Bm2YrPBUaN0wD
{
"shopid":"1234",
"shopname":"你的小店",
"shopdesc":"你的小店,只为喂饱你的胃"
}
postman截图
批量添加:
请求url: http://127.0.0.1:9200/shop/_bulk
代码语言:javascript复制{ "index":{} }
{ "shopid":"1234656","shopname":"fox" ,"shopdesc":"亲承5为自己生下5个孩子 此前12个" }
{ "index":{} }
{ "shopid":"1234657","shopname":"乒联" ,"shopdesc":"国际乒联奥地利公开赛正赛展开" }
{ "index":{"_id":"iikdjsd"} }
{ "shopid":"1234658","shopname":"纷纷两连败" ,"shopdesc":"两连败 二当家伤停再遭困境 考验欧文.." }
{ "index":{"_id":"iik3325"} }
{ "shopid":"1234659","shopname":"纷纷返回" ,"shopdesc":"33 9 4 5误!这是最乔治!黑贝最.." }
index可以指定参数,比如指定id,不指定则默认生成id
postman截图:
4.2.3 删除文档
请求方式选择Delete
请求url : http://127.0.0.1:9200/shop/_doc/1 (索引/"_doc"/文档id)
4.2.4 查询文档
请求方式选择Get
请求url : http://127.0.0.1:9200/shop/_doc/1 (索引/"_doc"/文档id)
4.2.5 修改文档
请求方式选择POST
请求url : http://127.0.0.1:9200/shop/_doc/1 (索引/"_doc"/文档id)
代码语言:javascript复制 {
"shopname":"fox"
}
4.2.6 根据关键词查询文档
请求方式选择Get
请求url http://127.0.0.1:9200/shop/_doc/_search (索引/"_doc"/"_search")
请求参数query、term为固定命宁,shopdesc为指定在哪个字段查询什么关键字(支持什么样的关键字查询取决于mapping里指定的分析器,比如单个字为索引、分词索引,之前测试的语句都是标准分词,以单个字为索引,所以查询的时候只支持一个汉字,如果输入多个则查询不到数据)
代码语言:javascript复制{
"query": {
"term": {
"shopdesc": "店"
}
}
}
postman截图
4.2.7 queryString查询
queryString是讲输入参数进行分词然后去索引库中检索。
请求方式选择Get
请求url http://127.0.0.1:9200/shop/_doc/_search
请求参数
代码语言:javascript复制{
"query": {
"query_string": {
"default_field": "shopname",
"query": "小店"
}
}
}
postman截图
4.2.8 分页查询
ElasticSearch IK中文分词器
1 什么是分词器?为什么要分词器?
在上面的学习例子中我们使用的是Es默认的分词器,在中文的分词上并不友好,会将语句每个字进行分词作为索引,所以在使用Term关键字查询的时候多个汉字无法命中文档。这个时候就需要一个合理的分词规则,将一个完整的语句划分为多个比较复合表达逻辑的独立的词条。
分词器包含三个部分:
- character filter:分词之前的预处理,过滤掉HTML标签、特殊符号转换(例如,将&符号转换成and、将|符号转换成or)等。
- tokenizer:分词
- token filter:标准化
2 ElasticSeach内置分词器
standard分词器:(默认的)它将词汇单元转换成小写形式,并去掉停用词(a、an、the等没有实际意义的词)和标点符号,支持中文采用的方法为单字切分(例如,‘你好’切分为‘你’和‘好’)。
simple分词器:首先通过非字母字符来分割文本信息,然后将词汇单元同一为小写形式。该分析器会去掉数字类型的字符。
Whitespace分词器:仅仅是去除空格,对字符没有lowcase(大小写转换)化,不支持中文;并且不对生成的词汇单元进行其他的标准化处理。
language分词器:特定语言的分词器,不支持中文。
3 IK分词器
3.1 IK分词器简介
IK分词器在是一款 基于词典和规则 的中文分词器,提供了两种分词模式:ik_smart (智能模式)和ik_max_word (细粒度模式)
输入数据
代码语言:javascript复制数据:IK Analyzer是一个结合词典分词和文法分词的中文分词开源工具包。它使用了全新的正向迭代最细粒度切分算法。
智能模式效果:
代码语言:javascript复制ik analyzer 是 一个 结合 词典 分词 和 文法 分词 的 中文 分词 开源 工具包 它 使 用了 全新 的 正向 迭代 最 细粒度 切分 算法
细粒度模式:
代码语言:javascript复制ik analyzer 是 一个 一 个 结合 词典 分词 和文 文法 分词 的 中文 分词 开源 工具包 工具 包 它 使用 用了 全新 的 正向 迭代 最 细粒度 细粒 粒度 切分 切 分 算法
3.2 使用ElasticSearch中的 analyze 测试Ik分词效果
请求方式 post
请求url http://127.0.0.1:9200/_analyze
请求参数:
代码语言:javascript复制{
"analyzer":"ik_smart",
"text":"我们是一群牛逼的程序员"
}
输出效果
代码语言:javascript复制{
"tokens": [
{
"token": "我们",
"start_offset": 0,
"end_offset": 2,
"type": "CN_WORD",
"position": 0
},
{
"token": "是",
"start_offset": 2,
"end_offset": 3,
"type": "CN_CHAR",
"position": 1
},
{
"token": "一群",
"start_offset": 3,
"end_offset": 5,
"type": "CN_WORD",
"position": 2
},
{
"token": "牛",
"start_offset": 5,
"end_offset": 6,
"type": "CN_CHAR",
"position": 3
},
{
"token": "逼",
"start_offset": 6,
"end_offset": 7,
"type": "CN_CHAR",
"position": 4
},
{
"token": "的",
"start_offset": 7,
"end_offset": 8,
"type": "CN_CHAR",
"position": 5
},
{
"token": "程序员",
"start_offset": 8,
"end_offset": 11,
"type": "CN_WORD",
"position": 6
}
]
}
ElasticSearch集群
1 集群 cluster
一个集群就是一个或多个节点组织在一起,他们共同持有整个库的数据,并在一起提供索引和搜索功能,一个集群由一个唯一的名字表示。所有节点通过这个集群名字,来进入这个集群。
2 节点node
一个节点是由集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的。一个节点可以通过配置集群名称的方式来加入一个指定的集群。
3 分片和复制 shard & replicas
分片:
一个索引可以存储超过单个节点硬件限制的大量数据,比如说一个索引具有10亿文档,占据1T的磁盘空间,而任意一个节点都没有这样大的一个磁盘空间;或者单个节点处理搜索请求,响应太慢了,为了解决这个问题,ElasticSearch提供了将索引划分为多份的能力,每一份就叫做一个分片。当建立一个索引的时候,可以指定想要分配的分片数量。每个分片本身也是一个功能晚上并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主要体现在两方面:a、允许你水平分割/扩展你的内容容量。2) 允许你在分片之上进行分布式并行操作,从而提高性能和吞吐量
至于分片怎么分布,查询结果怎么聚合,完全由elasticsearch管理的。开发者不需要关心。
复制:
在网络环境或者说分布式环境中,通讯发生失败是常有的事,所以当某个分片节点出现故障,故障转移机制是非常有必要的。因此Elasticsearch允许你船舰分片的一份或者多份拷贝,这些拷贝叫做复制分片,或者就叫复制。
复制的存在提高了节点出现故障时的集群高可用性。因为这个原因,复制分片应注意与主分片不能在同一个节点上。
总结的说,一个索引可以被分为多个分片,可以被复制0~N次,一旦复制了就有了主分片和复制分片之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,复制的数量可以改变,但是分片数量不能改变。
4 集群搭建
参考上面容器化集群搭建
5 节点的4中类型
主节点:
即 Master 节点。主节点的主要职责是和集群操作相关的内容,如创建或删除索引,跟踪哪些节点是群集的一部分,并决定哪些分片分配给相关的节点。稳定的主节点对集群的健康是非常重要的。默认情况下任何一个集群中的节点都有可能被选为主节点。索引数据和搜索查询等操作会占用大量的cpu,内存,io资源,为了确保一个集群的稳定,分离主节点和数据节点是一个比较好的选择。虽然主节点也可以协调节点,路由搜索和从客户端新增数据到数据节点,但最好不要使用这些专用的主节点。一个重要的原则是,尽可能做尽量少的工作。
数据节点:
即 Data 节点。数据节点主要是存储索引数据的节点,主要对文档进行增删改查操作,聚合操作等。数据节点对 CPU、内存、IO 要求较高,在优化的时候需要监控数据节点的状态,当资源不够的时候,需要在集群中添加新的节点。
预处理节点:
也称作 Ingest 节点,在索引数据之前可以先对数据做预处理操作,所有节点其实默认都是支持 Ingest 操作的,也可以专门将某个节点配置为 Ingest 节点。
以上就是节点几种类型,一个节点其实可以对应不同的类型,如一个节点可以同时成为主节点和数据节点和预处理节点,但如果一个节点既不是主节点也不是数据节点,那么它就是负载均衡节点。具体的类型可以通过具体的配置文件来设置。
节点类型 | 默认配置 | 专用节点 | 注意事项 |
---|---|---|---|
主节点 | node.master: true | node.master: true node.data: false node.ingest: false cluster.remote.connect: false | discovery.zen.minimum_master_nodes: 1(防止脑裂设置)意思是最少需要多少node.master: true 的节点集群才能工作建议(master_eligible_nodes / 2) 1比如能node.master: true节点有6个 (6/2) 1=4那么如果健康节点少于4集群将不能工作 |
数据节点 | node.data: true | node.master: false node.data: true node.ingest: false cluster.remote.connect: false | 建议使用SSD硬盘缓解I/O压力 |
预处理节点 | node.ingest | node.master: false node.data: false node.ingest: true cluster.remote.connect: false | 节点负载将会很高,建议使用专用节点作为Ingest node |
JAVA应用集成ElasticSearch客户端
Elasticsearch官方为Java提供了三种客户端API:
1、TransportClient:这种方式通过TCP与Elasticsearch服务进行交互。
2、Java Low Level REST Client: 低级别的REST客户端,通过http与集群交互,用户需自己编组请求JSON串,及解析响应JSON串。兼容所有ES版本。
3、Java High Level REST Client: 高级别的REST客户端,基于低级别的REST客户端,增加了编组请求JSON串、解析响应JSON串等相关api。使用的版本需要保持和ES服务端的版本一致,否则会有版本问题。
GitHub代码:Java客户端学习源码