1. 简介
Elasticsearch 是一个功能强大的分布式搜索和分析引擎,具备快速的数据处理能力、高可用性、灵活的扩展性和丰富的查询功能,广泛应用于日志分析、实时搜索、数据分析和监控等领域。通过其分布式架构和弹性扩展性,它可以应对大数据量和高查询速度的需求。
2. 安装和设置
2.1 Elasticsearch安装
2.2 Kinaba安装
3. 基本概念
3.1index索引
一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引,另一个产品目录的索引,还有一个订单数据的索引。一个索引由一个名字来标识(必须全部是小写字母的),并且当我们要对对应于这个索引中的文档进行索引、搜索、更新和删除的时候,都要使用到这个名字。在一个集群中,可以定义任意多的索引。可类比mysql中表
3.2Filed字段
相当于是数据表的字段,对文档数据根据不同属性进行的分类标识 。
3.3映射mapping
mapping是处理数据的方式和规则方面做一些限制,如某个字段的数据类型、默认值、分析器、是否被索引等等,这些都是映射里面可以设置的,其它就是处理es里面数据的一些使用规则设置也叫做映射,按着最优规则处理数据对性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能对性能更好。相当于mysql中的创建表的过程,设置主键外键等等
3.4 document文档
一个文档是一个可被索引的基础信息单元。比如,你可以拥有某一个客户的文档,某一个产品的一个文档,当然,也可以拥有某个订单的一个文档。文档以JSON(Javascript Object Notation)格式来表示,而JSON是一个到处存在的互联网数据交互格式。在一个index/type里面,你可以存储任意多的文档。注意,尽管一个文档,物理上存在于一个索引之中,文档必须被索引/赋予一个索引的type。 插入索引库以文档为单位,类比与数据库中的一行数据
3.5 集群cluster
一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。一个集群由 一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集 群的名字,来加入这个集群。
3.6 节点node
一个节点是集群中的一个服务器,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。和集群类似,一 个节点也是由一个名字来标识的,默认情况下,这个名字是一个随机的漫威漫画角色的名字,这个名字会在启动的 时候赋予节点。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务器对 应于Elasticsearch集群中的哪些节点。
一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫 做“elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此, 它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。
在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何Elasticsearch节点, 这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。
3.7分片和复制 shards&replicas
一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。分片很重要,主要有两方面的原因: 1)允许你水平分割/扩展你的内容容量。 2)允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量。
至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由Elasticsearch管理的,对于作为用户的你来说,这些都是透明的。
在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。
复制之所以重要,有两个主要原因: 在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行。总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制的数量,但是你事后不能改变分片的数量。
默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。
4. 索引和查询数据
- 展示如何创建索引和映射。
创建索引
#创建了名字为orders的index,类似于mysql的table
PUT /orders
{
"mappings": {
"properties": {
"order_id": {
"type": "keyword"
},
"customer_name": {
"type": "text"
},
"order_date": {
"type": "date"
},
"total_amount": {
"type": "float"
},
"products": {
"type": "nested",
"properties": {
"product_id": {
"type": "keyword"
},
"product_name": {
"type": "text"
},
"price": {
"type": "float"
}
}
}
}
}
}
创建文档
#创建了doc,类似于mysql的行数据
POST /orders/_doc
{
"order_id": "123456789",
"customer_name": "John Doe",
"order_date": "2022-12-31T23:59:59",
"total_amount": 199.99,
"products": [
{
"product_id": "1",
"product_name": "Product A",
"price": 99.99
},
{
"product_id": "2",
"product_name": "Product B",
"price": 100
}
]
}
查询文档
GET /orders/_search
{
"query": {
"match_all": {}
}
}
5. 高级搜索功能
5.1全文搜索、精确搜索、模糊搜索和通配符搜索
- 全文搜索:假设你希望在 "customer_name" 字段中执行全文搜索,找到包含关键词 "John Doe" 的订单。你可以使用
match
查询来完成:
{
"query": {
"match": {
"customer_name": "John Doe"
}
}
}
这将返回所有 "customer_name" 字段中包含 "John" 或 "Doe" 单词的订单。
- 精确搜索:如果你希望根据订单的唯一标识符进行精确匹配搜索,可以使用
term
查询。以下是一个示例:
{
"query": {
"term": {
"id": "123456789"
}
}
}
这将仅返回与订单标识符为 "123456789" 完全匹配的订单。
- 模糊搜索:假设你想要模糊搜索顾客姓名字段,以找到拼写类似于 "John Doe" 的订单。你可以使用
fuzzy
查询来实现:
{
"query": {
"fuzzy": {
"customer_name": {
"value": "John Doe",
"fuzziness": "auto"
}
}
}
}
这将返回与 "John Doe" 相近的顾客姓名,考虑到拼写的相似性。
- 通配符搜索:如果你想要搜索以 "J" 开头的顾客姓名的订单,可以使用通配符搜索。以下是一个示例:
{
"query": {
"wildcard": {
"customer_name": "J*"
}
}
}
5.2 如何使用布尔查询、过滤器、聚合和排序来构建复杂的查询。
好的,让我们用 orders
这个示例来解释布尔查询、过滤器、聚合和排序的使用。
先增加properties和doc:
PUT /orders
{
"mappings": {
"properties": {
"id": {"type": "keyword"},
"customer_name": {"type": "text"},
"status": {"type": "keyword"},
"price": {"type": "float"},
"order_date": {"type": "date"}
}
}
}
POST /orders/_bulk
{ "index": { "_id": "1" } }
{ "id": "123456789", "customer_name": "John Doe", "status": "pending", "price": 100.00, "order_date": "2022-02-15" }
{ "index": { "_id": "2" } }
{ "id": "987654321", "customer_name": "Jane Smith", "status": "shipped", "price": 50.00, "order_date": "2022-03-01" }
{ "index": { "_id": "3" } }
{ "id": "456789123", "customer_name": "Bob Johnson", "status": "cancelled", "price": 33.00, "order_date": "2022-02-01" }
首先,我们来创建一个 index 和一个包含一些订单的示例数据:
PUT /orders
{
"mappings": {
"properties": {
"id": {"type": "keyword"},
"customer_name": {"type": "text"},
"status": {"type": "keyword"},
"price": {"type": "float"},
"order_date": {"type": "date"}
}
}
}
POST /orders/_bulk
{ "index": { "_id": "1" } }
{ "id": "123456789", "customer_name": "John Doe", "status": "pending", "price": 100.00, "order_date": "2022-02-15" }
{ "index": { "_id": "2" } }
{ "id": "987654321", "customer_name": "Jane Smith", "status": "shipped", "price": 50.00, "order_date": "2022-03-01" }
{ "index": { "_id": "3" } }
{ "id": "456789123", "customer_name": "Bob Johnson", "status": "cancelled", "price": 33.00, "order_date": "2022-02-01" }
现在,我们将使用以下示例查询、过滤器、聚合和排序对数据进行操作:
- 布尔查询:假设你想要查找价格在 100 之间的处于 "pending" 状态的订单,也就是要执行一个 "must" 和 "must" 的布尔查询,用于组合多个条件以获取更精确的结果。以下是一个示例查询:
{
"query": {
"bool": {
"must": [
{
"range": {
"price": {
"gte": 20,
"lte": 100
}
}
},
{
"match": {
"status": "pending"
}
}
]
}
}
}
这将在满足价格在 100,以及状态为 "pending" 的订单中搜索。
- 过滤器:假设你想要查找订单日期在 2022 年 2 月份的订单,也就是按照日期进行查询。这个时候我们可以用过滤器来实现:
{
"query": {
"bool": {
"filter": {
"range": {
"order_date": {
"gte": "2022-02-01",
"lte": "2022-02-28"
}
}
}
}
}
}
这将筛选出日期在 2022 年 2 月份的订单。
- 聚合:假设你想要按照顾客名字将订单分组,计算每个顾客的平均订单总价和最大订单总价。以下是一个示例聚合:
{
"size": 0,
"aggs": {
"customer_orders": {
"terms": {
"field": "customer_name"
},
"aggs": {
"avg_order_total": {
"avg": {
"field": "price"
}
},
"max_order_total": {
"max": {
"field": "price"
}
}
}
}
}
}
这将按顾客名称聚合订单,并计算每个顾客的平均和最大订单总价。
- 排序:假设你想要以价格降序对订单进行排序。你可以在查询中添加一个 "sort" 参数来实现:
{
"query": {
"match_all": {}
},
"sort": [
{ "price": { "order": "desc" } }
]
}
这将按价格降序排序所有订单。
可以看到,使用 Elasticsearch 的查询、过滤器、聚合和排序等功能可以构建复杂的查询,提高数据检索效率和准确性。这里仅提供了一些简单的示例,实际应用需要根据不同的场景和需求进行不
6. 搜索优化
6.1 - 介绍如何使用索引优化器和分析器来提升搜索的性能。
6.2 内存配置
当为 Elasticsearch 分配内存时,需要考虑多个因素,如数据量、索引结构、查询需求等。下面是根据不同场景建议的分配策略:
- 全文搜索场景:
对于小规模或中等规模的索引(例如数百万条文档),建议将 Elasticsearch 堆内存分配为整个可用内存的 50% ~ 75%。这将允许 Elasticsearch 建立足够的缓存,以提供高效的索引和查询性能。在这种情况下,需要考虑避免存储过多的数据,以免触发 JVM 的 GC。
对于大规模的索引(例如数千万条文档),由于内存资源有限,建议对 Elasticsearch 堆内存进行更小的配置(例如设置为整个可用内存的 25% ~ 50%)。此时,需要使用更多的硬盘 I/O 和操作系统缓存来补充内存不足的情况。对于此类场景,建议使用 SSD 以提高磁盘操作的性能。
- 聚合和排序场景:
对于仅基于数字和日期字段的聚合和排序操作,可以将 Elasticsearch 堆内存设置为较小的值(例如 2GB ~ 4GB)。此时,需要留出一定的内存(例如 4GB ~ 8GB)用于操作系统缓存和 Lucene 的缓存。这将允许 Elasticsearch 建立足够的缓存,而无需使用过多的堆内存。
对于同时处理数字、日期和文本字段的聚合和排序操作,建议将 Elasticsearch 堆内存扩大(例如 16GB ~ 32GB)。此时,需要留出一定的内存(例如 8GB ~ 16GB)用于操作系统缓存和 Lucene 的缓存。在这种情况下,需要注意堆内存的使用情况,并确保 Elasticsearch 不会触发 JVM 的 GC。
- 多租户场景:
- 对于多租户场景,建议将 Elasticsearch 堆内存划分为多个分区,每个分区仅被单个租户使用。对于每个租户,可以根据其负载和实际需求进行不同的配置。例如,高负载的租户可以被分配更多的堆内存,而低负载的租户则可以被分配较少的堆内存。这种策略将允许 Elasticsearch 更好地隔离每个租户的资源,以保证系统的平稳运行。
7. 故障排除和监控
提供一些故障排除的技巧和常见问题的解决方案。
介绍如何使用监控工具来实时监测 Elasticsearch 集群的状态和性能。
8. 扩展 Elasticsearch
解释如何使用集群、节点和索引级别的设置来扩展 Elasticsearch。
介绍如何使用插件和自定义脚本来扩展 Elasticsearch 的功能。