Elasticsearch 是分布式、可扩展、实时的搜索与数据分析引擎,一般简称ES。
Elasticsearch 主要提供一下功能和特性:
Apache Lucene™
基础之上,提供了一个简单、连贯的 REST API,用于管理您的集群以及索引和搜索您的数据Elasticsearch是一个强大的分布式搜索和分析引擎,可以应用于许多场景。以下是一些常见的Elasticsearch应用场景:
总之,Elasticsearch非常适合需要强大搜索和分析功能的应用程序,并且可以应用于许多不同的场景,例如日志分析、业务智能、安全监控和实时数据处理等。
ELK是三个开源工具的缩写,分别是Elasticsearch、Logstash和Kibana。
这三个工具通常一起使用(经常还会配合Beats组件一起使用),作为完整的日志管理和分析解决方案。
Elasticsearch 官方文档 Set up Elasticsearch 介绍了不同场景下Elasticsearch的安装方式。
Kibana 官方文档 Set up 介绍了不同场景下Kibana的安装方式。
Elasticsearch 提供了Restful风格的API, 可以直接使用http客户端工具如curl
等直接操作数据。
但是就学习而言,使用可视化工具Kibana更便捷一些。
此处简单介绍通过Docker快速搭建Elasticsearch 和 Kibana的学习华景。
[windealli@VM-52-29-centos ~]$ docker network create elastic
[windealli@VM-52-29-centos ~]$ docker pull docker.elastic.co/elasticsearch/elasticsearch:7.17.9
[windealli@VM-52-29-centos ~]$ docker run -d --name es01-test --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.17.9
[windealli@VM-52-29-centos ~]$ docker pull docker.elastic.co/kibana/kibana:7.17.9
[windealli@VM-52-29-centos ~]$ docker run -d --name kib01-test --net elastic -p 5601:5601 -e "ELASTICSEARCH_HOSTS=http://es01-test:9200" docker.elastic.co/kibana/kibana:7.17.9
Elasticsearch中的概念可以类比关系型数据库MySQL:
Elasticsearch | 关系型数据库MySQL |
---|---|
索引 | 数据库 |
映射 | 表结构 |
文档 | 记录 |
字段 | 字段/列 |
集群和节点 | 集群和节点 |
分片 | 分片 |
DSL(基于JSON) | SQL |
打开Kibana的DevTool: http://127.0.0.1:5601/app/dev_tools#/console可以进行ES的基本操作
evernotecid://7D20C308-3D50-459D-A54D-B87FB1FC2C81/appyinxiangcom/11494076/ENResource/p1053
PUT /my_index_001
写入文档使用POST
请求,
单条写入:
POST /my_index_001/_doc
{
"user_id": 1001,
"user_name": "张三",
"company": "南山必胜客有限公司"
}
批量写入:
POST /_bulk
{"index": {"_index": "my_index_001"}}
{"user_id": 1002, "user_name": "李四", "company": "龙岗无敌手有限公司"}
{"index": {"_index": "my_index_001"}}
{"user_id": 1003,"user_name": "王五", "company": "龙岗无敌手有限公司", "age": 30}
在创建索引的时候,我们并没有定义索引的mapping, ES在写文档的时候会自动帮我们创建mapping, 并且我们插入的最后一个文档比前面两个文档多了一个额age
字段。
我们看下当前的索引mapping
// 请求:
GET /my_index_001/_mapping
// 应答:
{
"my_index_001" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"company" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"user_id" : {
"type" : "long"
},
"user_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
可以看出ES帮我们自动创建并拓展了索引的mapping。
但是,由于自动创建的mapping的字段类型等可能与我们的预期不一定一直,因此在实际应用中最好还是在创建索引的时候确认好mapping。
搜索用户名为张三的文档:
POST /my_index_001/_search
{
"query": {
"match": {
"user_name": "张三"
}
}
}
搜索公司名包含“必胜客”的文档,(ES中,中文按字进行分词)
POST /my_index_001/_search
{
"query": {
"match": {
"company": "必胜客"
}
}
}
根据文档id更新文档
POST /my_index_001/_update/s3Q1poYBVgNs6Cfh3Wc9
{
"doc": {
"user_name": "张三update"
}
}
根据条件更新文档
// 将缺少age字段的文档,填充age字段,设置值为20
POST /my_index_001/_update_by_query
{
"query": {
"bool": {
"must_not": {
"exists": {
"field": "age"
}
}
}
},
"script": {
"source": "ctx._source['age']=20",
"lang": "painless"
}
}
Elasticsearch 通过多节点的集群架构来保证系统的弹性拓展和高可用。
Elasticsearch 的节点按照功能角色可以分为三类:
节点的分类只是逻辑上的分类,比如在我们的单节点学习环境中,Master节点、数据节点和协调节点对应的都是同一个物理节点。
在生产环境中,可以分别给Master节点和协调节点专门指定一批物理节点,因此其架构如下图所示:
Elasticsearch 通过将数据按分片进行切分,以支持分布式搜索。
Elasticsearch 在创建索引是可以指定分片数和分片的副本数
PUT /my_index_002
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
}
}
下图是Elasticsearch分配的示意图
集群中包含:
文档写入时(假设向索引s_A写入文档),协调节点根据下面的公式先计算文档需要落在哪个分片:
shard=hash(routing)%number_of_primary_shards
routing代表每条文档提交时的参数,该值是可变的,用户可以自定义,在默认情况下使用的是文档的_id值;number_of_primary_shards是索引中主分片的个数。
得到分配ID:shard后,根据分配与节点的路由表,将文档数据转发给对应的节点。
与写入文档类似,获取文档同样是先计算分配ID,然后根据路由表得到对应分片(可以是主分片,也可以是副分片)的节点。
前面我们介绍Elasticsearch的基本使用时,有使用到了其搜索能力。强大搜索能力是Elasticsearch最重要的特性之一。
如果仅仅只是吧文档分片存储,在搜索时岂不是要全量扫描?其实并非如此, Elasticsearch基于Lucene和分析器两大组件来实现强大的搜索能力。
倒排索引其实就是根据字段值来映射记录(文档)的位置。以我们前面创建的三个文档为例。
文档ID | user_id | user_name | company | age |
---|---|---|---|---|
s3Q1poYBVgNs6Cfh3Wc9 | 1001 | 张三 | 南山必胜客有限公司 | 20 |
tHQ-poYBVgNs6Cfh72fO | 1002 | 李四 | 龙岗无敌手有限公司 | 20 |
tXQ-poYBVgNs6Cfh72fO | 1003 | 王五 | 龙岗无敌手有限公司 | 30 |
Lucene针对每一个字段建立倒排索引,以user_id为例:
Key(user_id) | Value(文档ID |
---|---|
1001 | s3Q1poYBVgNs6Cfh3Wc9 |
1002 | tHQ-poYBVgNs6Cfh72fO |
1003 | tXQ-poYBVgNs6Cfh72fO |
Lucene建立倒排索引时,会对Key进行排序,这样在搜索的时候就可以进行二分查找。(写入时排序相比关系型数据库,其写入速度比较慢,因此其在事务性、实时性要求高的场景下就不太适用。
模糊搜索与分词:
在搜素的场景中,除了进行全文匹配,经常还需要进行模糊搜索。
这就需要对字段的值进行分词。 在英文中,分词可以按照单次进行,在中文中,最简单的分词就是单字了。
以company为例:
Key(user_id) | Value(company ) |
---|---|
南 | s3Q1poYBVgNs6Cfh3Wc9 |
山 | s3Q1poYBVgNs6Cfh3Wc9 |
必 | s3Q1poYBVgNs6Cfh3Wc9 |
胜 | s3Q1poYBVgNs6Cfh3Wc9 |
客 | s3Q1poYBVgNs6Cfh3Wc9 |
有 | s3Q1poYBVgNs6Cfh3Wc9,tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
限 | s3Q1poYBVgNs6Cfh3Wc9,tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
公 | s3Q1poYBVgNs6Cfh3Wc9,tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
司 | s3Q1poYBVgNs6Cfh3Wc9,tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
龙 | tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
岗 | tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
无 | tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
敌 | tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
手 | tHQ-poYBVgNs6Cfh72fO,tXQ-poYBVgNs6Cfh72fO |
搜搜索时,会对每个文档ID根据匹配程度进行打分,排序。最后按照相关性返回。
Elasticsearch 官方文档
Elasticsearch搜索引擎构建入门与实战
ChatGPT