Skip to content

Elastic Stack Elastic Stack

AI 整理版

本篇已整理为更适合学习与复习的笔记结构,欢迎前往阅读:Elastic Stack-AI整理版

Elastic Stack 简介

ELK是一个免费开源的日志分析架构技术栈总称,官网。包含三大基础组件,分别是Elasticsearch、Logstash、Kibana。但实际上ELK 不仅仅适用于日志分析,它还可以支持其它任何数据搜索、分析和收集的场景,日 志分析和收集只是更具有代表性。并非唯一性。下面是ELK架构:

ELK架构图

随着elk的发展,又有新成员Beats、elastic cloud的加入,所以就形成了 Elastic Stack。所以说,ELK是I旧的称呼,Elastic Stack是新的名字。

ElasticStack架构图

Elastic Stack特色

  • 处理方式灵活:elasticsearch是目前最流行的准实时全文检索引擎,具有 高速检索大数据的能力。

  • 配置简单:安装k的每个组件,仅需配置每个组件的一个配置文件即可。

    修改处不多,因为大量参数已经默认配在系统中,修改想要修改的选项即 可。

  • 接口简单:采用json形式RESTFUL API接受数据并响应,无关语言。

  • 性能高效:elasticsearch:基于优秀的全文搜索技术Lucene,采用倒排索 引,可以轻易地在百亿级别数据量下,搜索出想要的内容,并且是秒级响 应。

  • 灵活扩展:elasticsearchi和logstash都可以根据集群规模线性拓展, elasticsearch内部自动实现集群协作。

  • 数据展现华丽:kibana作为前端展现工具,图表华丽,配置简单。

Elastic Stack组件介绍

Elasticsearch

Elasticsearch是使用java开发,基于Lucene、分布式、通过Restful)方式进行 交互的近实时搜索平台框架。它的特点有:分布式,零配置,自动发现,索引自动 分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。

Logstash

Logstash基于java开发,是一个数据抽取转化工具。一般工作方式为c/s架 构,clienti端安装在需要收集信息的主机上,serveri端负责将收到的各节点日志进 行过滤、修改等操作在一并发往elasticsearch或其他组件上去。

Kibana

Kibana基于nodejs,也是一个开源和免费的可视化工具。Kibanai可以为 Logstash和ElasticSearch提供的日志分析友好的Web界面,可以汇总、分析和 搜索重要数据日志。

Beats

Beats平台集合了多种单一用途数据采集器。它们从成百上千或成千上万台机 器和系统向Logstash或Elasticsearch发送数据。

Beats由如下组成

Packetbeat

轻量型网络数据采集器,用于深挖网线上传输的数据,了解应 用程序动态。Packetbeat是一款轻量型网络数据包分析器,能够将数据发送至 Logstash或Elasticsearch。其支持ICMP(v4andv6)、DNS、HTTP、Mysql.. PostgreSQL、Redis、MongoDB、Memcache等t协议。

Filebeat

轻量型日志采集器。当您要面对成百上千、甚至成千上万的服务 器、虚拟机和容器生成的日志时,请告别SSH吧。Filebeat将为您提供一种轻量型 方法,用于转发和汇总日志与文件,让简单的事情不再繁杂。

Metricbeat

轻量型指标采集器。Metricbeat能够以一种轻量型的方式, 输送各种系统和服务统计数据,从CPU到内存,从Redis到Nginx,不一而足。 可定期获取外部系统的监控指标信息,其可以监控、收集Apache http、 HAProxy、MongoDB、MySQL、Nginx、PostgreSQL、Redis、System Zookeeper等服务。

Winlogbeat

轻量型Windows事件日志采集器。用于密切监控基于 Windows的基础设施上发生的事件。Winlogbeat能够以一种轻量型的方式,将 Windows事件日志实时地流式传输至Elasticsearch和Logstash。

Auditbeat

轻量型审计日志采集器。收集您Linux审计框架的数据,监控 文件完整性。Auditbeat实时采集这些事件,然后发送到Elastic Stack其他部分做 进一步分析。

Heartbeat

面向运行状态监测的轻量型采集器。通过主动探测来监测服务 的可用性。通过给定URL列表,Heartbeat仅仅询问:网站运行正常吗? Heartbeat会将此信息和响应时间发送至Elastic的其他部分,以进行进一步分 析。

Functionbeat

面向云端数据的无服务器采集器。在作为一项功能部署在云 服务提供商的功能即服务(FaaS)平台上后,Functionbeat即能收集、传送并监测 来自您的云服务的相关数据。

Elastic cloud

基于Elasticsearch的软件即服务(Saas)解决方案。通过Elastic的官方合作伙 伴使用托管的Elasticsearch服务。

Elasticsearch是什么

搜索是什么?

概念:用户输入想要的关键词,返回含有该关键词的所有信息。 场景:

  • 互联网搜索:谷歌、百度、各种新闻首页;
  • 站内搜索(垂直搜索):企业OA查询订单、人员、部门,电商网站内部搜索商品(淘宝、京东)场景。

数据库做搜索弊端

站内搜索(垂直搜索)

数据量小,简单搜索,可以使用数据库。

问题出现
  • 存储问题。

    电商网站商品上亿条时,涉及到单表数据过大必须拆分表,数据 库磁盘占用过大必须分库(mycat)。

  • 性能问题。

    解决上面问题后,查询“笔记本电脑”等关键词时,上亿条数据的 商品名字段逐行扫描,性能跟不上。

  • 不能分词。

    如搜索“笔记本电脑”,只能搜索完全和关键词一样的数据,那么 数据量小时,搜索“笔记电脑”,“电脑"数据要不要给用户。

总结

互联网搜索,肯定不会使用数据库搜索。数据量太大。PB级。

全文检索、倒排索引和Lucene

全文检索

倒排索引。数据存储时,经行分词建立term索引库。

建立term索引库

倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一 项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性 值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒 排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。

Lucene

就是一们r包,里面封装了全文检索的引擎、搜索的算法代码。开发时,引入 lucenel的jar包,通过api开发搜索相关业务。底层会在磁盘建立索引库。

什么是Elasticsearch

简介

ElasticSearch:是一个基于Lucene的搜索服务器。它提供了一个分布式多用户 能力的全文搜索引擎,基于RESTful web 接口。 官网

Elasticsearch

Elasticsearch的功能

  • 分布式的搜索引擎和数据分析引

    搜索:互联网搜索、电商网站站内搜索、OA系统查询 数据分析:电商网站查询近一周哪些品类的图书销售前十:新闻网站,最近3 天阅读量最高的十个关键词,舆情分析。

  • 全文检索,结构化检索,数据分析 全文检索:搜索商品名称包含java的图书selectfrom books where book_name like "%java%" 结构化检索:搜索商品分类为spring的图书都有哪些,selectfrom books where category_id='spring' 数据分析:分析每一个分类下有多少种图书,select category_id,count(*) from books group by category_id

  • 对海量数据进行近实时的处理 分布式:ES自动可以将海量数据分散到多台服务器上去存储和检索,经行并行查 询,提高搜索效率。相对的,Lucene是单机应用。 近实时:数据库上亿条数据查询,搜索一次耗时几个小时,是批处理(batch- processing)。而es只需秒级即可查询海量数据,所以叫近实时。秒级。

lucene-es部署

Elasticsearch 的使用场景

国外:

  • 维基百科,类似百度百科,“网络七层协议"的维基百科,全文检索,高亮, 搜索推荐
  • Stack Overflow(国外的程序讨论论坛),相当于程序员的贴吧。遇到it问 题去上面发帖,热心网友下面回帖解答。
  • GitHub(开源代码管理),搜索上千亿行代码。
  • 电商网站,检索商品
  • 日志数据分析,logstash采集日志,ES进行复杂的数据分析(ELK技术, elasticsearch+logstash+kibana
  • 商品价格监控网站,用户设定某商品的价格阈值,当低于该阈值的时候,发 送通知消息给用户,比如说订阅《jva编程思想》的监控,如果价格低于 27块钱,就通知我,我就去买。
  • BI系统,商业智能(Business Intelligence)。大型连锁超市,分析全国网 点传回的数据,分析各个商品在什么季节的销售量最好、利润最高。成本管 理,店面租金、员工工资、负债等信息进行分析。从而部署下一个阶段的战 略目标。

国内:

  • 百度搜索,第一次查询,使用es。
  • OA、ERP系统站内搜索。

Elasticsearch的特点

  • 可拓展性:大型分布式集群(数百台服务器)技术,处理PB级数据,大公 司可以使用。小公司数据量小,也可以部署在单机。大数据领域使用广泛。
  • 技术整合:将全文检索、数据分析、分布式相关技术整合在一起: lucene(全文检索),商用的数据分析软件(B软件),分布式数据库 mycat
  • 部署简单:开箱即用,很多默认配置不需关心,解压完成直接运行即可。拓 展时,只需多部署几个实例即可,负载均衡、分片迁移集群内部自己实施。
  • 接口简单:使用restful api经行交互,跨语言。
  • 功能强大:Elasticsearch作为传统数据库的一个补充,提供了数据库所不不 能提供的很多功能,如全文检索,同义词处理,相关度排名。

Elasticsearch的特点

Elasticsearch 的核心概念

lucene和elasticsearch的关系

Lucene:最先进、功能最强大的搜索库,直接基于lucene开发,非常复杂, api复杂。 Elasticsearch:基于lucene,封装了许多ucene底层功能,提供简单易用的 restful api接口和许多语言的客户端,如java的高级客户端(Java High Level REST Client)和底层客户端(Java Low Level REST Client)

Elasticsearch交互

起源:Shay Banon。2004年失业,陪老婆去伦敦学习厨师。失业在家帮老婆 写一个菜谱搜索引擎。封装了lucenet的开源项目,compass。找到工作后,做分布 式高性能项目,再封装compass,写出了elasticsearch,使得lucene,使得lucenet支持分布式。 现在是Elasticsearch创始人兼Elastic首席执行官。

Elasticsearch 的核心概念

1 NRT(Near Realtime):近实时
  1. 两方面: 写入数据时,过1秒才会被搜索到,因为内部在分词、录入索引。
  2. es搜索时:搜索和分析数据需要秒级出结果。
2 Cluster:集群

包含一个或多个启动着es实例的机器群。通常一台机器起一个es实例。同一网 络下,集名一样的多个s实例自动组成集群,自动均衡分片等行为。默认集群名 为"elasticsearch"。

3 Node:节点

每个s实例称为一个节点。节点名自动分配,也可以手动配置。

4 Document:文档

es中的最小数据单元。一个documenti就像数据库中的一条记录。通常以)json 格式显示。多个document存储于一个索引(Index)中。

json
book document

{
    "book_id":"1",
	"book_name":"java编程思想",
	"book_desc":"从Java的基础语法到最高级特性(深入的[面向对象](https://baike.baidu.com/item/面向对象)概念、多线程、自动项目构	建、单元测试和调试等),本书都能逐步指导你轻松学握。”,
	"category_id":"2",
	"category_name":"java"
}
5 Index:索引

包含一堆有相似结构的文档数据。 索引创建规则:

  • 仅限小写字母
  • 不能包含1、/、*、?、"、<、>、、#以及空格符等特殊符号
  • 从7.0版本开始不再包含冒号
  • 不能以、或+开头
  • 不能超过255个字节(注意它是字节,因此多字节字符将计入255个限制)
6 Field:字段

就像数据库中的列(Columns),定义每个document)应该有的字段。

7Type:类型

每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类, 一个type下的document,都有相同的field。 注意:6.0之前的版本有type(类型)概念,type相当于关系数据库的表,ES 官方将在ES9.0版本中彻底删除type。本教程ypy都为_doc。

8 shard:分片

index数据过大时,将index.里面的数据,分为多个shard,分布式的存储在各 个服务器上面。可以支持海量数据和高并发,提升性能和吞吐量,充分利用多台机 器的cpu。

9 replica:副本

在分布式环境下,任何一台机器都会随时宕机,如果宕机,index的一个分片 没有,导致此index不能搜索。所以,为了保证数据的安全,我们会将每个index的 分片经行备份,存储在另外的机器上。保证少数机器宕机s集群仍可以搜索。

能正常提供查询和插入的分片我们叫做主分片(primary shard),其余的我 们就管他们叫做备份的分片(replica shard)。

s6默认新建索引时,5分片,1副本,也就是一主一备,共10个分片。所以, es集群最小规模为两台。es71分片,1副本,一共2分片。

es核心概念

数据库核心概念vs.elasticsearch核心概念

关系型数据库(比如Mysql)
非关系型数据库(Elasticsearch)
数据库Database
索引Index
表Table
索引Index(原为Type)
数据行Rod
文档Document
数据列Column
字段Field
约束Schema
映射Mapping

es快速入门

商品的CRUD

1. 创建图书索引

语法:PUT /index

请求参数:

json
put /book

响应结果:

json
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "book"
}

2. 新增图书:新增文档

语法:PUT /index/type/id

请求参数

json
put /book/_doc/1
{
    "name": "Bootstrap开发",
    "description": "Bootstrap是由witter:推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、S程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个Css,不受浏览器限制的精美界面css效果。",
    "studymodel": "201002",
    "price": 38.6,
    "timestamp": "2019-08-2519:11:35",
    "pic": "group1/M00/00/00/wKh1QFs6RCeAYOpHAAJx5ZjNDEM428.jpg",
    "tags": [
        "bootstrap",
        "dev"
    ]
}

响应结果

json
{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

3. 根据_id查询图书:查询文档

语法:GET/index/type/id

请求参数

json
get /book/_doc/1

响应结果,存在

json
{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "Bootstrap开发",
    "description" : "Bootstrap是由witter:推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、S程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个Css,不受浏览器限制的精美界面css效果。",
    "studymodel" : "201002",
    "price" : 38.6,
    "timestamp" : "2019-08-2519:11:35",
    "pic" : "group1/M00/00/00/wKh1QFs6RCeAYOpHAAJx5ZjNDEM428.jpg",
    "tags" : [
      "bootstrap",
      "dev"
    ]
  }
}

响应结果不存在

json
{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "2",
  "found" : false
}

4. 覆盖指定_id的图书:覆盖文档

语法:PUT /index/type/id

请求参数:

json
put /book/_doc/1
{
    "name": "Bootstrap开发1",
    "description": "Bootstrap是由witter:推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、S程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个Css,不受浏览器限制的精美界面css效果。",
    "studymodel": "201002",
    "price": 38.6,
    "timestamp": "2019-08-2519:11:35",
    "pic": "group1/M00/00/00/wKh1QFs6RCeAYOpHAAJx5ZjNDEM428.jpg",
    "tags": [
        "bootstrap",
        "dev",
        "js"
    ]
}

响应结果:

json
{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

5. 修改指定_id的图书局部内容:修改文档

语法:POST /index/type/id/_update

请求参数:

json
post /book/_doc/1/_update
{
    "doc": {
        "name": "Bootstrap开发_update",
        "tags": [
            "bootstrap",
            "dev",
            "update"
        ]
    }
}

响应结果:

json
#! Deprecation: [types removal] Specifying types in document update requests is deprecated, use the endpoint /{index}/_update/{id} instead.
{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

它提示可以改为:

语法:POST /index/_update/id

请求参数:

json
post /book/_update/1
{
    "doc": {
        "name": "Bootstrap开发_update2",
        "tags": [
            "bootstrap",
            "dev"
        ]
    }
}

响应结果:

json
{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

6. 删除图书:删除文档

语法:DELETE /index/type/id

请求参数:

json
DELETE /book/_doc/1

响应结果:

json
{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

文档Document入门

默认的自带字段解析

json
{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "Bootstrap开发",
    "description" : "Bootstrap是由witter:推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、S程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个Css,不受浏览器限制的精美界面css效果。",
    "studymodel" : "201002",
    "price" : 38.6,
    "timestamp" : "2019-08-2519:11:35",
    "pic" : "group1/M00/00/00/wKh1QFs6RCeAYOpHAAJx5ZjNDEM428.jpg",
    "tags" : [
      "bootstrap",
      "dev"
    ]
  }
}

_index

  • 含义:此文档属于哪个索引。
  • 原则:类似数据放在一个索引中。数据库中表的定义规则。如图书信息放在00k索。
  • 引中,员工信息放在employee索引中。各个索存储和搜索时互不影响。 定义规则:英文小写。尽呈不要使用特殊字符。order user

_type

  • 含义:类别。book java node。
  • 注意:以后的es9将彻底册除此字段,所以当前版本在不断弱化type。不需要关 注。见到type都为doc。

_id

  • 含义:文档的唯一标识。就像表的id主键。结合索引可以标识和定义一个文档。
  • 生成:手动(put /index/_doc/id)、自动。

创建索引时,不同数据放到不同索引中

不同数据放到不同索引中

生成文档id

手动生成id

参考[2. 新增图书:新增文档](#2. 新增图书:新增文档)

自动生成id

白动id特点: 长度为20个字符,URL安全,base64编码,GUID,分布式生成不冲突。

语法:POST /index/type

请求入参:

json
POST /test_index/_doc
{
  "test_field": "demo"
}

响应结果:

json
{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "Fn28zYQBMWSYG3VSxZy0",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

_source字段

_source

含义:插入数据时的所有字段和值。在ge获取数据时,在_source:字段中原样返回。 GET /book/doc/1

6.3.2定制返回字段

就像sql不要select*,而要select name,.price from book,一样。

返回所有:GET /book/_doc/1

{
  "_index" : "book",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "Bootstrap开发",
    "description" : "Bootstrap是由witter:推出的一个前台页面开发css框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、S程序代码,可以帮助开发者(尤其是不擅长css页面开发的程序人员)轻松的实现一个Css,不受浏览器限制的精美界面css效果。",
    "studymodel" : "201002",
    "price" : 38.6,
    "timestamp" : "2019-08-2519:11:35",
    "pic" : "group1/M00/00/00/wKh1QFs6RCeAYOpHAAJx5ZjNDEM428.jpg",
    "tags" : [
      "bootstrap",
      "dev"
    ]
  }
}

定制返回字段: GET /book/_doc/1?_source_includes=name,price

json
{
    "_index": "book",
    "_type": "_doc",
    "_id": "1",
    "_version": 1,
    "_5eq_-no": 10,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "price": 38.6,
        "name": "Bootstrap开发牧程1"
    }
}

文档的替换与删除

全量替换

执行两次,返回结果中版本号(version)在不断上升。此过程为全量替换。

json
PUT /test_index/_doc/1
{
    "test_field":"test"
}

实质:旧文档的内容不会立即删除,只是标记为deleted。适当的时机,集群会将这些文档删除。

全量替换图

强制创建

为防止覆盖原有数据,我们在新增时,设置为强制创建,不会覆盖原有文档。

可以用于数据库同步数据,这样可以确保数据只插入一次不会重复插入或覆盖。

kibana
语法:PUT /index/_doc/id/_create

请求入参:

json
PUT /test_index/_doc/1/_create
{
    "test_field":"test"
}

第一次请求响应结果:

json
{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

再次请求(存在数据)响应结果:

json
{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[1]: version conflict, document already exists (current version [1])",
        "index_uuid" : "ej29cxPQQ3ab2t8_U0hMkg",
        "shard" : "0",
        "index" : "test_index"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[1]: version conflict, document already exists (current version [1])",
    "index_uuid" : "ej29cxPQQ3ab2t8_U0hMkg",
    "shard" : "0",
    "index" : "test_index"
  },
  "status" : 409
}

局部更新partial update

使用PUT/index/ype/id为文档全量替换,需要将文档所有数据提交。 partial update 局部替换则只修改变动字段。 用法:

json
post /index/type/id/_update
{
    "doc": {
        "field": "value"
    }
}
图解内部原理

图解局部更新内部原理

内部与全量替换是一样的,旧文档标记为删除,新建一个文档。 优点:

  • 大大减少网络传输次数和流量,提升性能。
  • 减少并发冲突发生的概率。
演示

[2. 新增图书:新增文档](#2. 新增图书:新增文档)

[5. 修改指定_id的图书局部内容:修改文档](#5. 修改指定_id的图书局部内容:修改文档)

使用脚本更新

es可以内置脚本执行复杂操作。例如painless脚本。 注意:groovy脚本在s6以后就不支持了。原因是耗内存,不安全远程注入漏洞。

内置脚本

需求1:修改文档6的num字段,+1。

插入数据:

json
PUT /test_index/_doc/6
{
    "num": 0
}

执行脚本操作:

json
POST /test_index/_doc/6/_update
{
    "script": "ctx._source.num+=1"
}

响应结果:

json
#! Deprecation: [types removal] Specifying types in document update requests is deprecated, use the endpoint /{index}/_update/{id} instead.
{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "6",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 1
}

查询数据:

json
GET /test_index/_doc_6

响应结果:

json
{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "6",
  "_version" : 3,
  "_seq_no" : 4,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "num" : 1
  }
}

需求2:搜索所有文档,将num字段乘以2输出。

插入数据:

json
PUT /test_index/_doc/7
{
    "num": 5
}

查询:

json
GET /test_index/_search
{
    "script_fields": {
        "my_doubled_field": {
            "script": {
                "lang": "expression",
                "source": "doc['num'] * multiplier",
                "params": {
                    "multiplier": 2
                }
            }
        }
    }
}

响应结果:

json
{
  "took" : 33,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "Fn28zYQBMWSYG3VSxZy0",
        "_score" : 1.0,
        "fields" : {
          "my_doubled_field" : [
            0.0
          ]
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "fields" : {
          "my_doubled_field" : [
            0.0
          ]
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "fields" : {
          "my_doubled_field" : [
            4.0
          ]
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.0,
        "fields" : {
          "my_doubled_field" : [
            10.0
          ]
        }
      }
    ]
  }
}
外部脚本

Bainless是内置支持的。脚本内容可以通过多种途径传给es,包括rest接口,或者放

到config/scripts目录等,默认开启。

注意:脚本性能低下,且容易发生注入,本教程忽略。

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-scripting-using.html

图解ES的并发问题

ES并发问题

如同秒杀场景,多线程情况下,ES同样会出现并发冲突问题。

图解悲观锁与乐观锁机制

为控制并发问题,我们通常采用锁机制。分为悲观锁和乐观锁两种机制。

悲观锁:很悲观,所有情况都上锁。此时只有一个线程可以操作数据。具体例子为

数据库中的行级锁、表级锁、读锁、写锁等。

特点:优点是方便,直接加锁,对程序透明。缺点是效率低。

乐观锁:很乐观,对数据本身不加锁。提交数据时,通过一种机制验证是否存在冲

突,如es中通过版本号验证。

特点:优点是并发能力高。缺点是操作繁琐,在提交数据时,可能反复重试多次。

图解es内部基于_version乐观锁控制

实验基于_version的版本控制

es对于文档的增刷改都是基于版本号。

新增多次文档:

json
PUT /test_index/_doc/3
{
	"test_field":"test"
}

返回版本号递增:

json
// 新增第一次
{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "3",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 6,
  "_primary_term" : 2
}

// 新增第二次
{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "3",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 9,
  "_primary_term" : 2
}

删除此文档:

jsom
DELETE /test_index/_doc/3

响应结果:

json
{
  "_index" : "test_index",
  "_type" : "_doc",
  "_id" : "3",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 7,
  "_primary_term" : 2
}

即使是删除,也可以看到版本号依然递增,验证延迟删除策略。 如果除一条数据立马删除的话,所有分片和副本都要立马刷除,对s集群压力太 大。

图解es内部主从同步并发控制

es内部主从同步时,是多线程异步。乐观锁机制。

图解es内部主从同步并发控制

批量增删改 bulk

Buk操作解释将文档的增删改查一些列操作,通过一次请求全都做完。减少网络传输

次数。

语法:

json
POST /_bulk
{"action":{"metadata"}}
{"data"}

如下操作,删除5,新增14,修改2。

json
POST /_bulk
{"create":{"_index":"test_index","_id":"8"}}
{"test_field":"test8"}
{"update":{"_index":"test_index","_id":"3"}}
{"doc":{"test_field":"bulk test"}}
{"delete":{"_index":"test_index","_id":"5"}}

总结:

  1. 功能:

    • delete:删除一个文档,只要1个json串就可以了;
    • create:相当于强制创建PUT /index/type/id/_create;
    • index:普通的put操作,可以是创建文档,也可以是全量替换文档;
    • update:执行的是局部更新partial update操作;
  2. 格式:每个json不能换行。相邻json必须换行。

  3. 隔离:每个操作互不影响。操作失败的行会返回其失败信息。

  4. 实际用法:buk请求一次不要太大,否则一下积压到内存中,性能会下降。所

    以,一次请求几干个操作、大小在几M正好。

Java API 实现文档管理

elasticsearch java API

之前写的整合博客。

CSDN:(71条消息) spring-boot 整合elasticsearch 7.x(简单入门含gitee源码)_meng前行的博客-CSDN博客_springboot整合elasticsearch7

简书:spring-boot 整合elasticsearch 7.x(简单入门含gitee源码) - 简书 (jianshu.com)

图解es内部机制

图解es分布式基础

视频

day2-09-图解es分布式基础_哔哩哔哩_bilibili

es对复杂分布式机制的透明隐藏特性
  • 分布式机制:分布式数据存储及共享。
  • 分片机制:数据存储到哪个分片,副本数据写入。
  • 集群发现机制:cluster discovery。新启动es实例,自动加入集群。
  • shard负载均衡:大呈数据写入及查询,es会将数据平均分配。
  • shard副本:新增副本数,分片重分配。
Elasticsearch的垂直扩容与水平扩容

垂直扩容:使用更加强大的服务器替代老服务器。但单机存储及运算能力有上线。

且成本直线上升。如10t服务器1万。单个10T服务器可能20万。

水平扩容:采购更多服务器,加入集群。大数据。

增减或减少节点时的数据rebalance

新增或减少es实例时,es集群会将数据重新分配。

master节点

功能:

  • 创建别除节点;
  • 创建删除索引;
节点对等的分布式架构
  • 节点对等,每个节点都能接收所有的请求;
  • 自动请求路由;
  • 响应收集;
示例图

图解es分布式基础

图解分片shard、副本replica机制

视频

day2-10-图解分片shard、副本replica机制_哔哩哔哩_bilibili

shard & replica机制
  1. 每个index包,含一个或多个shard。

  2. 每个shard都是一个最小工作单元,承载部分数据,lucene实例,完整的建立

    索引和处理请求的能力。

  3. 增减节点时,shard会自动在nodes中负载均衡。

  4. primary shardi和replica shard,每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard。

  5. replica shard,是primary shard的副本,负责容错,以及承担读请求负载。

  6. primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随 时修改。

  7. primary shard的默认数量是1,replica默认是1,默认共有2个shard,1个primary shard、 1replica shard。

    注意:es7以前primary shard的默认数量是5,replica默认是1,默认有10个shard,5个primary shard,5个replica shard。

  8. primary shard不能和自己的replica shardi放在同一个节点上(否则节点宕机, primary shard和副本都丢失,起不到容错的作用),但是可以和其他primary shard的replica shard放在同一个节点上。

图解单node环境下创建index是什么样子的

  1. 单node环境下,创建一个index,有3个primary shard,3个replica shard。
  2. 集群status是yellow。
  3. 这个时候,只会将3个primary shard:分配到仅有的一个node上去,另外3个 replica shard是无法分配的。
  4. 集群可以正常工作,但是一旦出现节点宕机,数据全部丢失,而且集群不可用, 无法承接任何请求。

请求创建索引并设置分片值:

json
PUT /test_index1
{
    "settings": {
        "number_of_shards": 3,
        "number_of_replicas": 1
    }
}

响应结果:

json
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "test_index1"
}

创建索引并设置分片值,插件可视化效果:

设置分片插件可视化效果

示例图

图解单node环境下创建index是什么样子的

图解2个node环境下replica shard是如何分配的

  1. replica shard分配:3个primary shard, 3个replica shard, 1 node。
  2. primary ---> replica同步。
  3. 读请求:primary/replica。
示例图

图解2个node环境下replica_shard是如何分配的.png

图解横向扩容

视频

day2-12-图解横向扩容_哔哩哔哩_bilibili

  • 分片自动负载均衡,分片向空闲机器转移。
  • 每个节点存储更少分片,系统资源给与每个分片的资源更多,整体集群性能提高。
  • 扩容极限:节点数大于整体分片数,则必有空闲机器。
  • 超出扩容极限时,可以增加副本数,如设置副本数为2,总共3*3=9个分片。9台机器同时运行,存储和搜索性能更强、容错性更好。
  • 容错性:只要一个索引的所有主分片在,集群就就可以运行。
示例图

图解横向扩容

当前示例图最多可挂掉6台机器,确保P0、P1、P2可以存在即可,即为R副本可以在P挂掉时存在对应的副本R进行升级为P。

图解es容错机制masteri选举,replica容错,数据恢复

视频

day2-13- 图解es容错机制 master选举,replica容错,数据恢复_哔哩哔哩_bilibili

以3分片,2副本数,3节点为例介绍。

  • master node:宕机,自动masteri选举,集群为red。
  • replica容错:新master将replica提升为primary shard,yellow。
  • 重启宕机node,master copy replica到该node,使用原有的shard并同步宕机后 的修改,green。
示例图

图解es容错机制masteri选举,replica容错,数据恢复

图解文档存储机制

9.1.数据路由

视频

day2-14-数据路由_哔哩哔哩_bilibili

9.1.1文档存储如何路由到相应分片

一个文档,最终会落在主分片的一个分片上,到底应该在哪一个分片?这就是数据

路由。

9.1.2路由算法
shell
shard hash(routing)%number_of_primary_shards

哈希值对主分片数取模。

举例:

对一个文档经行crud时,都会带一个路由值routing number。.默认为文档id(可能是

手动指定,也可能是自动生成)。

存储1号文档,经过哈希计算,哈希值为2,此索引有3个主分片,那么计算2%3=2,就算出此文档在P2分片上。

决定一个document在哪个shard.上,最重要的一个值就是routing值,默认是id,也

可以手动指定,相同的routing值,每次过来,从hash函数中,产出的hash值一定是

相同的。

无论hash值是几,无论是什么数字,对number of primary shards求余数,结果一

定是在0-number._of_primary_shards-1之间这个范围内的。0,1,2。

9.1.3手动指定routing key
json
PUT /test_index/_doc/157?routing=tom
{
    "username": "tom"
}

场景:在程序中,架构师可以手动指定已有数据的一个属性为路由值,好处是可以

定制一类文档数据存储到一个分片中。缺点是设计不好,会造成数据倾斜。

所以,不同文档尽量放到不同的索引中。剩下的事情交给s集群自己处理。

9.1.4主分片数星不可变

涉及到以往数据的查询搜索,所以一旦建立索引,主分片数不可变。

示例图

图解文档存储机制

9.2.图解文档的增删改内部机制

视频

day2-15-图解文档的增删改内部机制_哔哩哔哩_bilibili

增删改可以看做update,都是对数据的改动。一个改动请求发送到es集群,经历以下

四个步骤:

  1. 客户端选择个node发送请求过去,这个node就是coordinating node(协调节 点)。
  2. coordinating node,对documenti进行路由,将请求转发给对应的node(有 primary shard)。
  3. 实际的node上的primary shard处理请求,然后将数据同步到replica node。
  4. coordinating node,如果发现primary node和所有replica node都搞定之后, 就返回响应结果给客户端。
示例图

图解文档的增删改内部机制

9.3.图解文档的查询内部机制

视频

day2-16-图解文档的查询内部机制_哔哩哔哩_bilibili

  1. 客户端发送请求到任意个node,成为coordinating node。
  2. coordinatingnode对documenti进行路由,将请求转发到对应的node,此时会使用round-robin随机轮询算法,在primary shard以及其所有replica中随机选择一个,让读请求负载均衡。
  3. 接收请求的node返回document给coordinatingnode。
  4. coordinatingnode返回document给客户端。
  5. 特殊情况:document如果还在建立索l过程中,可能只有primary shard有,任何一个replica shard都没有,此时可能会导致无法读取到document,但是document完成索建立之后,primary shard 和 replica shard就都有了。
示例图

图解文档的查询内部机制

9.4.bulk api奇特的json格式

json
POST /_bulk
{"action":{"meta"}}\n
{"data"}\n
{"action":{"meta"}}\n
{"data"}\n

// 正常的json应该如下,但是不符合es规范
[
    {
        "action": {
            "method": "create"
        },
        "data": {
            "id": 1,
            "fieldl": "java",
            "field2": "spring"
        }
    },
    {
        "action": {
            "method": "create"
        },
        "data": {
            "id": 2,
            "fieldl": "java",
            "field2": "spring"
        }
    }
]
  1. bulk中的每个操作都可能要转发到不同的node的shard去执行。

  2. 如果采用比较良好的json数组格式。

    允许任意的换行,整个可读性非常棒,读起来很爽,es拿到用那种标准格式的

    json串以后,要按照下述流程去进行处理:

    (1) 将json数组解析为JSONArray对像,这个时候,整个数据,就会在内存中出

    现一份一模一样的拷贝,一份数据是json文本,一份数据是)SONArrayi对象;

    (2) 解析ison数组里的每个json,对每个请求中的document进行路由;

    (3) 为路由到同一个shard.上的多个请求,创建一个请求数组。100请求中有10个是到P1; (4) 将这个请求数组序列化;

    (5) 将序列化后的请求数组发送到对应的节点上去;

  3. 耗费更多内存,更多的jvm gci开销。

    我们之前提到过bulk size最佳大小的那个问题,一般建议说在几千条那样,然后

    大小在10MB左右,所以说,可怕的事情来了。假设说现在100个buk请求发送

    到了一个节点上去,然后每个请求是10MB,100个请求,就是1000MB=1GB,然

    后每个请求的json都copy一份为jsonarray对象,此时内存中的占用就会翻倍,

    就会占用2GB的内存,甚至还不止。因为弄成jsonarray之后,还可能会多搞一

    些其他的数据结构,2GB+的内存占用。

    占用更多的内存可能就会积压其他请求的内存使用量,比如说最重要的搜索请

    求,分析请求,等等,此时就可能会导致其他请求的性能急速下降。

    另外的话,占用内存更多,就会导致jva虚拟机的垃圾回收次数更多,更频繁,

    每次要回收的垃圾对象更多,耗费的时间更多,导致es的java虚拟机停止工作线

    程的时间更多。

  4. 现在的奇特格式

    json
    POST /_bulk
    {"delete":{"_index":"test_index","_id":"5"}}\n
    {"create":{"_index":"test_index","_id":"14"}}\n
    {"test_field":"test14"}\n
    {"update":{"_index":"test_index","_id":"2"}}\n
    {"doc":{"test_field":"bulk test"}}\n

    (1) 不用将其转换为json对象,不会出现内存中的相同数据的拷贝,直接按照换行符切割json;

    (2) 对每两个一组的json,读取meta,进行document路由;

    (3 )直接将对应的json发送到node上去;

  5. 最大的优势在于,不需要将json数组解析为一个)SONArrayi对象,形成一份大

    数据的拷贝,浪费内存空间,尽可能地保证性能

10.Mapping映射入门

10.1.什么是mapping映射

概念:自动或手动为index中的_doc建立的一种数据结构和相关配置,简称为

mapping映射。

插入几条数据,让es自动为我们建立一个索引:

json
PUT /website/_doc/1
{
    "post_date": "2019-01-01",
    "title": "my first article",
    "content": "this is my first article in this website",
    "author_id": 11400
}

PUT /website/_doc/2
{
    "post_date": "2019-01-02",
    "title": "my second article",
    "content": "this is my second article in this website",
    "author_id": 11400
}

PUT /website/_doc/3
{
    "post_date": "2019-01-03",
    "title": "my third article",
    "content": "this is my third article in this website",
    "author_id": 11400
}

对比数据库建表语句

mysql
create table website(
	post_date date,
	title varchar(50),
	content varchar (100),
	author_id int(11)
);

动态映射:dynamic mapping,自动为我们建立index,以及对应mapping中包含了每

个field对应的数据类型,以及如何分词等设置。

重点:我们当然,后面会讲解,也可以手动在创建数据之前,先创建idex,以及对应

的mapping。

GET /website/_mapping

响应结果:

json
{
  "website" : {
    "mappings" : {
      "properties" : {
        "author_id" : {
          "type" : "long"
        },
        "content" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "post_date" : {
          "type" : "date"
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

尝试各种搜索

json
GET /website/_search?q=2019 0条结果

GET /website/_search?q=2019-01-01 1条结果

GET /website/_search?q=post_date:2019-01-01 1条结果

GET /website/_search?q=post_date:2019 0条结果

GET /website/_search?q-third 1条结果

GET /website/_search?q=title:third 1条结果

搜索结果为什么不一致,因为es自动建立mapping的时候,设置了不同的field不同

的data type。

不同的data type的分词、搜索等行为是不一样的。所以出现了_all field和

post_date field的搜索表现完全不一样。

10.2.精确匹配与全文检索的对北比分析

10.2.1 exact value精确匹配

2019-01-01, exact value, 搜索的时候,必须输入2019-01-01,才能搜索出来

如果你输入一个01,是搜索不出来的。ype=date时,是精确匹配。

select from book where post date='2019-01-01'

10.2.2 full text全文检索

搜笔记电脑”,笔记本电脑词条会不会出现。

select*from book where name like'%笔记电脑%'

(1)缩写vs.全称:cnvs.china

(2)格式转化:like liked likes

(3)大小写:Tom vs tom

(4)同义词:like vs love

2019-01-01,20190101,搜索2019,或者01,都可以搜索出来

china,搜索cn,也可以将china搜索出来

likes,搜索ike,也可以将ikes搜索出来

Tom,搜索tom,也可以将Tom搜索出来

Iike,搜索love,同义词,也可以将ike搜索出来

就不是说单纯的只是匹配完整的一个值,而是可以对值进行拆分词语后(分词)进

行匹配,也可以通过缩写、时态、大小写、同义词等进行匹配。深入NPL,自然语义

处理。

10.3·全文检索下倒排索引核心原理快速揭秘

doc1 :I really liked my small dogs,and I think my mom also liked them.

doc2 :He never liked any dogs,so I hope that my mom will not expect me to liked him.

分词,初步的倒排索引的建立
termdoc1doc2
I**
really*
liked**
my**
small*
dogs*
and*
think*
mom**
also*
them*
He*
never*
any*
so*
hope*
that*
will*
not*
expect*
me*
to*
him*

演示了一下倒排索引最简单的建立的一个过程

搜索

mother like little dog,不可能有任何结果

mother

like

little

dog

这不是我们想要的结果。同义词mom\mother在我们人类看来是一样。想进行标

准化操作。

重建倒排索引

normalization正规化,建立倒排索引的时候,会执行一个操作,也就是说对拆分出

的各个单词进行相应的处理,以提升后面搜索的时候能够搜索到相关联的文档的概

率。

时态的转换,单复数的转换,同义词的转换,大小写的转换

mom ---> mother

liked ---> like

small ---> little

dogs ---> dog

重新建立倒排索引,加入normalization,再次用mother liked little dog搜索,就可以

搜索到了。

termdoc1doc2normalization
I**
really*
like**liked ---> like
my**
little*small ---> little
dog*dogs ---> dog
and*
think*
mother**mom ---> mother
also*
them*
He*
never*
any*
so*
hope*
that*
will*
not*
expect*
me*
to*
him*
重新搜索

搜索:mother liked little dog, 对搜索条件经行分词normalization

mother

liked-》like

little

dog

doc1和doc2都会搜索出来!

10.4.分词器analyzer

10.4.1 什么是分词器analyzer

作用:切分词语,normalization(提升recall召回率)

给es一段句子,然后将这段句子拆分成一个一个的单个的单词,同时对每个单词进

行normalization(时态转换,单复数转换)

recall,召回率:搜索的时候,增加能够搜索到的结果的数量

analyzer 3个组成部分、步骤:

  1. character filter:在一段文本进行分词之前,先进行预处理,比如说最常见的就

    是,过滤html标签(<span>hello<span>->hello), &->and ( l&you ---> I and you)。

  2. tokenizer:分词,hello you and me- --> hello,you,and,me。

  3. token filter lowercase stop word synonymom dogs ---> dog,liked --->

    like,Tom ---> tom,a/the/an->干掉,mother ---> mom,small ---> little

    stop word 停用词:了 的 呢。

一个分词器,很重要,将一段文本进行各种处理,最后处理好的结果才会拿去建立

倒排索引。

10.4.2 内置分词器的介绍

例句:Set the shape to semi--transparent by calling set_trans(S)

standard analyzer标准分词器:set,the,shape,to,semi,transparent,,by,calling,set_trans,5(默认的是standard)

simple analyzeri简单分词器:set,the,shape,to,semi,transparent,by,calling,set,trans

whitespace analyzer Set,the,shape,to,semi-transparent,by,calling,set_trans(5)

language analyzer(特定的语言的分词器,比如说,english,英语分词器):set,shape,semi,transpar,call,set_tran,5

官方文档地址:

[Built-in analyzer reference | Elasticsearch Guide 7.7] | Elastic

10.5.query string根据字段分词策略

10.5.1 query string:分词

query string必须以和index建立时相同的analyzeri进行分词

query string对exact value和full text的区别对待

如:date:exact value精确匹配

text:full text全文检索

10.5.2测试分词器
json
GET /_analyze
{
    "analyzer": "standard",
    "text": "Text to analyze 70"
}

响应结果:

json
{
  "tokens" : [
    {
      "token" : "text",
      "start_offset" : 0,
      "end_offset" : 4,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "to",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "<ALPHANUM>",
      "position" : 1
    },
    {
      "token" : "analyze",
      "start_offset" : 8,
      "end_offset" : 15,
      "type" : "<ALPHANUM>",
      "position" : 2
    },
    {
      "token" : "70",
      "start_offset" : 16,
      "end_offset" : 18,
      "type" : "<NUM>",
      "position" : 3
    }
  ]
}