初识elasticsearch
概要#
此部分将零散的知识放在一起
es与relational DB#
elastcisearch是面向文档的,就意味着索引和搜索的数据最小的单位是文档。
关系型数据库 es 数据库 索引 indices 表 types 行 documents 字段 fields
下载地址与兼容性#
elastic中文社区提供的下载,该网站的下载速度特别快!!
不同的jdk对不同的ElastcSearch的兼容性是不一样的,详情可以查看官网,操作系统等兼容性问题,也可以在该网址中找到。
elasticsearch7.x默认包含jdk
端口#
es端口9200
kabana端口5601
es目录结构#
bin 启动文件 config 配置文件 log4j2 日志配置文件 jvm.options java虚拟机相关配置 elasticsearch.yml es的配置文件,默认9200端口 lib 相关jar包 logs 日志 modules 功能模块 plugins 插件
分片#
分片是 Elasticsearch 在集群中分发数据的关键。
把分片想象成数据的容器。文档存储在分片中,然后分片分配到集群中的节点上。当集群扩容或缩小,Elasticsearch 将会自动在节点间迁移分片,以使集群保持平衡。一个分片(shard)是一个最小级别“工作单元(worker unit)”,它只是保存了索引中所有数据的一部分。
分片有主分片和副本分片之分。
- 主分片:所以数据写入时都要到主分片中写入,主分片的数量决定了索引最多能存储多少数据。
- 副本分片:是主分片的一个副本,它可以防止硬件故障导致的数据丢失,同时可以提供读请求,比如搜索或者从别的 shard 取回文档
倒排索引#
倒排索引是搜索引擎的核心。搜索引擎的主要目标是在查找发生搜索条件的文档时提供快速搜索。ES中的倒排索引其实就是 lucene 的倒排索引,区别于传统的正向索引,倒排索引会再存储数据时将关键词和数据进行关联,保存到倒排表中,然后查询时,将查询内容进行分词后在倒排表中进行查询,最后匹配数据即可。
ik分词器#
在elasticsearch 中查询数据,使用了默认的分词器,分词效果不太理想。会把字段分成一个一个汉字,搜索时会把搜索到的句子进行分词,非常不智能,所以本次引入更为智能的IK分词器。
ik分词器有两种分词算法:ik_smart(最少切分)和ik_max_word(最细粒度划分)
- 安装
- github下载对应版本,点击这里,也可以在镜像网站中下载(上面有网址)
- 解压放到es的plugin目录下
unzip elasticsearch-analysis-ik-7.9.3.zip -d /opt/es7.9.3/plugin/ik
- 重启es
- 可以用
elasticsearch-plugin list
命令查看插件(在es/bin中)
- 测试(用kibana)
- ik_smart,通俗来说就是一个词往大了分,即一句话用断点分开,没有重复的部分。
返回值:GET _analyze { "analyzer": "ik_smart", "text": "逆水行舟" } { "tokens" : [ { "token" : "逆水行舟", "start_offset" : 0, "end_offset" : 4, "type" : "CN_WORD", "position" : 0 } ] } - ik_max_word,就是穷极词的组合,往细分。
返回值:GET _analyze { "analyzer": "ik_max_word", "text": "逆水行舟" } { "tokens" : [ { "token" : "逆水行舟", "start_offset" : 0, "end_offset" : 4, "type" : "CN_WORD", "position" : 0 }, { "token" : "逆水", "start_offset" : 0, "end_offset" : 2, "type" : "CN_WORD", "position" : 1 }, { "token" : "行舟", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 2 } ] } - 增加自定义词
ik分词器可能不能识别出某些词如:“张继科”等人名或我们的昵称等。所以需要我们手动添加词到词库中。- 在ik分词器config目录下创建一个字典:
vim /opt/elasticsearch-7.9.3/plugins/ik/config/name.dic
name.dic:
张继科 马龙 王皓 许昕 - 将字典放到ik分词器配置中:
vim /opt/elasticsearch-7.9.3/plugins/ik/config/IKAnalyzer.cfg.xml
IKAnalyzer.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>IK Analyzer 扩展配置</comment> <!--用户可以在这里配置自己的扩展字典 --> <entry key="ext_dict">name.dic</entry> <!--用户可以在这里配置自己的扩展停止词字典--> <entry key="ext_stopwords"></entry> <!--用户可以在这里配置远程扩展字典 --> <!-- <entry key="remote_ext_dict">words_location</entry> --> <!--用户可以在这里配置远程扩展停止词字典--> <!-- <entry key="remote_ext_stopwords">words_location</entry> --> </properties> - 在ik分词器config目录下创建一个字典:
创建索引时指定分词器
curl -X PUT "localhost:9200/user" -H "Content-Type: application/json" -d '{ "settings": { "analysis": { "analyzer": { "ik": { "tokenizer": "ik_max_word" } } } } }'
修改已经有的索引的分词器
方法:重新创建一个新的索引,设置好正确的 Mapping,再使用 reindex 将旧索引导入到新的索引里面去。
kibana#
kibana干什么的网上一堆介绍。
安装kibana
- 下载rpm包,根据在官网或镜像网站中下载
- 可以下载sha512文件检验:
sha512sum -c kibana-xxx.rpm.sha512
- rpm命令安装:
rpm -ivh kibana-7.4.0-x86_64.rpm
- 修改配置文件
配置文件:/etc/kibana/kibana.yml
。
关于配置文件主要看这个官方文档
-
- 启动kibana:
systemctl start kibana
kibana程序目录为/usr/share/kibana,其中:
plugins 为插件目录
bin 为执行文件目录
数据目录为/var/lib/kibana - 启动kibana:
-
- 自启动:
systemctl enable kibana
- 自启动:
-
- 防火墙:
firewall-cmd --add-port=5601/tcp --permanent
和firewall-cmd --reload
5601是默认端口,以自己的配置为准
- 防火墙:
REST风格#
rest是一种风格,es使用RESTful风格的接口:
method | url | 说明 |
---|---|---|
PUT | localhost:9200/索引名称/类型名称/文档id |
创建文档(指定id) |
POST | localhost:9200/索引名称/类型名称 |
创建文档(随机id) |
POST | localhost:9200/索引名称/类型名称/文档id/_update |
修改文档 |
DELETE | localhost:9200/索引名称/类型名称/文档id |
删除文档 |
GET | localhost:9200/索引名称/类型名称/文档id |
通过文档id查询数据 |
POST | localhost:9200/索引名称/类型名称/_search |
根据请求体条件查询数据 |
索引#
创建#
自动创建#
curl -X PUT "localhost:9200/user?pretty
创建一个userl的索引
pretty参数表示返回漂亮打印的JSON结果
- 在写入文档时,如果索引不存在,会自动创建索引
- 这种机制,使得我们无需手动定义mappings。Elasticsearch会自动根据文档信息,推算出字段的类型
- 有的时候,Elasticsearch可能会推算不对,如:地理位置信息
- 当类型推算得不对时,可能导致一些功能无法正常运行,如Range查询。
如果索引不存在时,创建一个文档,会自动创建一个索引。
自定义创建#
使用mapping,Mapping类似于关系型数据库的Schema,主要包含以下内容:
- 定义索引中字段的名称
- 定义字段的数据类型,如:字符串、数字、boolean等
- 可对字段设置倒排索引的相关配置,如是否需要分词,使用什么分词器
注意:从7.x开始,一个Mapping只属于一个索引的type 默认type 为:_doc
mapping的主要类型:
类型 | 具体类型 |
---|---|
字符串类型 | text、keyword |
数字类型 | long、integer、short、byte、double、float、half_float、scaled_float |
日期类型 | date、date_nanos |
布尔类型 | boolean |
二进制类型 | binary |
范围类型 | range |
点击这里查看所以字段的类型,以及字段的参数 |
text与keyword的区别:
- text
默认会进行分词,支持模糊查询(5.x之后版本string类型已废弃,请大家使用text)。 - keyword
不进行分词;keyword类型默认开启doc_values来加速聚合排序操作,占用了大量磁盘io 如非必须可以禁用doc_values。
text和keyword使用的分词器也不一样,text:
standard
而 keyword:keyword
,
可以使用GET _anlayze进行测试
关于嵌套数据类型和上面的类型的解释见:Elasticsearch 7.x 映射(Mapping)中的字段类型
7.x新增类型:
alias:并不实际存在,而是对已有字段的一种别名映射,搜索该字段与搜索实际字段返回的内容没有本质的区别。
date_nanos:另一种时间类型,可精确到纳秒,用法类似date。
features:用来存储特征向量,数据不能为0和负数,查询时只能使用rank_feature query,该字段主要为支持后续机器学习相关功能做准备。
vector:存储特征数组,支持稀疏与稠密向量存储,该字段主要为支持后续机器学习相关功能做准备。
- settings指定该索引的设置,定义不同的数据分布
- mappings定义文档字段的类型。
curl -X PUT "localhost:9200/user" -H "Content-Type: application/json" -d '{ "settings": { "number_of_shards": 3, "number_of_replicas": 2 }, "mappings": { "properties": { "name": { "type": "text" }, "age": { "type": "integer" }, "isteacher": { "type": "boolean" }, "createdate": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" } } } }'
number_of_shards指定索引的主分片,默认为1,指定之后不可以改
number_of_replicas指定索引的副本分片,默认为1,指定后可以修改
curl -X PUT "localhost:9200/user/_settings" -H "Content-Type: application/json" -d '{ "number_of_relicas": 2 }'
mapping还可以这样创建:
curl -X PUT "localhost:9200/user/_mapping" -H "Content-Type: application/json" -d '{ "properties": { "name": { "type": "text", "index": true }, "sex": { "type": "keyword", "index": true }, "tel": { "type": "keyword", "index": false } } }'
每个字段的参数
参数 | 说明 |
---|---|
index | 是否为索引,否的话不能直接查找该字段 |
type | 字段类型 |
doc_values | ture or false,列式存储,为支持快速聚合与排序场景而设计,不在该类场景的可禁用 |
ignore_malformed | 是否忽略脏数据,为true,数据格式或类型错误数据将被忽略,其它字段会正常插入;为false,一旦数据不符合要求整个文档将被拒绝。 |
更多见(包括settings的参数)此文elasticsearch简介和elasticsearch_dsl
使用python创建#
注意:指定analyzer需要自己安装,不再使用_doc
的形式创建索引,否则报错。
from elasticsearch import Elasticsearch # from elasticsearch import AsyncElasticsearch es = Elasticsearch(host="localhost", port=9200) # es = AsyncElasticsearch() body = { "settings": { "number_of_shards": 3, "number_of_replicas": 2 }, "mappings": { #"_doc": { "properties": { "id": { "type": "integer", }, "text": { "type": "text", # "analyzer": "ik_max_word", # 指定ik分词器,适用中文分词。 "index": False }, "userId": { "type": "long", }, "reprinted": { "type": "keyword", }, # } } } } # 创建 index es.indices.create(index="test", body=body)
指定分词器#
curl -X PUT "localhost:9200/user" -H "Content-Type: application/json" -d '{ "settings": { "analysis": { "analyzer": { "ik": { "tokenizer": "ik_max_word" } } } }, "mappings": { "properties": { "title": { "type": "text" }, "content": { "type": "text", "analyzer": "ik_max_word" } } } }
改#
curl -X PUT "localhost:9200/user/_mapping" -H "Content-Type: application/json" -d '{ "properties": { "name": { "type": "text", "index": true }, "sex": { "type": "keyword", "index": true }, "tel": { "type": "keyword", "index": false } } }'
ES 的索引一旦建立,对Mapping的修改只能新增字段,不能对Mapping中已有的字段进行修改、删除。在默认情况下,Mapping的动态映射Dynamic = true,会自动推测字段的类型并添加到Mapping中。
更多请查看此文:ES文档字段删除与索引重建。
查#
curl#
curl -X GET "localhost:9200/_cat/indices?v"
也可以:
curl -X GET "localhost:9200/index_name/ # index_name就是要查的索引名字,有的话就会返回
python#
from elasticsearch import Elasticsearch es = Elasticsearch(["127.0.0.1:9200"]) index_name = 'student' if es.indices.exists(index_name) == True: print('索引存在') else: print('索引不存在')
删除#
curl#
curl -X DELETE '127.0.0.1:9200/user'
python#
from elasticsearch import Elasticsearch es = Elasticsearch(["127.0.0.1:9200"]) es.indices.delete(index='student')
文档#
es是面向文档的,文档是小的可搜索单位,文档会被序列化为JSON格式,每个文档都有自己的Unique ID(自己指定或自动生成)
增加#
curl#
这种增加方式为幂等操作,所以用PUT。
curl -X PUT "localhost:9200/customer/_doc/1" -H 'Content-Type: application/json' -d'{ "name": "Jane Doe", "age": 20 } '
假如不指定id:"localhost:9200/customer/_doc/
则会自动生成id,为非幂等操作,使用POST。
curl:
curl -X POST "localhost:9200/customer/_doc/" -H 'Content-Type: application/json' -d'{ "name": "Jane Doe", "age": 20 } '
也可以使用:"localhost:9200/customer/_create/
创建:
curl -X PUT "localhost:9200/customer/_create/3" -H 'Content-Type: application/json' -d'{ "name": "Jane Doe", "age": 20 } '
python#
from elasticsearch import Elasticsearch index_name = 'my_index' es = Elasticsearch(['127.0.0.1:9200']) es.index(index=index_name, id='1', body={ 'name': '法外狂徒-张三', 'id': 1, } )
删除#
curl#
curl -X DELETE "localhost:9200/customer/_doc/2?pretty"
python#
from elasticsearch import Elasticsearch index_name = 'my_index' es = Elasticsearch(['127.0.0.1:9200']) es.delete(index=index_name, id=1)
修改#
curl#
修改的方式有两种,一是全量修改,二是局部更新。这两者的区别就是请求方式的不同,前者有PUT后者用POST,而且URL和请求体也不一样。
# 全量修改(即覆盖) curl -X PUT "localhost:9200/user/_doc/1?pretty" -H 'Content-Type: application/json' -d '{"name":"张三"}'
局部修改
curl -X POST "localhost:9200/user/_update/1?pretty" -H 'Content-Type: application/json' -d' { "script" : "ctx._source.age += 5" }' # ctx._source引用的是当前源文档 # 或者 curl -X POST "localhost:9200/user/_update/1?pretty" -H 'Content-Type: application/json' -d '{"doc":{"name":"张三"}}' # doc表示当前文档
python#
from elasticsearch import Elasticsearch index_name = 'my_index' es.update(index = index_name, id = 1, body = {"doc":{"name":"张三"}})
查#
可以使用这种方式查询:curl GET "localhost:9200/test/_search?q=name:lczmx"
,但不推荐,以json的形式更好。
主键查询:根据id查一条数据。
curl -X GET "localhost:9200/test/_doc/1?pretty"
假如想要全文查找,则需要使用curl -X GET "localhost:9200/test/_search"
,见DSL的内容。
DSL#
DSL是elasticsearch的一种查询语法,它是通过如下形式查找的:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} } } '
返回结果
形如:
{ "took" : 12, "timed_out" : false, "_shards" : { "total" : 3, "successful" : 3, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "test", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "name" : "lczmx" } } ] } }
took
: Elasticsearch执行搜索的时间(以毫秒为单位)timed_out
: 告诉我们检索是否超时_shards
: 告诉我们检索了多少分片,以及成功/失败的分片数各是多少hits
: 检索的结果hits.total
: 符合检索条件的文档总数hits.hits
: 实际的检索结果数组(默认为前10个文档)hits.sort
: 排序的key(如果按分值排序的话则不显示)hits._score
:匹配度,匹配度越高分值越高hits.max_score
现在我们先忽略这些字段
query查询
DLS使用query表示要如何查找,查找方式有一下几种。
精准查询term
term查询是直接通过倒排索引指定的词条进行精确查找。效率较高。
term
字段只有一个值时候,用term关键词查询
查询biz_id值为1909190023901225的记录
curl -XGET "localhost:9200/xyerp/order/_search" -H 'Content-Type: application/json' -d ' { "query": { "term": { "biz_id": "1909190023901225" } } }'
进一步优化查询,因为是精准查询,不需要查询进行评分计算,只希望对文档进行包括或排除的计算,所以我们会使用constant_score
查询以非评分模式来执行 term 查询并以一作为统一评分。推荐如下查询
curl -XGET "localhost:9200/xyerp/order/_search" -H 'Content-Type: application/json' -d ' { "query" : { "constant_score" : { "filter" : { "term" : { "biz_id" : "1909190023901225" } } } } }'
terms
字段有一多个值时候,用terms关键词查询,后跟数组。
curl -XGET "localhost:9200/xyerp/order/_search" -H 'Content-Type: application/json' -d ' { "query":{ "terms":{ "biz_id":["1909190023901225"] } } }'
term多个条件,使用bool
curl -XGET "localhost:9200/xyerp/order/_search" -H 'Content-Type: application/json' -d ' GET /account/_search { "query": { "bool": { "should": [ { "term": { "biz_id": "1909190023901225" } }, { "term": { "name": "lczmx" } } ] } } } '
constant_scorec查询
constant_score
以非评分模式查询,推荐如下查询。
{ "query" : { "constant_score" : { "filter" : { "terms" : { "biz_id" : ["1909190023901225","e1909190111365113"] } } } } }'
匹配查询match
match_all
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "_source": ["account_number", "balance"] } '
相当于:
SELECT account_number, balance FROM bank
match
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match": { "account_number": 20 } } } '
相当于:
SELECT * FROM bank WHERE account_number = 20
假如是字符串的话:
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match": { "address": "mill" } } } '
SELECT * FROM bank WHERE address LIKE '%mill%
注意:以空格隔开如{ "match": { "address": "mill link" }
,表示mill OR link
。,只要符合一个就可以查出,可以通过分数查看匹配程度。
multi_match
{ "query":{ "multi_match":{ "query":"2501", "fields":["merchant_id","_id"] } } }
match_phrase
表示的是完全匹配,只有一模一样的才能匹配上。
curl GET "localhost:9200/test/_search?pretty" -H "Content-Type: application/json" -d '{"query":{ "match_phrase":{"name": "lcz"}}}'
bool查询
bool查询包含四种操作符,分别是must,should,must_not,filter。它们均是一种数组,数组里面是对应的判断条件
must: 必须匹配,与and等价。贡献算分
must_not:必须不匹配,与not等价,常过滤子句用,但不贡献算分
should: 选择性匹配,至少满足一条,与 OR 等价。贡献算分
filter: 过滤子句,必须匹配,符合要求留下,不符合的过滤。但不贡献算分
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "should": [ { "match": { "address": "mill" } }, { "match": { "address": "lane" } } ] } } } ' # 要求address匹配上mill 或 lane
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "bool": { "must": [ { "match": { "address": "mill" } }, { "match": { "name": "lczmx" } } ] } } } ' # 要求同时满足address和name
bool和filter+range经常一起使用,见下小节例子
filter查询
过滤器,会查询对结果进行缓存,不会计算相关度,避免计算分值,执行速度非常快。
如下, 查询出status为active的状态
{ "query": { "bool": { "filter": { "term": { "status": "active" } } } } }
filter也常和range范围查询一起结合使用,range范围可供组合的选项
gt : 大于
lt : 小于
gte : 大于等于
lte :小于等于
如下,查询merchant_id值为2501下的交易数据
{ "query": { "bool": { "must": { "term": { "merchant_id": "2501" } }, "filter": { "range": { "trade_finished_time": { "from": "2019-09-01T00:00:00", "to": "2019-09-30T23:59:59" } } } } } }
如下查询,must下匹配,filter进行过滤,range定义范围
{ "query": { "bool": { "must": [ { "match": { "title": "Search" } }, { "match": { "content": "Elasticsearch" } } ], "filter": [ { "term": { "status": "1" } }, { "range": { "publish_date": { "gte": "2015-01-01" } } } ] } } }
sort排序
指定结果的排序方式
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "sort": [ { "age": { "order": "desc" } } ] } ' # 以account_number升序,desc为降序
由于我们手动排序了,所以其score为null
size、from分页
from参数(从0开始)指定从哪个文档索引开始,并且size参数指定从from开始返回多少条,分页时有用。
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "from": 10, "size": 10 } '
假如要分页的话:from = (页码 - 1) * 每页数据数
如:每页10条数据,则第2页的from为:(2 - 1) * 10 = 20
_source
限度返回数据
指定要返回那些数据。
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d' { "query": { "match_all": {} }, "_source": ["account_number", "balance"] } '
相当于:
SELECT account_number, balance FROM bank
aggs聚合函数
使用聚合函数。
需要指定聚合后的名字和使用哪个聚合函数。假如只需要统计数据的话,可以指定size
为0。
-
分组
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d'{ "aggs":{ "name_group": { "terms": { "field": "name" } } } }' # name_group只是一个自己取的名字 -
平均值
curl -X GET "localhost:9200/bank/_search" -H 'Content-Type: application/json' -d'{ "aggs":{ "name_avg": { "avg": { "field": "price" } } } }'
highlight高亮
指定哪些字段可以高亮显示。
curl GET "localhost:9200/test/_search?pretty" -H "Content-Type: application/json" -d '{ "query": {"match": { "name": "lczmx" }}, "highlight":{ "fields": { "name": {} } } }' # fields指定哪些字段高亮,字段的值为{}
默认为<em>lczmx</em>"
==> lczmx,我们可以指定标签前缀和后缀:
curl GET "localhost:9200/test/_search?pretty" -H "Content-Type: application/json" -d '{ "query": { "match": { "name": "lczmx" } }, "highlight": { "pre_tags": "<p class='key' style='color:red;'>", "post_tags": "</p>", "fields": { "name": {} } } }'
变为:<p class='name' style='color:red;'>lczmx</p>
==>
lczmx
利用python查询#
使用elasticsearch模块
调用search方法,body和dsl的语法一样,返回值是一个字典,和用curl、kibana等工具操作的返回值一样。
from elasticsearch import Elasticsearch es = Elasticsearch(host="192.168.43.128", port=9200) # 创建 index body = {"query": { "match_all": {}}, "from": 0, "size": 1 } res = es.search(index="account", doc_type="_doc", body=body) print(type(res)) # <class 'dict'> print(res.get("hits").get("hits")) # [{'_index': 'account', '_type': '_doc', '_id': '1', '_score': 1.0, '_source': {'name': 'lczmx', 'age': 22, 'birthday': '2020/12/22 12:22:39'}}]
elasticsearch_dsl模块
见我的另一篇文章python elasticsearch_dsl模块
集群#
es一个节点就是一个集群,默认为elasticsearch,es后台把每页的索引分成多个分片,每个分片可以在集群中的不同服务器之间迁移。
创建索引时会由5个分片(primary shard)构成,每个祝主分片会有一个副本(replica shard, 又称复制分片)
ES集群中的节点有三种不同的类型:
- 主节点:负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 主节点并不需要涉及到文档级别的变更和搜索等操作。可以通过属性node.master进行设置。
- 数据节点:存储数据和其对应的倒排索引。默认每一个节点都是数据节点(包括主节点),可以通过node.data属性进行设置。
- 协调节点:如果node.master和node.data属性均为false,则此节点称为协调节点,用来响应客户请求,均衡每个节点的负载,但每个节点就是不设置也可以隐性成为协调节点。
部署#
-
解压es
tar -zxvf elasticsearch-xxx.tar.gz -C /opt/module -
创建新用户
因为安全问题,Elasticsearch 不允许 root 用户直接运行,所以要创建新用户,在 root 用户中创建新用户 -
修改配置文件
ES 默认会加载位于 $ES_HOME/config/elasticsearch.yml 的配置文件。
备注:任何能够通过配置文件设置的内容,都可以通过命令行使用 -E 的语法进行指定,例如:./bin/elasticsearch -d -Ecluster.name=my_cluster -Enode.name=node_1 cluster.name
设置集群名称。一个节点只能加入一个集群中,默认的集群名称是 elasticsearch。cluster.name: search-7.3.2 node.name
可以配置每个节点的名称。用来提供可读性高的 ES 实例名称,它默认名称是机器的 hostname,可以自定义:node.name: node-1 同一集群中的节点名称不能相同
network.host
设置访问的地址。默认仅绑定在回环地址127.0.0.1
和[::1]
。建议设置为主机的公网 IP 或 0.0.0.0:network.host: 0.0.0.0 http.port
默认端口是 9200http.port: 9200 transport.port
集群中节点通信端口,范围:9300-9400。transport.port: 9300 注意:transport.tcp.xxx这种写法在es6开始就变为了transport.xxx,所以看网上的配置要识别
discovery.seed_hosts
发现设置。有两种重要的发现和集群形成配置,以便集群中的节点能够彼此发现并且选择一个主节点。如果要与其他主机上的节点组成集群,则必须设置 discovery.seed_hosts,用来提供集群中的其他主机列表。默认将绑定到可用的环回地址,并将扫描本地端口 9300 - 9305,所以其它主机需要配置。可以看看官方的说明:Discovery and cluster formation settings。discovery.seed_hosts: ["abc.com:9300","192.168.43.112:9301","127.0.0.1:9300""] cluster.initial_master_nodes
初始的候选 master 节点列表。需要确保cluster.initial_master_nodes 中的值与 node.name 完全匹配。
es选master的流程,开发时可以不指定该配置,有es自动完成,但可能会有故障。所以工作环境中需要指定。cluster.initial_master_nodes: ["node1", "node2"] - 在启动一个新的集群的时候需要有 cluster.initial_master_nodes 初始化集群主节点列表。
- 如果一个集群一旦形成,你不该再设置该配置项,应该移除它。
- 集群形成之后,就算保留,这个配置也会被忽略的!
- 该配置项并不是需要每个节点设置保持一致,设置需谨慎。若都设置了,当一个主节点关闭了,可能会导致其他主节点也会关闭!!因为一旦节点初始启动时设置了这个参数,它下次启动时还是会尝试和当初指定的主节点链接,当链接失败时,自己也会关闭!因此,为了保证可用性,预备做主节点的节点不用每个上面都配置该配置项!保证有的主节点上就不设置该配置项,这样当有主节点故障时,还有可用的主节点不会一定要去寻找初始节点中的主节点!
更多配置可以看这篇文章:ElasticSearch7.x 之 elasticsearch.yml详细配置
现在列出我的配置:
# es-node-1 cluster.name: es7 node.name: node-1 node.master: true node.data: false node.ingest: false network.host: 0.0.0.0 http.port: 9200 transport.port: 9300 discovery.seed_hosts: ["127.0.0.1:9300","127.0.0.1:9301","127.0.0.1:9302"] cluster.initial_master_nodes: ["node-1"] # es-node-2 cluster.name: es7 node.name: node-2 node.master: true node.data: true node.ingest: false network.host: 0.0.0.0 http.port: 9201 transport.port: 9301 discovery.seed_hosts: ["127.0.0.1:9300","127.0.0.1:9301","127.0.0.1:9302"] # es-node-3 cluster.name: es7 node.name: node-3 node.master: true node.data: true node.ingest: false network.host: 0.0.0.0 http.port: 9202 transport.port: 9302 discovery.seed_hosts: ["127.0.0.1:9300","127.0.0.1:9301","127.0.0.1:9302"] node-1 节点仅仅是一个 master 节点,它不是一个数据节点。
-
修改系统配置
启动时可能会报错,不报错可跳过这步。
修改/etc/security/limits.conf
:# 在文件末尾中增加下面内容 # 每个进程可以打开的文件数的限制 es soft nofile 65536 es hard nofile 65536 修改
/etc/security/limits.d/20-nproc.conf
:# 在文件末尾中增加下面内容 # 每个进程可以打开的文件数的限制 es soft nofile 65536 es hard nofile 65536 # 操作系统级别对每个用户创建的进程数的限制 * hard nproc 4096 # 注:* 带表 Linux 所有用户名称 修改
/etc/sysctl.conf
:# 在文件中增加下面内容 # 一个进程可以拥有的 VMA(虚拟内存区域)的数量,默认值为 65536 vm.max_map_count=655360 重新加载:
sysctl -p -
启动
cd /opt/module/es/ # 启动 bin/elasticsearch # 后台启动 bin/elasticsearch -d
配置信息#
elasticsearch.yml
属性名 | 说明 |
---|---|
cluster.name |
配置elasticsearch的集群名称,默认是elasticsearch。建议修改成一个有意义的名称。 |
node.name |
节点名,es会默认随机指定一个名字,建议指定一个有意义的名称,方便管理 |
path.conf |
设置配置文件的存储路径,tar或zip包安装默认在es根目录下的config文件夹,rpm安装默认在/etc/ elasticsearch |
path.data |
设置索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开 |
path.logs |
设置日志文件的存储路径,默认是es根目录下的logs文件夹 |
path.plugins |
设置插件的存放路径,默认是es根目录下的plugins文件夹 |
bootstrap.memory_lock |
设置为true可以锁住ES使用的内存,避免内存进行swap |
network.host |
设置bind_host和publish_host,设置为0.0.0.0允许外网访问 |
http.port |
设置对外服务的http端口,默认为9200。 |
transport.port |
集群结点之间通信端口 |
discovery.zen.ping.timeout |
设置ES自动发现节点连接超时的时间,默认为3秒,如果网络延迟高可设置大些 |
discovery.zen.minimum_master_nodes |
主结点数量的最少值 ,此值的公式为:(master_eligible_nodes / 2) + 1 ,比如:有3个符合要求的主结点,那么这里要设置为2 |
详细:
################################### Cluster ################################### #定义集群名称,默认是elasticsearch cluster.name: elasticsearch #################################### Node ##################################### #定义此节点名称 node.name: "node-1" #此节点是否为master,master作用就是做协调,协调集群的状态,数据的读取时由集群的各个节点共同完成的,但是数据的修改只能master完成 # 当前节点是否可以被选举为master节点,是:true、否:false node.master: true #此节点是否为子节点,功能就是存储数据,存储索引之类的,当前节点是否用于存储数据,是:true、否:false node.data: true #node.rack: rack314 #每个热/温/冷节点加入如下配置并重启服务 #这两项配置是为节点增加标签,具体名称并不是写死的,与后面模板和策略配置有关 node.attr.box_type: hot/warm/cold node.attr.rack: rack1 # 设置一台服务器能运行的节点数,一般为1就好,因为一般情况下一台机器只跑一个节点 #node.max_local_storage_nodes: 1 #################################### Index #################################### #注:ES7.×版本后不再支持定义索引属性 #定义索引分片的数量 #index.number_of_shards: 5 #定义副本的数量 #index.number_of_replicas: 1 #################################### Paths #################################### #定义配置文件的设置 #path.conf: /path/to/conf #定义索引数据存储的位置 #path.data: /path/to/data #path.data: /path/to/data1,/path/to/data2 #定义临时文件的位置 #path.work: /path/to/work # Path to log files: #定义日志文件的路径 #path.logs: /path/to/logs #定义插件的位置 #path.plugins: /path/to/plugins # 需求锁住物理内存,是:true、否:false bootstrap.memory_lock: false # SecComp检测,是:true、否:false bootstrap.system_call_filter: false #################################### Plugin ################################### #这个属性值为各个插件的名称,如果该值里的所列的插件没安装,则该节点不能启动,默认是没有插件 #plugin.mandatory: mapper-attachments,lang-groovy ################################### Memory #################################### #es在内存不够jvm开启swapping的时候,表现的会很差,所以为了避免这个问题,将概述性设置为true,表示锁定es所使用的内存 ############################## Network And HTTP ############################### #elasticsearch节点绑定的地址 #network.bind_host: 192.168.0.1 #elasticsearch和其他节点通信的地址,如果不设置的话 会自动获取 #network.publish_host: 192.168.0.1 # Set both 'bind_host' and 'publish_host': # #network.host: 192.168.0.1 network.host: 0.0.0.0 #设置节点之间通信的端口 #transport.port: 9300 #定义是否压缩tcp传输时的数据 #transport.compress: true #定义http传输监听的端口 # 主机访问的端口号 http.port: 9200 #设置http交互中传输内容的最大长度 #http.max_content_length: 100mb #是否启用http协议,如果不想让elasticsearch走http协议就设置为FALSE #http.enabled: false # 是否支持跨域,是:true,在使用head插件时需要此配置 http.cors.enabled: true # "*" 表示支持所有域名 http.cors.allow-origin: "*" ################################### Gateway ################################### #elasticsearch底层持久化,默认是走的本地,也可以设置为aws的s3 #gateway.type: local #控制集群在达到多少个节点之后才会开始数据恢复,通过这个设置可以避免集群自动相互发现的初期,shard分片不全的问题, #假如es集群内一共有5个节点,就可以设置为5,那么这个集群必须有5个节点启动后才会开始数据分片,如果设置为3,就有可能另外两个节点没存储数据分片 #gateway.recover_after_nodes: 1 #初始化数据恢复的超时时间,假如gateway.recover_after_nodes参数设置为5,就是5个节点全部启动后,再过5分钟开始数据恢复 #gateway.recover_after_time: 5m # Set how many nodes are expected in this cluster. Once these N nodes # are up (and recover_after_nodes is met), begin recovery process immediately # (without waiting for recover_after_time to expire): #启动几个节点后开始数据恢复,假如gateway.recover_after_nodes这个参数设置为5,那么等到这5个节点全部启动后直接可以数据恢复,不用等待gateway.recover_after_time设置的时间 #gateway.expected_nodes: 2 ############################# Recovery Throttling ############################# #设置一个节点的并发数量, #cluster.routing.allocation.node_initial_primaries_recoveries: 4 #cluster.routing.allocation.node_concurrent_recoveries: 2 # Set to throttle throughput when recovering (eg. 100mb, by default 20mb): #恢复数据时,限制的宽带流量,如果是0就是无限制 #indices.recovery.max_bytes_per_sec: 20mb #从其他分片恢复数据时,最大打开并发的值 #indices.recovery.concurrent_streams: 5 ################################## Discovery ################################## #1、在新版7.0的es中,对es的集群发现系统做了调整,不再有discovery.zen.minimum_master_nodes这个控制集群脑裂的配置, #转而由集群自主控制,并且新版在启动一个新的集群的时候需要有cluster.initial_master_nodes初始化集群列表。 #2、在es7中,discovery.zen.* 开头的参数,有些已经失效 #(旧) #设置这个集群,有多少个节点有master候选资格,如果集群较大官方建议为2-4个 #discovery.zen.minimum_master_nodes: 2 #es集群中自动发现其他节点的超时时间,如果网络延迟较大,建议设置长一点,防止误判 #discovery.zen.ping.timeout: 3s #是否打开多播协议 #discovery.zen.ping.multicast.enabled: false #设置集群中master集群初始化列表,这个数组里的机器将被自动发现加入集群 #discovery.zen.ping.unicast.hosts: ["host1", "host2:port"] #(新) # es7.x 之后新增的配置,写入候选主节点的设备地址,在开启服务后可以被选为主节点 # es7之后,不需要上面discovery.zen.ping.unicast.hosts这个参数,用discovery.seed_hosts替换 # discovery.zen.ping.unicast.hosts: ["10.19.1.9:9200","10.19.1.10:9200","10.19.1.11:9200"] discovery.seed_hosts: ["10.19.1.9:9200","10.19.1.10:9200","10.19.1.11:9200"] # es7.x 之后新增的配置,初始化一个新的集群时需要此配置来选举master #cluster.initial_master_nodes: [“node-1”] cluster.initial_master_nodes: ["node-1"] ################################## Slow Log ################################## # Shard level query and fetch threshold logging. #index.search.slowlog.threshold.query.warn: 10s #index.search.slowlog.threshold.query.info: 5s #index.search.slowlog.threshold.query.debug: 2s #index.search.slowlog.threshold.query.trace: 500ms #index.search.slowlog.threshold.fetch.warn: 1s #index.search.slowlog.threshold.fetch.info: 800ms #index.search.slowlog.threshold.fetch.debug: 500ms #index.search.slowlog.threshold.fetch.trace: 200ms #index.indexing.slowlog.threshold.index.warn: 10s #index.indexing.slowlog.threshold.index.info: 5s #index.indexing.slowlog.threshold.index.debug: 2s #index.indexing.slowlog.threshold.index.trace: 500ms ################################## GC Logging ################################ #monitor.jvm.gc.young.warn: 1000ms #monitor.jvm.gc.young.info: 700ms #monitor.jvm.gc.young.debug: 400ms #monitor.jvm.gc.old.warn: 10s #monitor.jvm.gc.old.info: 5s #monitor.jvm.gc.old.debug: 2s ################################## Security ################################ # Uncomment if you want to enable JSONP as a valid return transport on the # http server. With this enabled, it may pose a security risk, so disabling # it unless you need it is recommended (it is disabled by default). # #http.jsonp.enable: true
ES原理#
见我另一篇文章ElasticSearch原理(TODO)
参考:
【ES】ElasticSearch 深入分片
elasticsearch简介和elasticsearch_dsl
elasticsearch7常见查询(term、match、bool、filter)
Elasticsearch 7 : 添加和更新文档
ElasticSearch7.4学习之基础操作(增删改查)
这个博主有很多的elasticsearch的文章
ElasticSearch 7 教程(一整套的)
作者:忞翛
出处:https://www.cnblogs.com/lczmx/p/14979285.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
欢迎各位大佬评论交流。可以的话,不妨点一下推荐。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端