ELK(一)-----ElasticSearch入门学习


ELK(一)—ElasticSearch入门学习

Elasticsearch

简介

Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析和探索的能力。充分利用Elasticsearch的水平伸缩性,能使数据在生产环境变得更有价值。

Elasticsearch是与名为Logstash的数据收集和日志解析引擎以及名为Kibana的分析和可视化平台一起开发的。这三个产品被设计成一个集成解决方案,称为“Elastic Stack”(以前称为“ELK stack”)。

优点

  • 横向可扩展:只需要增加一台服务器,做一点配置,启动一下Elasticsearch进程就可以并入集群
  • 分片机制提供更好的分布性:同一个索引分成多个分片(sharding),这点类似于HDFS的块机制;分而治之的方式可提升处理效率
  • 高可用:提供复制(replica)机制,一个分片可以设置多个复制,使得某台服务器在宕机的情况下,集群依旧可以照常运行,并会把服务器宕机丢失数据信息复制恢复到其他可用节点上。
  • 使用简单:只需一条命令就可以下载文件,然后很快就能搭建一个站内搜索引擎。

实现原理

  1. 首先用户将数据提交到Elasticsearch 数据库中
  2. 再通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据
  3. 当用户搜索数据时候,再根据权重将结果排名,打分,再将返回结果呈现给用户。

安装

Windows

1

  1. 下载elasticsearch-7.15.1-windows-x86_64.zip

  2. 解压进入elasticsearch/bin目录cd elasticsearch-7.15.1/bin双击elasticsearch.bat即可启动。

  3. 在打开浏览器,输入localhost:9200即可查看是否安装成功

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PrJ3U4LF-1636448914921)(C:\Users\路小白\IdeaProjects\EleasticSearchStudy\ELK(一)]-----ElasticSearch.assets\image-20211029093846148.png)

  4. 安装head插件(ES最初的管理工具,在浏览器中显示ES集群,索引等信息),在浏览器输入http://localhost:9100

    git clone git://github.com/mobz/elasticsearch-head.git
    cd elasticsearch-head
    npm install
    npm run start
    
  5. head插件要访问ES,需要修改ES使用的参数,重启启动ES

    cd cd elasticsearch-7.15.1/conf
    vim elasticsearch.yml
    
    ##增加以下两行参数,就可以访问es
    http.cors.enabled: true
    http.cors.allow-origin: "*"
    

后台运行步骤

cd elasticsearch\bin
elasticserach-service install			//安装elasticsearch-service
elasticsearch-service manager			//启动服务

ES配置

主要有三个配置文件:

  • elasticsearch.ymlES的配置,more
  • jvm.options ES JVM配置,more
  • log4j2.properties ES 日志配置, more

JVM配置

默认情况下,弹性搜索会根据节点的角色和总内存自动设置JVM堆大小。建议大多数生产环境中的默认尺寸

JVM参数设置在ES_HOME/conf/jvm.options(推荐)中进行修改或者ES_JAVA_HOME环境变量来修改

官网介绍了如何设置堆大小

默认情况,ES 告诉 JVM 使用一个最小和最大都为 1GB 的堆。在生产环境,这个配置就比较重要了,确保 ES 有足够堆空间可用。

ES 使用 Xms(minimum heap size)Xmx(maxmimum heap size) 设置堆大小。你应该将这两个值设为同样的大小。

XmsXmx 不能大于你物理机内存的 50%。

SLM自动备份

配置快照存储库

elasticsearch.yml配置存储库位置添加该参数path.repo: ["D:\\eleasticSearchs\\snapshot_repo"]

PUT /_snapshot/my_backup
{
  "type": "fs",
  "settings": {
    "location": "D:\\eleasticSearchs\\snapshot_repo\\my_backup"
  }
}

#验证集群各个节点是否可以使用这个仓库
POST /_snapshot/my_backup/_verify

#保存集群下所有索引快照
#格式: _snapshot/仓库名称/快照名称
PUT _snapshot/my_backup/snapshot_1


##保存集群下指定索引快照
PUT _snapshot/my_backup/snapshot_2?wait_for_completion=true
{
    "indices": "txt_number"
}

#获取指定索引快照状态
GET _snapshot/my_backup/snapshot_2/_status

不要害怕配置频繁拍摄快照的策略。快照是增量的,有可能很多快照依赖于过去的段并可以有效地利用存储。所以在仓库下的文件不要手动删除

snapshot还原

只需要在集群的快照ID后加上_restore即可

POST _snapshot/my_backup/snapshot_2/_restore

如果集群中已有快照的索引那就会报索引已存在的错误

如果在不替换现有数据的前提下,恢复老数据来验证内容,或者做其他处理。可以从快照里恢复单个索引并提供一个替换的名称:

POST _snapshot/my_backup/snapshot_2/_restore
{
  "indices": "txt_number",
  "ignore_unavailable": true,
  "include_global_state": false,
  "rename_pattern": "txt_number",
  "rename_replacement": "restore_txt_number2",
  "include_aliases": false
}

数据还原时,需要等待默认情况下每个节点的节流恢复速度默认为40mb/s,每个系欸但的快照速率限制,默认为40mb/s

其他

##删除快照
DELETE _snapshot/my_backup/snapshot_2

##删除多个
DELETE _snapshot/my_backup/snapshot_1,snapshot_2

##过期快照清理
POST _snapshot/my_backup/_cleanup

基本概念

index(索引):相当于mysql中的数据库

type(类型):相当于mysql中的一张表

document(文档):相当于mysql中的一行(一条记录)

field(域): 相当于mysql中的一列(一个字段)

节点 :一个服务器,由一个名字来标识

集群 :一个或多个节点组织在一起

分片 :将一份数据划分为多小份的能力,允许水平分割和扩展容量。多个分片可以响应请求,提高性能和吞吐量。

副本 :复制数据,一个节点出问题时,其余节点可以顶上。

Elasticsearch 是利用分片将数据分发到集群内各处的。分片是数据的容器,文档保存在分片内,分片又被分配到集群内的各个节点里。
当你的集群规模扩大或者缩小时, Elasticsearch 会自动的在各节点中迁移分片,使得数据仍然均匀分布在集群里。

一个分片可以是 主 分片或者 副本 分片。 索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。

一个副本分片只是一个主分片的拷贝。 副本分片作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。

创建一个索引,主分片为5,副分片为1

PUT job
{
	"settings":{
		"index":{
			"number_of_shards":5,
			"number_of_replicas":1
		}
	}
}

{
	"acknowledged":true
	"shards_acknowledged":true
}

分片是Elasticsearch在集群周围分发数据的单位。 Elasticsearch在重新平衡数据时 (例如 发生故障后) 移动分片的速度 取决于分片的大小和数量以及网络和磁盘性能。

提示:避免有非常大的分片,因为大的分片可能会对集群从故障中恢复的能力产生负面影响。 对于多大的分片没有固定的限制,但是分片大小为50GB通常被界定为适用于各种用例的限制。

基本字段类型
  • 字符串: text(分词), keyword(不分词), StringField(不分词文本),TextFiled(要分词文本),text默认为全文文本,keyword默认为非全文文本
  • 数字: long, integer, short, double, float
  • 日期: date
  • 逻辑: Boolean
复制字段类型
  • 对象类型: object
  • 数组类型: array
  • 地理位置: geo_point, geo_shape
默认映射
JSON typeField type
Boolean: true or false“boolean”
Whole number: 123“long”
Floating point: 123.45“double”
String, valid date: “2014-09-15”“date”
String: “foo bar”“string”
映射规则
属性名解释
type字段的类型:基本数据类型,integer,long,date,boolean,keyword,text…
enable是否启用:默认为true。 false:不能索引、不能搜索过滤
boost权重提升倍数:用于查询时加权计算最终的得分,比如标题中搜索到的内容比简介中搜索到的内容跟重要,那么可以提升
index索引模式:analyzed (索引并分词,text默认模式), not_analyzed (索引不分词,keyword默认模式),no(不索引)
analyzer索引分词器:索引创建时使用的分词器,如ik_smart,ik_max_word,standard
search_analyzer搜索分词器:搜索该字段的值时,传入的查询内容的分词器。
fields多字段索引:当对该字段需要使用多种索引模式时使用。如:城市搜索New York"city":

倒排索引

ElasticSearch引擎把文档数据写入到倒排索引(Inverted Index)的数据结构中,倒排索引建立的是分词(Term)和文档(Document)之间的映射关系,在倒排索引中,数据是面向词(Term)而不是面向文档的

一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表

组成部分

单词词典(Term Dictionary)

搜索引擎通常索引单位是单词,单词是由文档集合中出现过的所有单词构成的字符串集合,同时用来记载某个单词对应的倒排列表在倒排文件中的位置信息。

结构组成:哈希+链表+B树(或者B+树)

主体部分是哈希表,每个哈希表项保存一个指针,指针指向冲突链表,在冲突链表里,相同哈希值的单词形成链表结构。

查询某个词时,利用哈希函数获取对应的哈希值,根据哈希值找到对应哈希表中保存的指针,找到对应的冲突链表。在冲突链表中找到对应的倒排列表。

树形结构主要根据层级查找,中间节点用于指出一定顺序范围的词典项目存储在哪个子树中,起到根据词典项比较大小进行导航的作用,最底层的叶子节点存储单词的地址信息,根据这个地址就可以提取出单词字符串

倒排列表(Posting List)

倒排列表记载了出现过某个单词的所有文档的文档列表单词在该文档中出现的位置信息频率关键性算分,每条记录称为一个倒排项Posting。根据倒排列表,即可获知哪些文档包含某个单词。

倒排索引项包含如下信息:

  1. 文档ID:用于获取原始信息
  2. 单词频率(TF,Term Frequency): 记录该单词在该文档中出现的次数,用于后续相关性算分
  3. 位置(Positing): 记录单词在文档中的分词位置(多个),用于词语搜索(Phrase Query)
  4. 偏移(Offset): 记录单词在文档的开始和结束位置,用于高亮显示
倒排文件(Inverted File)

所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件即被称之为倒排文件,倒排文件存储倒排索引的物理文件

示例

文档ID文档内容
1谷歌地图之父跳槽Facebook
2谷歌地图之父加盟Facebook
3谷歌地图创始人拉斯离开谷歌加盟Facebook
4谷歌地图之父跳槽Facebook与Wave项目取消有关
5谷歌地图之父拉斯加盟社交网站Facebook
单词ID单词文档频率倒排列表(DocID;TF; < P O S > <POS> <POS>)
1谷歌5(1;1;<1>), (2;1;<1>), (3;2<1;6>), (4;1;<1>), (5;1;<1>)
2地图5(1;1;<2>), (2;1;<2>), (3;1;<2>), (4;1;<2>), (5;1;<2>)
3之父4(1;1;<3>), (2;1<3>), (4;1;<3>), (5;1;<3>)
4跳槽2(1;1;<4>),(4;1;<4>)

单词ID:记录每个单词的单词编号;
单词:对应的单词;
文档频率:代表文档集合中有多少个文档包含某个单词
倒排列表:包含单词ID及其他必要信息
DocId:单词出现的文档id
TF:单词在某个文档中出现的次数
POS:单词在文档中出现的位置

倒排索引不可变的好处
  • 不需要锁,提升并发能力,避免锁的问题
  • 数据不变,一直保存在os cache中,只要cache内存足够
  • filter cache一直驻留在内存,因为数据不变
  • 可以压缩,节省cpu和IO开销

分词

分词是将文本转换成一系列单词(Term or Token)的过程,也可以叫文本分析,在ES里面称为Analysis

分词器

分词器是ES中专门处理分词的组件,英文为Analyzer,它的组成如下:

Character Filters:针对原始文本进行处理,比如去除html标签
Tokenizer:将原始文本按照一定规则切分为单词
Token Filters:针对Tokenizer处理的单词进行再加工,比如转小写、删除或增新等处理

预定义分词器

  • Standard Analyzer

    • 默认分词器
    • 按词切分,支持多语言
    • 小写处理
  • Simple Analyzer

    • 按照非字母切分
    • 小写处理
  • Whitespace Analyzer

    • 空白字符作为分隔符
  • Stop Analyzer

    • 相比Simple Analyzer多了去除请用词处理
    • 停用词指语气助词等修饰性词语,如the, an, 的, 这等
  • Keyword Analyzer

    • 不分词,直接将输入作为一个单词输出
  • Pattern Analyzer

    • 通过正则表达式自定义分隔符
    • 默认是\W+,即非字词的符号作为分隔符
  • Language Analyzer

    • 提供了30+种常见语言的分词器

中文分词器插件es-ik安装

  • 点击ES-ik下载压缩包,解压到ES\plugin\ik目录下
  • 重启ES即可

版本不一致问题

1、ES 7.x默认不再支持指定索引类型,默认索引类似是_doc,如果想改变,则需要配置include_type_name:true。同时这一字段将在8.x舍弃

PUT /shakespeare?include_type_name=true
{
  "mappings": {
    "doc" : {
      "properties":{
        "speaker":{
          "type": "keyword"
        },
        "play_name":{
          "type": "keyword"
        },
        "line_id":{
          "type": "integer"
        },
        "speech_number":{
          "type": "integer"
        }
      }
    }
  }
}

2、数据导入,导入之前需创建对应的index。

    curl -H "Content-Type: application/x-ndjson" -XPOST "127.0.0.1:9200/shakespeare/doc/_bulk?pretty" --data-binary @D:\TestData\elasticsearch\shakespeare_6.0.json
    curl -H "Content-Type: application/x-ndjson" -XPOST "127.0.0.1:9200/bank/account/_bulk?pretty" --data-binary @D:\TestData\elasticsearch\accounts.json
	curl -H "Content-Type: application/x-ndjson" -XPOST "127.0.0.1:9200/_bulk?pretty" --data-binary @D:\TestData\elasticsearch\logs.jsonl

3、搜索时,若提示未启用安全功能,可以在Elasticsearch/conf/elasticsearch.yml文件中增加如下参数,重启ES示例即可

#禁用安全选项
xpack.security.enabled: false

聚合(aggregations)

桶(bucket)

桶的作用,是按照某种方式对数据进行分组,每一组数据在ES中称为一个,例如我们根据国籍对人划分,可以得到中国桶英国桶日本桶……或者我们按照年龄段对人进行划分:0$$10,10$ 20 , 20 20,20 20,20$30,3040等。

划分桶的方式:

  • Date Histogram Aggregation:根据日期阶梯分组,例如给定阶梯为周,会自动每周分为一组
  • Histogram Aggregation:根据数值阶梯分组,与日期类似
  • Terms Aggregation:根据词条内容分组,词条内容完全匹配的为一组
  • Range Aggregation数值日期的范围分组,指定开始和结束,然后按段分组

度量(metrics)

分组完成以后,一般会对组中的数据进行聚合运算,例如求平均值、最大、最小、求和等,这些在ES中称为度量

常用的度量聚合方式

  • Avg Aggregation:求平均值
  • Max Aggregation:求最大值
  • Min Aggregation:求最小值
  • Percentiles Aggregation:求百分比
  • Stats Aggregation:同时返回avg、max、min、sum、count等
  • Sum Aggregation:求和
  • Top hits Aggregation:求前几
  • Value Count Aggregation:求总数

批量操作

  1. bulk:ES本地支持的批量导入方式,如果是txt文本需要进行数据格式转换为json文件
  2. logstash: ELK生态中的另一个产品,可以将数据文本 转换为ES的数据源
  3. SpringData-ES的Java方式

mget

这个命令的话直接上代码比较容易理解的

PUT example/_mapping
{
  "properties": {
    "id": {"type": "long"},
    "name": {"type": "text"},
    "counter": {"type": "integer"},
    "tags": {"type": "text"}
  }
}

POST example/_doc/1
{
    "id": 1,
    "name": "admin",
    "counter": 1,
    "tags": ["gray"]
}
POST example/_doc/2
{
    "id": 2,
    "name": "zhangsan",
    "counter": 1,
    "tags": ["black"]
}
POST example/_doc/3
{
    "id": 3,
    "name": "lisi",
    "counter": 1,
    "tags": ["purple"]
}

PUT example_test/_mapping
{
  "properties": {
    "id": {"type": "long"},
    "name": {"type": "text"},
    "counter": {"type": "integer"},
    "tags": {"type": "text"}
  }
}

POST example_test/_doc/1
{
    "id": 1,
    "name": "test-admin",
    "counter": 1,
    "tags": ["gray"]
}
POST example_test/_doc/2
{
    "id": 2,
    "name": "test-zhangsan",
    "counter": 1,
    "tags": ["black"]
}
POST example_test/_doc/3
{
    "id": 3,
    "name": "test-lisi",
    "counter": 1,
    "tags": ["purple"]
}
GET example/_search
GET _mget
{
    "docs": [
        {
            "_index": "example",
            "_id": "1"
        },
        {
            "_index": "example",
            "_id": "2"
        },
        {
            "_index": "example_test",
            "_id": "1"
        },
        {
            "_index": "example_test",
            "_id": "2"
        }
    ]
}
GET example/_mget
{
    "docs": [
        {
            "_id": "1"
        },
        {
            "_id": "2"
        },
        {
            "_id": "3"
        }
    ]
}

Bulk processtor

BulkProcessor提供了一个简单的接口来实现批量提交请求(多种请求,如IndexRequest,DeleteRequest),且可根据请求数量、大小或固定频率进行flush提交。flush方式可选同步或异步

bulk request 会加载到内存里,如果太大的话,性能反而会下降,因此需要反复尝试一个最佳的 bulk size。一般从 1000~5000 条数据开始,尝试逐渐增加。另外,如果看大小的话,最好是在 5~15 MB 之间

官方示例
public BulkProcessor bulkProcessor() throws UnknownHostException {
        Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
        //客户端连接的采用端口为9300,否则获取不到对应的节点
        Client client = new PreBuiltTransportClient(settings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), Integer.parseInt("9300")));

        BulkProcessor bulkProcessor = BulkProcessor.builder(
                        client,//添加搜索客户端
                        new BulkProcessor.Listener() {
                            @Override
                            public void beforeBulk(long executionId,
                                                   BulkRequest request) {
                                //批量执行之前被调用

                            }

                            @Override
                            public void afterBulk(long executionId,
                                                  BulkRequest request,
                                                  BulkResponse response) {
                                //批量执行之后被调用 检查是否有一些失败的请求

                            }

                            @Override
                            public void afterBulk(long executionId,
                                                  BulkRequest request,
                                                  Throwable failure) {//
                                System.out.println("error>>> " + failure);
                            }
                        })
                .setBulkActions(10000)//10000个请求执行一次批量请求
                .setBulkSize(new ByteSizeValue(1, ByteSizeUnit.GB))//每1G冲洗一次批量
                .setFlushInterval(TimeValue.timeValueSeconds(5))//无论请求数量多少,每5秒冲洗一次批量
                .setConcurrentRequests(1)//设置并发请求的数量,值 0 表示仅允许执行单个请求,值 1 表示允许在累积新的批量请求时执行 1 个并发请求。
                .setBackoffPolicy(
                        /**
                         *
                         * 设置一个自定义的退订策略,最初将等待 100m,成倍增加,重述多达三次。
                         * 每当一个或多个批量项目请求失败时,都会尝试重试,这表明可用于处理请求的计算资源太少。
                         * 要禁用后退,通过。EsRejectedExecutionExceptionBackoffPolicy.noBackoff()
                         */
                        BackoffPolicy.exponentialBackoff(TimeValue.timeValueMillis(100), 3))
                .build();

        return bulkProcessor;
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路小白&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值