使用elk处理千亿级数据 – 墨天轮

  • A+
所属分类:其他杂项
本文信息本文由方法SEO顾问发表于2021-09-1614:15:14,共 7451 字,转载请注明:使用elk处理千亿级数据 – 墨天轮_【方法SEO顾问】

0x00 前言

做GA业务从目标处拿回原始数据后,通常还需要根据客户的需求对数据进行查询、分析、统计等操作。而大一点的目标拿回的流水数据动辄上亿条,普通数据库即使建了索引也难以支撑如此庞大数据量的查询操作,使用体验极差。

最近发现elk号称可以支持千亿级数据查询,试用后发现查询效率真的不错,虽然我没有千亿的数据,但实测支持几十亿数据查询绰绰有余。这周就写文章给大家介绍一下如何搭建和使用elk。

0x01 食用指南

这是一个分享安全技术的公众号啦,很多东西都会有所涉及但不会深入。本文仅适合那些想快速上手使用elk处理大量静态的数据,而不在乎原理和更多高级玩法的人观看。

对于想钻研大数据领域,深入学习elk的读者,推荐找一些完善的课程、书籍或啃官方文档去系统性学习,本文讲elk相对那些专业的教程是比较业余的。

0x02 elk背景知识

1、什么是ELK

先简要介绍一下elk,如lamp集成环境一样,elk不是一个产品,而是elastic公司的三个产品的合称:

(1)Elasticsearch:开源分布式搜索和分析引擎,提供搜集、分析、存储数据三大功能。

(2)Logstash:具有实时传输能力的数据收集引擎,日志的搜集与分析,过滤日志工具。

(3)Kibana:提供日志分析友好的web界面,可以在es的索引中查找交互数据,生成各种图表。

简单地说,elasticsearch用于存储数据,logstash用于导入数据,kibana用于查询数据。

现在ELK中还新增了一个FileBeat工具,看了介绍大概相当于一个性能更高但少了过滤功能的logstash,不符合本文需求所以下面不会提及这个工具。

2、为什么需要ELK

elk主要的使用场景是处理日志。

集中化日志管理:分布式多节点日志归档、文本搜索、多维度查询

功能需求:收集、传输、存储、分析、警告

3、基本原理

es底层使用Lucene编写,核心功能为全文检索,通过倒排索引来实现。

一些基本概念:

Index(索引):一类业务数据的集合,类似于传统数据库的DB概念,和传统数据库的索引意义完全不同。

Document(文档):数据存储和检索的基本单位。一条完整的数据记录,json格式,类似于传统数据库的一行。

Field(字段):文档的具体一个属性,类似于传统数据库的列。

Term(分词):全文检索特有词汇,存储文档或检索时会先把传入的值进行拆分,使用拆分后的词进行存储和检索。

es将要取消的type概念:

本意是为了类比传统数据库,降低学习成本:index类比为database、type类比为table。但是后面发现两种数据库存储数据的方式和原理完全不同,这种类比毫无意义且降低数据库的效率。所以在es7版本一个index只能有一个type:_doc。es8版本将完全取消type的概念,官方也不建议继续使用type。

0x03 安装搭建elk

配置参考:win10的ubuntu子系统,8G内存,i7-6700 CPU @ 3.40GHz,导入数据使用SSD,存储及查询数据使用机械硬盘 (一台老古董,后面实测es的性能基于这个配置

主讲linux系统如何搭建,不过也会提一句windows。

1、新建用户

elk不允许root用户启动,新建一个用户elk,用于后续操作。

windows系统不用管。

2、下载elk

下载Elasticsearch、Logstash、Kibana,安装包版本要一致

下载地址:https://www.elastic.co/cn/downloads/

linux系统用arch命令查看架构,然后下载对应安装包。

windows系统使用迅雷下载更快速。

下载后linux用tar -xzvf命令解压,windows用压缩工具解压

解压后三个蓝色的目录就分别是elk三个软件的安装目录

3、安装配置java运行环境

注意es7版本以上需要使用java11及以上的环境。

配置java环境参考这篇文章的0x02章节,本文就不重复写了:

搭建和使用CobaltStrike

4、安装启动elasticsearch

进入elasticsearch安装目录下的config目录,编辑elasticsearch.yml文件

在尾部加入

cluster.name: elk
node.name: elasticsearch
network.host: 127.0.0.1
http.port: 9200
http.cors.enabled: true
http.cors.allow-origin: "*"
path.data: home/elk/data
path.logs: /home/elk/logs

其中path.datapath.logs是数据和运行日志的存储目录,这个根据自身情况自定义,注意权限问题(elk用户需要有目录的读写权限)。

linux如何启动elasticsearch:

./es安装目录/bin/elasticsearch

./es安装目录/bin/elasticsearch &(在后台启动)

建议先前台启动看看有没有error,一切正常的话ctrl+c掉再后台启动。

Linux系统运行可能出现问题:

Native controller process has stopped - no new native processes can be started

解决方法

修改elasticsearch.yml配置文件,在Discovery栏下加上

cluster.initial_master_nodes: ["node-1"]

然后修改/etc/sysctl.conf

添加配置vm.max_map_count=655360

然后sudo sysctl --system

windows如何启动elasticsearch

双击es安装目录下的bin目录里的elasticsearch.bat

测试:

使用curl或用浏览器访问 http://127.0.0.1:9200/,可以看到es的信息

5、安装启动Kibana

进入kibana安装目录的config目录

编辑kibana.yml文件,在末尾加入

server.port: 5601
server.host: "127.0.0.1"
elasticsearch.hosts: ["http://localhost:9200/"]
kibana.index: ".kibana"
i18n.locale: "zh-CN"

如果想远程访问,可以把server.host的值改成"0.0.0.0",注意安全问题

linux普通启动:

./kibana安装目录/bin/kibana

linux后台启动:

nohup ./kibana安装目录/bin/kibana &

windows普通启动:

双击kibana安装目录的bin目录下的kabana.bat

windows后台运行:

在kibana.bat同目录下新建文件kibana.vbs,内容如下,双击运行

createobject("wscript.shell").run "kibana.bat",0

想结束进程去任务管理器找Node.js: Server-side JavaScript

测试:

浏览器访问:http://127.0.0.1:5601/app/home

如果远程访问响应超时,注意检查系统防火墙和云服务器的安全组配置。

6、安装启动logstash

logstash需要根据数据文件的格式编写配置文件,并在其中指定需要导入的数据库文件路径,然后执行。

配置文件的编写方法和logstash的使用方法放在下一章节。

0x04 使用elk处理数据

1、数据结构设计与清洗

数据结构设计:

将一行数据划分成几个字段,可以增加查询的效率。

但是,如果效率没到瓶颈的话,完全不用设计,可以把所有数据写到同一个field里,这样导入不同来源、不同格式的数据时就不用更改logstash的配置文件,简单快捷。

而且elasticsearch全文检索的特性也使它可以在一个field里也能正确的匹配不同格式数据的关键词从而查询到正确的结果。

比如我有这样一个数据:

四行数据每行的列数都不同,使用的分隔符也不同,将它们导入到同一个filed中。可以看到es能完美的划分关键词并查询出每行数据。

编码问题:

因为我们要处理的是行数上亿的超大文件,所以尽量避免对源文件做改动(会很慢),所以无需更改源文件编码,只需在logstash导入时指定一下源文件使用的编码即可,logstash输出时会自动转换成utf-8编码,查询时不会出现乱码情况。

如何查看超大文件的编码呢,在windows下可以用emeditor专业版打开文件,linux可以将文件切一小片出来,然后vim进去输入命令set fileencoding来查看

数据去重:

虽说要尽量避免对原始数据做改动,但es导入数据后再去重实在是太麻烦了,我并没有找到合适的方法,所以去重的步骤就放在清洗数据这一步了。

使用linux命令:sort -u 原文件 > 新文件 进行去重,去重后会打乱原始数据的顺序,如果顺序很重要的话不要用这个命令,可以去找一下大文件去重的python脚本。

实测sort命令处理10G数据需要15min。

最后一行数据丢失问题

logstash导入数据时不会导入最后一行数据,所以要确保最后一行是空行。

使用linux命令tail -n 1 源文件 来查看最后一行是不是空行。

显示如下图是有空行的,可以放心导入

显示如下图是没有空行,直接导入会导致最后一行数据丢失

这时用命令echo "" >> 1.txt 就可以在文件最后添加一个空行。

2、编写logstash配置

logstash的配置文件分为三部分:input、filter和output,分别对应数据的输入、处理、和输出。

大家可以直接套用我写好的这个,使用时需要更改的部分:

(1)input—file方块里的path和codec,即源文件位置和编码

(2)output—elasticsearch方块中index的值,即导入数据到es的哪个索引(没有会自动创建)

input{
file{
    path         => "/tmp/1.txt"
    start_position    => "beginning"
codec => plain{charset => "GB2312"}
}
}


filter{
mutate{
remove_field => ["host","@version","@timestamp","path"]
}
}


output{
stdout{
codec => rubydebug
}
elasticsearch{
hosts => "127.0.0.1:9200"
index => "test"
}
}

一些问题:

文件路径问题源文件路径处,windows和linux系统一样使用一个正斜杠

给数据添加固定字段:input中的file大方块添加add_field => {"字段名"=>"字段值"}

关于ignore_older:网上说导入旧数据要设为0,但我实测发现设为0后还是无法导入旧数据,于是干脆去掉了这个配置项。

去除ES自带的字段:在filter中添加的代码的作用,否则elasticsearch会自动添加很多没有用字段,占用空间。

ANSI编码中文乱码:input中的file大方块添加codec => plain{charset => "GB2312"}

index的命名规范:不能使用大写字母,可以用中文。不能以+、-、下划线开头,不能包含空格及各种特殊符号(包括.),长度不能超过255字符

字段命名规范:配置文件中不指定字段则自动创建名为message的字段。不能用空格,尽量不要用点号(仅用于对象类型)。

3、运行logstash入库

置文件写好后,保存到一个位置(我这里保存到logstash安装目录的config目录下),然后在logstash安装目录的bin目录下行命令即可开始导入数据:

./logstash -f ../config/xxx.conf

导入完logstash仍会监听文件新写入内容,不会主动退出,所以看它不动了之后要手动退出

重复导入同一个配置文件:要删除logstash安装目录\data\plugins\inputs\file目录下的缓存,或在input中的file大方块添加sincedb_path => "/dev/null" (仅限linux,windows写空值会报错),否则缓存文件存在时,之前已导入过的数据不会再重复导入,做测试时要注意这一点。

数据存放位置:存放在elasticsearch配置文件中指定的data目录,删除索引会删除数据,实测入库后数据比原始数据大3.5倍。

关于导入速度:挂机导入时要注意电源设置,设置为从不睡眠,否则电脑睡眠后会影响导入性能。实测导入速度大概2kw条/h。

4、使用kibana查看数据

导入数据后如何查询数据呢,这时要用到kibana。

(1)kibana——左侧菜单——Stack Management——索引管理——查看数据是否完整导入(使用linux命令:wc -l 源文件查看文件行数,和这里的文档计数相对应)

(2)索引模式——创建索引模式——和索引同名

(3)kibana——左侧菜单——DisCover——进入查询界面

(4)点击搜索框右边的KQL切换为Lucene,否则匹配值权重可能还没有无关数据权重高

(5)在搜索框即可查询数据,尽量不要使用通配符,尤其是前置通配符,查询代价极高,可能直接把es节点打挂。

在Discover处查询没有超时时间,会一直转圈到查询出结果为止。实测查询速度和查询出的数据条数正相关,在5亿数据中查一条数据只要不到1秒,如果把5亿数据全部查出来大概要4分钟。

5、使用开发工具执行查询

kibana——左侧菜单——开发工具

批量修改数据,将匹配到字段名1=值1的数据的字段名2修改为值2(字段名12可相同):

POST 索引/文档名/_update_by_query
{
"query": {
"match": {
"字段名1":"值1"
}
},
"script": {
"inline": "ctx._source['字段名2'] = '值2'"
}
}

批量删除数据,将匹配到字段名1=值1的数据删除:

POST 索引名/_delete_by_query
{
"query":{
"match":{
"字段名1":"值1"
}
}
}

还有更多的语句大家自行研究吧。

要注意这里的查询是有超时时间的,不同于Discover,对大量数据进行操作会出现502状态码,但这时查询仍在进行,注意不要同时发出多个查询请求,有可能把es节点打挂。

0x05、ELK性能优化

关于索引和分片:

(1)es本身有一些指标限制:单个分片数据容量官方建议不超过 50GB,合理范围是 20GB~40GB 之间;单个分片数据条数不超过约 21 亿条;

(2)一个索引默认5个分片,创建后不能更改,想更改需要重建索引。

(3)索引分片过低或过多都会降低效率,需要不断调试找出针对当前索引的最优分片数量。

(4)一个大索引比多个小索引效率更高。

修改分配内存:

(1)es安装后默认使用1G内存

(2)修改es安装目录的jvm.options文件,去掉-Xms4g和-Xmx4g前面的注释和空格,调整后面的数字4g即可修改分配内存,两个值要相同。

(3)建议分配物理内存的一半(另一半会被lucene使用),但是不要超过32G。修改后重启es。

禁用内存交换:

修改elasticsearch.yml,添加一行 bootstrap.memory_lock: true

0x06 后记

如果对你有帮助,就点个赞吧~

0x07 参考文献

简单介绍ELK 组件与历史

https://www.linuxprobe.com/elk-jieshano.html

说说 ELK 火热的原因?

https://zhuanlan.zhihu.com/p/79011122

You know, for search--带你认识Elasticsearch

https://elasticsearch.cn/article/13564#tip5

ELK搭建教程(Elasticsearch+Logstash+Kibana)

https://www.jianshu.com/p/4304e60353f4

Windows 10安装Elasticsearch-7.0.0

https://gobea.cn/blog/detail/M5X2Wj6d.html

Ubuntu安装jdk11

https://www.jianshu.com/p/1658c52445fd

kinaba 安装踩坑:FATAL Error: [elasticsearch.url\]: definition for this key is missing

https://www.cnblogs.com/miaoying/p/11639437.html

linux安装elasticsearch及遇到的各种问题

https://www.cnblogs.com/cnsdhzzl/p/9401829.html

ElasticSearch启动报错,bootstrap checks failed解决方案

https://www.jianshu.com/p/ac5816776204

ElasticSearch: Index 和 Type 的区别

https://www.bayescafe.com/database/elasticsearch-using-index-or-type.html

Elasticsearch核心技术(2)--- 基本概念

https://www.cnblogs.com/qdhxhz/p/11448451.html

ElasticSearch系列(七)es内存大小设置

https://blog.csdn.net/csdn_20150804/article/details/107917560

Elasticsearch 合理内存分配

https://blog.csdn.net/choulao8648/article/details/100745746

ES 的跨索引查询有多便利?对比下分库分表、分片更直观

https://www.infoq.cn/article/ekygoihkqifj4kdgso6a

从 10 秒到 2 秒!ElasticSearch 性能调优

https://zhuanlan.zhihu.com/p/55092525

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: