L ==> E & L & K ==> G
三剑客:Elastic Stack
在学习ELK前,先对 Lucene作基本了解。
今天才知道关系型数据库的索引是 B-Tree,罪过...
- 减少磁盘寻道次数 ---> 提高查询性能
Lucene
原始数据基础查询 + 原始数据聚合查询
- 物化视图
- 实时聚合
核心:反向倒排索引
1 2 3 | //关键词 document ---> term ---> posting list<docid> term dictionary ---> term index |
- Term Index:以 FST(finite state transducers)形式保存
- Term Dictionary: 以分 block 形式式保存,block 内公共前缀压缩 term
联合索引查询
- skip list 数据结构:同时遍历 A和 B的 posting list,互相 skip
- Frame Of Reference编码压缩 docid
- bitset 数据结构:对 A和 B两个 filter分别求出 bitset,对两个 bitset做 AND 操作
- Roaring Bitmap
关于两者的性能比较,参见:Frame of Reference and Roaring Bitmaps
Nested Document
定期行数据合并:子文档 ---> 父文档
DocValues
主存储按列组织,随机读操作很快
- 底层读文件方式:memory mapped byte buffer(mmp)
时间序列数据库秘密:https://segmentfault.com/a/1190000003502849?mType=Group
E:Elasticsearch
基于Lucene实现,接近实时(NRT,Near Realtime)的搜索平台,基于 JSON的分布式搜索和分析引擎
- 开源分布式搜索与数据分析引擎
- 面向文档型,文档Json序列化
- PB 级的数据处理
- 开箱即用,RESTful WebApi:Json
官网:https://www.520mwx.com/view/44635,版本演进:5.x --> 6.x --> 7.x
1 2 3 4 5 6 7 | 从 5 .x支持拆分成text和keyword,在 6 .x废弃string 在 7 .x废弃TransportClient,建议High-level-rest-client 在 7 .x使用默认的_doc作为type,在 8 .x移除type 从 7 .x默认节点名称为主机名,分片数改为 1 在 7 .x默认自带jdk 从 7 .x Kibana支持全局开启“黑暗”模式 从 7 .x时间戳从毫秒级支持至纳秒级 |
- Weak-AND算法:取 TOP-N 结果集,估算命中记录数
- 间隔查询(Intervals query)
关于7.x版本参见:Elastic Stack 7.0.0, Breaking changes in 7.0
ES每日持续性能监控:https://benchmarks.elastic.co/index.html
基本概念
1 2 | 关系数据库 --> 数据库 --> 表 --> 行(Rows) --> 列(Columns) Elasticsearch --> 索引(Index) --> 类型(type) --> 文档(Docments) --> 字段(Fields) |
其中,document 是可以被索引的基本信息单元,Index 名字务必小写 。
基本操作:GET-查询,POST-更新,PUT-增加,DELETE-删除
- 倒排索引:词条-文档,segment在硬盘
- 顺排索引:文档-词条,fielddata堆内存,通过format参数控制是否启用字段的fielddata特性,loading属性控制fielddata加载到内存的时机
最佳场景:1、检索 2、统计监控 3、(日志)分析
- 新浪ES 如何分析处理32亿条实时日志:http://dockone.io/article/505
- 阿里ES 构建挖财自己的日志采集和分析体系:http://afoo.me/columns/tec/logging-platform-spec.html
- 有赞ES 业务日志处理:http://tech.youzan.com/you-zan-tong-ri-zhi-ping-tai-chu-tan/
- ES实现站内搜索:http://www.wtoutiao.com/p/13bkqiZ.html
1 | docid --> block --> Segment --> Shards/Replicas --> Index |
分片 number_of_shards:
- 支持水平分割/扩展内容容量
- 支持在分片之上进行分布式、并行操作
复制 number_of_replicas:
- 在分片/节点失败的情况下,提供了高可用性
- 在所有的复制上并行运行,扩展搜索量/吞吐量
默认情况下,Elasticsearch中的每个索引配置5个主分片和每个分片的1个复制
1 | 节点数 <= 主分片数 *(副本数+1) |
shards索引创建后不可更改,replicas可用 update-index-settings API 动态修改
1 2 3 | PUT /myindex/_settings { "number_of_replicas" : 1 } |
Mapping映射
动态映射 --> 定制映射
- 创建索引同时创建映射
- 先创建索引,再创建映射
mapping一经创建无法修改,若要修改需重新建立索引和定义映射,具体方法:
step1.给现有索引定义别名,并把现有索引指向该别名,PUT /现有索引/_alias/别名A
step2.新创建一个索引,定义新的映射关系
step3.将别名指向新的索引,并且取消之前索引的执行
1 2 3 4 5 6 7 | POST /_aliases { "actions" :[ { "remove" : { "index" : "现有索引名" , "alias" : "别名A" }}, { "add" : { "index" : "新建索引名" , "alias" : "别名A" }} ] } |
性能:实现索引的平滑过渡,并且是零停机。
索引+检索
精髓:一切设计都是为了提高搜索的性能
- Java API
- HTTP Restful API
【强烈推荐】:Elasticsearch 的性能优化,亿级 Elasticsearch 性能优化
自动创建索引
1 2 3 | action.auto_create_index: false //禁止自动创建索引 index.mapper.dynamic: false //禁止自动映射 PUT http: //host:port/index_name/ + index_configuration //手动建立索引 |
通常设置为true即可
1 2 3 4 5 6 7 8 | PUT /_cluster/settings { "persistent" : { "action" : { "auto_create_index" : "true" } } } |
其中,indiex_configuration用于定义索引的配置信息:映射节(mappings)和配置节(settings)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | PUT faceafvmain-201905{ "settings" :{ "number_of_shards" :5, "number_of_replicas" :0 }, "mappings" :{ "articles" :{ "dynamic_date_formats" :[ "yyyy-MM-dd" , "yyyyMMdd" ], "dynamic" : "false" , "properties" :{ "articleid" :{ "type" : "long" , "index" : "not_analyzed" , }, "title" :{ "type" : "string" , "index" : "analyzed" , }, "author" :{ "type" : "string" , "index" : "analyzed" , }, "content" :{ "type" : "string" , "index" : "analyzed" , }, "postat" :{ "type" : "date" , "format" :[ "yyyy-MM-dd" , "yyyyMMdd" ], "index" : "not_analyzed" , } } } } } |
若未手动指定时间戳,_source中也不存在时间戳字段,建议指定mapping中的_timestamp设置为enable
1 2 3 4 5 6 7 8 9 | PUT myindex { "mappings" : { "mytype" : { "_timestamp" : { "enabled" : true } } } } |
索引使用问题总结
[1]. 建议使用double,float类型存储在es中可能存在精度损失
[2]. 索引数据插入与更新
1 2 | 插入: "result" : "created" , "_version" : 1 更新: "result" : "updated" , "_version" : 2 |
[3]. IP类型:支持ipv4/ipv6
文档刷新与过期时间
TTL时间间隔以_timestamp为基准
若数据操作索引后要马上能搜到,可手动执行refresh操作:只要在API后面添加 refresh=true ,但不建议
Pipeline Aggregation
先了解下聚合
- metric:类似sum、avg等
- bucket:类似group by
可优化网络传输量
- Shard本地聚合 ---> 多Shards最终聚合
- Hyperloglog算法
Pipeline Aggregation 作为聚合的 plus版本
ElasticSearch使用列式存储实现排序和聚合查询
elasticsearch安装
推荐 ES 6.x版本,暂用 -v6.8.0 & -v6.2.0
鉴于 .net Framework生产最高 4.6,也采用 ES v6.2.0版本
同时考虑 Java技术栈中 NodeClient已过期,当前流行的 Transport Client在 7.x版本开始将不再支持
运行:elasticsearch.bat
1 2 | 9300:java/.Net 程序访问的端口(tcp) 9200:浏览器、postman 访问端口(http) |
默认 ES只允许本机访问,修改 config/elasticsearch.yml文件,修改 network.host
为 0.0.0.0或指定IP,再重启即可
建议在文件最后新增如下配置
1 2 3 4 | http.cors.enabled: true //是否支持跨域 http.cors.allow-origin: "*" //支持所有域名 (以上2个配置解决:使用 Head 插件连接不上集群) node.master: true node.data: true |
注意,根据规划 ES 6.x版每个 Index只允许包含一个 Type,7.x版将会彻底移除 Type:Removal of mapping types
若遇报错
1 2 | ERROR: bootstrap checks failed system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk |
则在配置文件中新增
1 2 | bootstrap.memory_lock: false bootstrap.system_call_filter: false |
常用命令
1 2 3 4 5 6 7 8 9 | http: //localhost:9200/_cat/indices?v //当前结点的所有Index http: //localhost:9200/_mapping?pretty=true //当前Index包含的所有Type http: //ip:9200/_nodes #查看节点信息 http: //ip:9200/_template #查看模板 GET /Index/Type/_search?pretty #返回索引记录,默认size= 10 GET /index_name/_mapping/type_name #查询映射 GET /index_Name/_mapping #获取映射关系 GET /_all/_mapping/ #获取集群内的所有映射关系 |
安装教程:https://blog.csdn.net/weixin_42633131/article/details/82902812
elasticsearch-head插件
下载地址:https://github.com/mobz/elasticsearch-head
在 Gruntfile.js的 connect配置项中新增 hostname:'*',
注意,es5 以上版本安装 head需要安装 node和 grunt
- node.js -v8.11.3
- grunt -v1.3.2
重点了解下grunt
JavaScript 任务运行器,基于 Node.js的项目构建工具,可以进行打包压缩、测试、执行等工作
1 2 | npm install -g grunt-cli #全局安装 grunt -version #查看版本号 |
head 插件通过 grunt 启动。
安装教程:https://www.cnblogs.com/wymbk/p/5766064.html
head/_site/app.js 下配置修改
1 2 | #这里改成es的IP和端口 this .base_uri = this .config.base_uri || this .prefs.get( "app-base_uri" ) || "http://99.6.150.141:9200" ; |
暂时未用到,先 mark 备用。
1 2 | 安装:npm install 运行:grunt server 或 npm run start |
安装时若出现 FetchError: request to https://registry.npmjs.com/grunt-karma failed,reason connect EACCES 104.16.27.35:443
解决:更新npm:npm install -g npm
若出现 notarget No matching version found for grunt-karma@2.0.0
解决:重新安装grunt
若出现 error phantomjs-prebuilt@2.1.16 install: 'node install.js'
解决:执行npm install -g phantomjs-prebuilt@2.1.16 --ignore-scrip
相关信息可参考:npm install error | stackoverflow
至于出现 Local Npm module "grunt-contrib-jasmine" not found. Is it installed?
解决:可以忽略,尚不影响使用,也可以安装 npm install grunt-contrib-jasmine解决
注意,出现 connect EACCES 或 connect ETIMEDOUT,优先启用重试大法命令。
安装教程:https://blog.csdn.net/qq_42875667/article/details/87450394
ik分词器
ES 内置分词器(standard、simple)效果不理想,推荐插件安装:IK Analyzer v3.0
- 面向Java的公用分词组件,独立于Lucene项目
- 正向迭代最细粒度切分算法
- 多子处理器分析模式
选择与 ES配套的版本即可,下载地址,或选择其他分词器 smartcn
- analyzer:字段文本的分词器
- search_analyzer:搜索词的分词器
- ik_max_word:插件ik提供的分词器,可对文本进行最大数量的分词
重命名为 ik,放在 elasticsearch\plugins 目录下重启 es 即可
- IKAnalyzer.cfg.xml:扩展词和停用词文件
分词在线测试地址:grokdebug
注意,原始文本作为单个分词最大长度默认 32766Bytes,可以通过 ignore_above 属性设置字符个数
ES中一个字段不能同时支持全文和聚合搜索,除非采用如下方式:参见
1 2 3 4 5 6 7 8 | "url" : { "type" : "string" , "analyzer" : "simple" , "fields" : { "keyword" : { "type" : "keyword" , "ignore_above" : 256 } } }, |
基本使用
几个重要的配置
1 2 3 4 5 | # (master_eligible_nodes / 2) + 1 discovery.zen.minimum_master_nodes:集群主节点最小可见数量,为提高集群的可用性,避免集群脑裂 discovery.zen.ping.unicast.hosts:节点发现机制,unicast通信方式 discovery.zen.ping_timeout:发现过程中的等待时间,默认3秒 bootstrap.memory_lock:ture 启用Elasticsearch的内存锁定,避免内存被OS换出 |
L:Logstash
动态数据收集管道,日志解析引擎,拥有可扩展的插件生态系统。
官网:https://www.elastic.co/cn/products/logstash
下载版本与 es一致即可:下载地址
安装教程:
- 组成部分:input、filter、output、codec
- Grok:filter核心插件,文本格式字符串 ---> 结构化数据 + 正则表达式:测试地址
filter的ruby插件待学习...
基本使用
Shipper Logstash --> Redis --> Indexer Logstash --> Elasticsearch
K:Kibana
分析和可视化平台, 统计 。官网:https://www.elastic.co/cn/products/kibana
默认 Kibana只允许本机访问,修改 config/kibana.yml文件,修改 server.host 为 0.0.0.0或指定IP,再重启即可
1 | http: //ip:5601/app/kibana#/home/tutorial_directory/sampleData?_g=() #添加kibana样例数据 |
基本使用
REST访问模式:<REST Verb>/<Index>/<Type>/<ID>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | http: //localhost:5601/status #状态信息 GET _cluster/health GET /_cat/health?v #集群健康信息 GET /_cat/nodes?v #集群中结点列表 GET /_cat/indices?v #集群中索引列表 GET _cat/plugins GET / #集群属性信息 GET /_all/_settings #索引配置信息 GET /index_c/_settings PUT index_c/_settings { #配置索引参数 "index" :{ "max_result_window" :50000 } } |
删除
1 2 3 4 5 6 7 8 9 10 11 12 | DELETE /index_name DELETE /index_name/type_name/0gt3dWwBJmcVNuQWEmyy POST /index_name/type_name/_delete_by_query { ---按条件删除数据 "query" :{ "term" : { "PhoneNumber" : { "value" : "12304567890" } } } } |
快捷键
1 | ctrl+enter:提交当前请求 |
建议入库 ES 的对象包含 Date 字段,否则 Create Index Pattern 时无可用字段可选,报错
1 | The indices which match this index pattern don't contain any time fields. |
日期字段尽量兼容多种格式
1 2 3 4 5 | "date" : { "type" : "date" , "format" : "yyyy-MM-dd'T'HH:mm:ss.SSSZ||yyyy/MM/dd'T'HH:mm:ss.SSSZ||yyyy-MM-dd HH:mm:ss.SSS||yyyy/MM/dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss||yyyy/MM/dd HH:mm:ss" , "copy_to" : "All_Info" } |
reindex
给出一个简单的迁移示例
1 2 3 4 5 6 7 8 | POST _reindex { "source" : { "index" : "index_b" }, "dest" : { "index" : "index_a" }, "script" :{ "lang" : "painless" , "source" : "ctx._source.date=ctx._source.date.replace('/','-').replace(' ','T');if(!ctx._source.date.contains('.')){ctx._source.date=ctx._source.date+'.100+0800';} else if(!ctx._source.date.contains('+')){ctx._source.date=ctx._source.date+'+0800';}" } } |
其中,源、目的索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | PUT index_a { "order" : 1, "index_patterns" : [ "auto-afvapp*" ], "settings" : { "index" : { "max_result_window" : "2147483647" , "refresh_interval" : "10s" , "number_of_shards" : "2" , "number_of_replicas" : "1" } }, "mappings" : { "afvapp" : { "dynamic" : false , "properties" : { "uid" : { "type" : "keyword" }, "date" : { "type" : "date" , "format" : "yyyy-MM-dd'T'HH:mm:ss.SSSZ||yyyy/MM/dd'T'HH:mm:ss.SSSZ||yyyy-MM-dd HH:mm:ss.SSS||yyyy/MM/dd HH:mm:ss.SSS||yyyy-MM-dd HH:mm:ss||yyyy/MM/dd HH:mm:ss" , "copy_to" : "All_Info" }, "errmsg" : { "type" : "text" , "fields" : { "keyword" : { "type" : "keyword" , "ignore_above" : 1024 } } } } } }, "aliases" : {} } PUT index_b { "order" : 1, "index_patterns" : [ "auto-afvapp*" ], "settings" : { "index" : { "max_result_window" : "2147483647" , "refresh_interval" : "10s" , "number_of_shards" : "2" , "number_of_replicas" : "1" } }, "mappings" : { "afvapp" : { "dynamic" : false , "properties" : { "uid" : { "type" : "keyword" }, "date" : { "type" : "keyword" }, "errmsg" : { "type" : "text" , "fields" : { "keyword" : { "type" : "keyword" , "ignore_above" : 1024 } } } } } }, "aliases" : {} } |
painless script语法参见:Painless API
尤其注意:日期时间格式
问题解决
1 2 | 按{ "type" : "string" , "index" : "not_analyzed" }设置mapping时,报错: Elasticsearch:No handler for type [string] declared on field[XXX] |
原因:Elasticsearch从5.X引入
text"
和"
keyword"
用于分词和全词匹配,从6.X彻底移除"string",且"index"值只能是boolean变量:string类型已去, 字符串数据永生。"
- 关键词搜索(keyword search):精准匹配和聚合分析
- 全文搜索(full-text search):分词
若允许该字段被索引查询,需{"type":"text","index":true},否则会报错:Cannot search on field [xxx] since it is not indexed.
关于ES中的数据类型,参见:Field datatypes
G:Grafana
分析和可视化平台, 监控
扩展工具
ElasticHD
独立于elasticsearch安装使用,cmd命令启动
Elastsearch-SQL
作为插件依赖elasticsearch使用
X-Pack
ElasticSearch 扩展包
- 安全防护:用户验证 + 授权和基于角色的访问控制 + 节点/客户端认证和信道加密
- 实时集群监控:可视化报告
cerebro
elasticsearch 开源监控软件,替代 kopf(http://99.6.150.141:9200/_plugin/kopf/#!/cluster)
下载地址:cerebro | github
es-rally
ES性能监控工具
[使用教程](https://blog.csdn.net/laoyang360/article/details/52155481)
其他工具使用
1 2 3 4 | Grafana:适合监控类场景 ElasticHD:支持SQL转DSL elasticsearch-SQL:类SQL查询工具 测试工具:在原来执行的DSL的基础上新增profile参数 "profile" : true |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!