前言

什么是es?

官网地址:https://www.elastic.co/cn/

es是基于Apache Lucene的开源分布式(全文)搜索引擎,,提供简单的RESTful API来隐藏Lucene的复杂性。

es除了全文搜索引擎之外,还可以这样描述它:

  1. 分布式的实时文件存储,每个字段都被索引并可被搜索
  2. 分布式的实时分析搜索引擎
  3. 可以扩展到成百上千台服务器,处理PB级结构化或非结构化数据。

es数据组织类比

Relation DB Elasticsearch
数据库(database) 索引(index)
表(tables) types
行(rows) documents
字段(columns) fields

应用场景

  • 站内搜索:主要和 Solr 竞争,属于后起之秀

    NoSQL json文档数据库:主要抢占 Mongo 的市场,它在读写性能上优于 Mongo ,同时也支持地理位置查询,还方便地理位置和文本混合查询,属于歪打正着 (对比测试参见:http://blog.quarkslab.com/mongodb-vs-elasticsearch-the-quest-of-the-holy-performances.html)
  • 监控:统计以及日志类时间序的数据的存储和分析以及可视化,这方面是引领者
  • 国外:Wikipedia使用 ES 提供全文搜索并高亮关键字、StackOverflow结合全文搜索与地理位置查询、Github使用Elasticsearch检索1300亿行的代码
  • 国内:百度(在casio、云分析、网盟、预测、文库、直达号、钱包、风控等业务上都应用了ES,单集群每天导入30TB+数据,总共每天60TB+)、新浪 (见大数据架构--log),阿里巴巴、腾讯等公司均有对ES的使用
  • 使用比较广泛的平台ELK(ElasticSearch, Logstash, Kibana)

核心概念

集群

集群(Cluster): 包含一个或多个具有相同 cluster.name 的节点.

ElasticSearch 的主旨是随时可用和按需扩容。 而扩容可以通过购买性能更强大( 垂直扩容 ,或 纵向扩容 ) 或者数量更多的服务器( 水平扩容 ,或 横向扩容 )来实现。

  1. 集群内节点协同工作,共享数据,并共同分担工作负荷。
  2. 由于节点是从属集群的,集群会自我重组来均匀地分发数据.
  3. cluster Name是很重要的,因为每个节点只能是群集的一部分,当该节点被设置为相同的名称时,就会自动加入群集。
  4. 集群中通过选举产生一个mater节点,它将负责管理集群范畴的变更,例如创建或删除索引,添加节点到集群或从集群删除节点。master 节点无需参与文档层面的变更和搜索,这意味着仅有一个 master 节点并不会因流量增长而成为瓶颈。任意一个节点都可以成为 master 节点。我们例举的集群只有一个节点,因此它会扮演 master 节点的角色。
  5. 作为用户,我们可以访问包括 master 节点在内的集群中的任一节点。每个节点都知道各个文档的位置,并能够将我们的请求直接转发到拥有我们想要的数据的节点。无论我们访问的是哪个节点,它都会控制从拥有数据的节点收集响应的过程,并返回给客户端最终的结果。这一切都是由 Elasticsearch 透明管理的

节点(node)

一个节点是一个逻辑上独立的服务,可以存储数据,并参与集群的索引和搜索功能, 一个节点也有唯一的名字,群集通过节点名称进行管理和通信.

索引(Index)

索引与关系型数据库实例(Database)相当。索引只是一个 逻辑命名空间,它指向一个或多个分片(shards),内部用Apache Lucene实现索引中数据的读写

文档类型(Type)

相当于数据库中的table概念。每个文档在ElasticSearch中都必须设定它的类型。文档类型使得同一个索引中在存储结构不同文档时,只需要依据文档类型就可以找到对应的参数映射(Mapping)信息,方便文档的存取

6.x 之后废弃

文档(Document)

相当于数据库中的row, 是可以被索引的基本单位。例如,你可以有一个的客户文档,有一个产品文档,还有一个订单的文档。文档是以JSON格式存储的。在一个索引中,您可以存储多个的文档。请注意,虽然在一个索引中有多分文档,但这些文档的结构是一致的,并在第一次存储的时候指定, 文档属于一种 类型(type),各种各样的类型存在于一个 索引 中

5.x 以及之前的结构

6.x 之后结构

Mapping

定义一个文档以及其所包含的字段如何被存储和索引的方法

相当于数据库中的schema,用来约束字段的类型,不过 Elasticsearch 的 mapping 可以自动根据数据创建

核心简单域类型

Elasticsearch 支持如下简单域类型:

  • 字符串: string
  • 整数 : byte, short, integer, long
  • 浮点数: float, double
  • 布尔型: boolean
  • 日期: date

当你索引一个包含新域的文档—​之前未曾出现-- Elasticsearch 会使用 动态映射 ,通过JSON中基本数据类型,尝试猜测域类型,使用如下规则:

示例 类型
JSON type type
布尔型: true 或者 false boolean
整数: 123 long
浮点数: 123.45 double
字符串,有效日期: 2014-09-15 date
字符串: foo bar string

这意味着如果你通过引号( "123" )索引一个数字,它会被映射为 string 类型,而不是 long 。但是,如果这个域已经映射为 long ,那么 Elasticsearch 会尝试将这个字符串转化为 long ,如果无法转化,则抛出一个异常。

分片(shard)

是 工作单元(worker unit) 底层的一员,用来分配集群中的数据,它只负责保存索引中所有数据的一小片。

分布式原理:shard = hash(routing) % number_of_primary_shards

  1. 分片是一个独立的Lucene实例,并且它自身也是一个完整的搜索引擎。
  2. 文档存储并且被索引在分片中,但是我们的程序并不会直接与它们通信。取而代之,它们直接与索引进行通信的
  3. 把分片想象成一个数据的容器。数据被存储在分片中,然后分片又被分配在集群的节点上。当你的集群扩展或者缩小时,elasticsearch 会自动的在节点之间迁移分配分片,以便集群保持均衡
  4. 分片分为 主分片(primary shard) 以及 从分片(replica shard) 两种。在你的索引中,每一个文档都属于一个主分片
  5. 从分片只是主分片的一个副本,它用于提供数据的冗余副本,在硬件故障时提供数据保护,同时服务于搜索和检索这种只读请求
  6. 索引中的主分片的数量在索引创建后就固定下来了,但是从分片的数量可以随时改变。
  7. 一个索引默认设置了5个主分片,每个主分片有一个从分片对应

        (集群结构图)

架构图

从下往上来分析ElasticSearch 架构图

  • Gateway代表ElasticSearch索引的持久化存储方式。包含索引信息,ClusterState(集群信息),mapping,索引碎片信息,以及transaction log等。

在Gateway中,ElasticSearch默认先把索引存储在内存中,然后当内存满的时候,再持久化到Gateway里。当ES集群关闭或重启的时候,它就会从Gateway里去读取索引数据。比如LocalFileSystem和HDFS、AS3等。

  • DistributedLucene Directory,它是Lucene里的一些列索引文件组成的目录。它负责管理这些索引文件。包括数据的读取、写入,以及索引的添加和合并等。
  • River,代表是数据源。是以插件的形式存在于ElasticSearch中。()
  • Mapping,映射的意思,非常类似于静态语言中的数据类型。比如我们声明一个int类型的变量,那以后这个变量只能存储int类型的数据。

比如我们声明一个double类型的mapping字段,则只能存储double类型的数据。

Mapping不仅是告诉ElasticSearch,哪个字段是哪种类型。还能告诉ElasticSearch如何来索引数据,以及数据是否被索引到等。

  • Search Moudle,搜索模块
  • Index Moudle,索引模块
  • Disvcovery,主要是负责集群的master节点发现。比如某个节点突然离开或进来的情况,进行一个分片重新分片等。这里有个发现机制。

发现机制默认的实现方式是单播和多播的形式,即Zen,同时也支持点对点的实现。另外一种是以插件的形式,即EC2。

  • Scripting,即脚本语言。包括很多。如mvel、js、python等。
  • Transport,代表ElasticSearch内部节点,代表跟集群的客户端交互。包括 Thrift、Memcached、Http等协议
  • RESTful Style API,通过RESTful方式来实现API编程。
  • 3rd plugins,代表第三方插件。
  • Java(Netty),是开发框架。
  • JMX,是监控。

写入\读取原理

https://blog.csdn.net/laoyang360/article/details/84727820?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

es读工作流程

查询

  1. GET某一条数据,当你写入了某个document的时候,这个document会给你自动分配一个id doc id
  2. 查询的时候通过docid去进行查询, 也就是根据doc id进行hash路由到一个随机的shard节点上
  3. 这个时候它就作为协调节点,他会根据这个docid去查询到这个doc在哪个节点上,(因为我们知道读的话,shard和replica都可以去读)这时候就采用随机轮询的算法,让客户端在shard和replica中随机进行读取,读取完后,接受请求的协调节点对数据进行返回

搜索

  1. 客户端发送一个请求到一个协调节点上,因为不知道doc的id,不知道数据存在哪里,这个时候呢,就会将搜索的请求转发到所有的shard对应的primary shard或replica shard上

比如我有三个shard也就意味着我有三个replica,因为是读,所以,转发到三个节点上对应的shard或replica上就可以了

  1. 每个shard将自己的搜索的结果其实就是通过内容查询出来和请求内容相关的doc id(通过倒排索引)返回给协调节点

比如说我现在搜索的是java,它就会进行对比,进行判断,把带有java的这些内容的docid返回给协调节点,这时候协调节点就会收到类似于“java真好”,“java真不好”的这些doc 的id

  1. 由协调节点去拉去到此docid所对应的document的完整的数据拉取回来,然后进行数据的合并,排序,分页等操作,产出最终的结果,然后由协调节点返回给客户端

es的写流程

首先会对你要写的这条数进行hash,然后随机分发到一个节点,去执行写操作

通过hash路由到这个节点之后,数据首先写到一个buffer中(缓冲区),这时候,是搜索不到数据的,只有等1秒后,数据会从buffer中refresh到一个新的segmentfile中并持久化到磁盘。

注意点

  1. 如果buffer快满的时候,也会将里面的数据存储到segmentfile中
  2. 清空buffer,其实并非将segmentfile持久化到磁盘需要一秒时间,而是首先会将segmentfile写入os cache中,注:os cache(操作系统的内存),然后再将segmentfile持久化到磁盘中,写入oscache的同时,建立倒排索引,这时就可以供客户端进行访问了,这就是为什么说es是准实时的了,默认是每隔1秒refresh一次的,所以es是准实时的,因为写入的数据1秒之后才能被看到

当然我们可以通过es的restful api或者java api,手动执行一次refresh操作,就是手动将buffer中的数据刷入os cache中,让数据立马就可以被搜索到。

  1. translog,每写入一条数据,就会写入一条translog到os cache中去,每个五秒就会持久化一条translog日志文件到磁盘中去,这是为了防止电脑突然卡住,或者突然宕机造成的数据丢失问题(内存中的数据还没来的及持久化,就宕机了),如果出现这种情况,这时候,重启机器,就会读取translog到buffer和oscache中进行数据的恢复了,但是每次一条数据写入buffer,同时会写入一条日志到translog日志文件中去,所以这个translog日志文件是不断变大的。
  2. 当translog日志文件大到一定程度的时候,就会执行commit操作

整个commit的过程叫做flush操作,commit操作发生第一步,就是将buffer中现有数据refresh到os cache中去,然后将commit point这个文件持久化到磁盘中,这个文件记录了,这个时间点之前,你刷到os cache的所有的segmentfile,清空buffer 然后强行将os cache中所有的数据全都一个一个的通过segmentfile的形式,持久到磁盘上去,然后把translog文件删掉清空,再开一个空的translog文件,

translog是默认30分钟执行一次flush,一般我们不叫作commit操作,只是类似于一个提交的操作,我把它理解为commit,在es中的flush操作,就对应着commit的全过程。我们也可以通过es api,手动执行flush操作,手动将os cache中的数据fsync强刷到磁盘上去,记录一个commit point,清空translog日志文件

  1. translog其实也是先写入os cache的,默认每隔5秒刷一次到磁盘中去,所以默认情况下,可能有5秒的数据会仅仅停留在buffer或者translog文件的os cache中,如果此时机器挂了,会丢失5秒钟的数据。但是这样性能比较好,最多丢5秒的数据。也可以将translog设置成每次写操作必须是直接fsync到磁盘,但是性能会差很多

删除更新的原理

问题

每一次删除,都需要从集群中找到存储那个数据的节点在进行删除吗?

Es删除原理

如果是删除请求的话,提交的时候会生成一个.del文件,里面将某个doc标识为deleted状态,那么搜索的时候根据.del文件就知道这个doc被删除了,客户端搜索的时候,发现数据在.del文件中标志为删除就不会搜索出来了

Es更新原理

  1. 将原来的doc标识为deleted状态,然后重新写入一条数据。
问题

那么这并不是一个物理删除,那么物理删除实在什么时候呢?

  1. mege(合并)

buffer每次refresh一次,就会产生一个segment file,所以默认情况下是1秒钟一个segment file,segment file会越来越多,此时会定期执行merge

每次merge的时候,会将多个segment file合并成一个,同时这里会将标识为deleted的doc给物理删除掉,然后将新的segment file写入磁盘,这里会写一个commit point,标识所有新的segment file,然后打开segment file供搜索使用,同时删除旧的segment file

总结

es里的写流程,有4个底层的核心概念,refresh、flush、translog、merge 需要好好的去理解

运用

官方文档

gas油站加油汇总重构

  1. 读取mysql binlog 同步数据到es中

不能直接读取bing log,通过Canal来读取数据的

https://www.jianshu.com/p/87944efe1005

  1. 监听binlog event 事件,修改es数据
  2. mysql和es结合
http://x.x.x.x:9200/gas_prod_gas_history/_search

{"size":0,"query":{"bool":{"filter":{"bool":{"must":[{"range":{"oil_time":{"gte":"2020-2-12 00:00:00","lt":"2020-8-12 23:59:59"}}},{"terms":{"station_id":["cb23830cfe4066b4691fe75225212cb2","1ee7b6b3d7443617fe858f043bd8025b","34467af833ad5288e17171f8bb67888a","0aedd6b3f118f4dc5aba132a99145445","935262dd5e6a91856b403e81a0eaa5dc","1eca1cf9e7f0ec49d5a920ae975a02f7","f045592cdc8f927cd006473264b4a044","109509d5dc74b2dceff7fce054c730a6","90716c968d5bd7b3f6fab711828ca113","251c01653e6ccaba488d55575985fb27","0a6eebe2243fc77c83fa06075f5783da","530dcdd8bd71410285951ec6e7bbd824","dbb76a120b25ff79f3d71d5ee8711a0d","ed957f8e5f096d3f704c381eab27d2d4","987250e2a8f31929d14cd19b307851c4","09f733dc1b12688550ac835b0523fb87","7888bee53e6dc88f456040205e417296","df2af318c4f5d653876719b042549ede","db0bd2052f6026f92f2c8d5ae8189fad","f7b3d02ae64160d85351c55ffce3f30a"]}},{"terms":{"log_type":["1111","1112","1113"]}}]}}}},"aggs":{"group_by_station_id":{"terms":{"script":"doc['station_id'].values +'##'+ doc['provice_code'].values+'##'+ doc['city_code'].values","size":2147483647},"aggs":{"sum_num_count":{"sum":{"field":"oil_num"}},"sales":{"date_histogram":{"field":"oil_time","interval":"1d","format":"yyyy-MM-dd"},"aggs":{"sum_oil_num":{"sum":{"field":"oil_num"}}}}}}}}

碰到的问题

聚合之后不能分页码

whereIn 个数不能超过1024(默认)

group by之后,limit不好用

//查询硬件上报流水

 $builder = self::select('pcode', 'station_id', 'oil_name', 'oil_type', 'oil_time')
->where($where); //whereIn 条件拼装
foreach ($whereInArr as $key => $values) {
$builder = $builder->whereIn($key, $values);
}
$builder->groupBy(\DB::raw('pcode,station_id,oil_type,oil_name'))
->limit(10000); $res = self::$es->queryBySql($builder); //发现返回的结果为空 {
"from": 0,
"size": 0,
"query": {
"bool": {
"filter": [
{
"bool": {
"must": [
{
"bool": {
"must": [
{
"range": {
"updatetime": {
"from": "2020-09-01 01:10:00",
"to": null,
"include_lower": true,
"include_upper": true,
"boost": 1.0
}
}
},
{
"range": {
"updatetime": {
"from": null,
"to": "2020-09-01 23:59:59",
"include_lower": true,
"include_upper": true,
"boost": 1.0
}
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"_source": {
"includes": [
"pcode",
"station_id",
"oil_name",
"oil_type",
"oil_time"
],
"excludes": [ ]
},
"stored_fields": [
"pcode",
"station_id",
"oil_name",
"oil_type",
"oil_time"
],
"aggregations": {
"pcode": { //pcode 在最外层,包住了其他条件,limit 也只对pcode生效了
"terms": {
"field": "pcode",
"size": 10000,
"min_doc_count": 1,
"shard_min_doc_count": 0,
"show_term_doc_count_error": false,
"order": [
{
"_count": "desc"
},
{
"_key": "asc"
}
]
},
"aggregations": {
"station_id": {
"terms": {
"field": "station_id",
"size": 10,
"min_doc_count": 1,
"shard_min_doc_count": 0,
"show_term_doc_count_error": false,
"order": [
{
"_count": "desc"
},
{
"_key": "asc"
}
]
},
"aggregations": {
"oil_type": {
"terms": {
"field": "oil_type",
"size": 10,
"min_doc_count": 1,
"shard_min_doc_count": 0,
"show_term_doc_count_error": false,
"order": [
{
"_count": "desc"
},
{
"_key": "asc"
}
]
},
"aggregations": {
"oil_name": {
"terms": {
"field": "oil_name",
"size": 10,
"min_doc_count": 1,
"shard_min_doc_count": 0,
"show_term_doc_count_error": false,
"order": [
{
"_count": "desc"
},
{
"_key": "asc"
}
]
}
}
}
}
}
}
}
}
}
}

Es 学习笔记 (1)的更多相关文章

  1. OpenGL ES学习笔记(三)——纹理

    首先申明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. <OpenGL ES学习笔记( ...

  2. OpenGL ES 学习笔记 - Overview - 小旋的博客

    移动端图形标准中,目前 OpenGL ES 仍然是比较通用的标准(Vulkan 则是新一代),这里新开一个系列用于记录学习 OpenGL ES 的历程,以便查阅理解. OverView OpenGL ...

  3. OpenGL ES学习笔记(二)——平滑着色、自适应宽高及三维图像生成

    首先申明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. <Android学习笔记--O ...

  4. ES学习笔记

    ES学习 1. 安装 1.1 ES 安装配置 curl -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5. ...

  5. OpenGL ES学习笔记(一)——基本用法、绘制流程与着色器编译

    首先声明下,本文为笔者学习<OpenGL ES应用开发实践指南(Android卷)>的笔记,涉及的代码均出自原书,如有需要,请到原书指定源码地址下载. 在Android.iOS等移动平台上 ...

  6. 【ES】elasticsearch学习笔记

    ES学习 1 优势 1.1 简单 1.1.1 相比Solor配置部署等非常简单 1.2 高效 1.2.1 ES使用Netty作为内部RPC框架,Solor使用Jetty 1.3 插件化 1.3.1 E ...

  7. Oracle学习笔记三 SQL命令

    SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)  

  8. TEX学习笔记

    整理在这里, 方便以后容易查找. 毕竟每个tex的模板有些不一样. Beamer: Latex beamer 学习总结 http://blog.sina.com.cn/s/blog_6cf921f30 ...

  9. Android学习笔记(二)——探究一个活动

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 活动(Activity)是最容易吸引到用户的地方了,它是一种可以包含用户界面的组件,主要用于和用户进行交互.一 ...

随机推荐

  1. Eplan创建符号详细解说

    如何创建新的符号库以及在项目里面导入这个新的符号库 这个就不详细的赘述了 网上很多教程 和我一样的萌新可以参考 https://wenku.baidu.com/view/18c16641e45c3b3 ...

  2. Golang 汇编asm语言基础学习

    Golang 汇编asm语言基础学习 一.CPU 基础知识 cpu 内部结构 cpu 内部主要是由寄存器.控制器.运算器和时钟四个部分组成. 寄存器:用来暂时存放指令.数据等对象.它是一个更快的内存. ...

  3. 【PHP库】phpseclib - sftp远程文件操作

    需求场景说明 对接的三方商家需要进行文件传输,并且对方提供的方式是 sftp 的服务器账号,我们需根据他们提供的目录进行下载和上传指定文件. 安装 composer require phpseclib ...

  4. 「POJ 3666」Making the Grade 题解(两种做法)

    0前言 感谢yxy童鞋的dp及暴力做法! 1 算法标签 优先队列.dp动态规划+滚动数组优化 2 题目难度 提高/提高+ CF rating:2300 3 题面 「POJ 3666」Making th ...

  5. Luogu1038 神经网络 (拓扑排序)

    拓扑排序,裸的,水的. 第一发:题读错,输出错,输入错,到处错 \(\longrightarrow\) 40pts (excuse me ?) 第二发:漏了输入层特判 \(\longrightarro ...

  6. 数据库运维之路——关于tempdb暴增实战案例

    转眼间,2021年的第一个季度已经到了最后一个月了,由于疫情原因,最近一段时间一直在北京,基本上没有出差,每天上班下班的日子感觉时间过的好快,新的一年继续努力奋斗啊. 仔细回想一下,自己踏入到sql ...

  7. C#基础_类与对象的关系

    类不占内存,对象占内存

  8. 【HTML】学习路径2-设置文档类型、网页编码、文件注释

    第一章:设置文档类型 我们通常在html文件最前面写一行: <!DOCTYPE html> 这玩意有啥用? https://developer.mozilla.org/zh-CN/docs ...

  9. 「题解报告」 P3167 [CQOI2014]通配符匹配

    「题解报告」 P3167 [CQOI2014]通配符匹配 思路 *和?显然无法直接匹配,但是可以发现「通配符个数不超过 \(10\) 」,那么我们可以考虑分段匹配. 我们首先把原字符串分成多个以一个通 ...

  10. 【设计模式】Java设计模式 - 动态代理

    [设计模式]Java设计模式 - 动态代理 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 一个有梦有戏的人 @怒放吧德德 最近工作比较忙,没啥时间学习 目录 [设计模 ...