为什么用到ELK
一般需要进行日志分析的时候,直接在日志文件中 grep、awk 就可以获得自己想要的信息。但在规模较大的场景中,此方法效率低下,尤其是在目前微服务和容器化普及的场景下,面临问题包括日志量太大如何归档、文本搜索太慢、无法多维度查询,所以迫切需要一个集中化的日志管理工具。
ELK的组成工具简介
开源实时日志分析 ELK 平台由 Elasticsearch、 Logstash 和 Kibana 三个开源工具组成。现在新增一个 FileBeat,它是一个轻量级的日志收集处理工具(Agent),FileBeat 占用资源少,适合于在各个服务器上搜集日之后传输给 Logstash 。
- Elasticsearch 是个开源分布式搜索引擎,提供搜集、分析、存储数据三大功能。它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。
- Logstash 主要是用来日志的搜集、分析、过滤日志的工具,支持大量的数据获取方式可以理解为一个管道,或者中间件。功能是从定义的输入源inputs读取信息,经过filters过滤器处理,输入到定义好的outputs输出源。
- Kibana 也是一个开源的UI工具,它可以为 Logstash 和 ElasticSearch 提供友好的日志分析 Web 界面,可以帮助汇总、分析和搜索重要数据日志。
- FileBeat隶属于 Beats。目前 Beats 包括四种工具。
- Packetbeat 搜集网络数据流量
- Topbeat 搜集系统、进程和文件系统级别的 CPU 和内存使用情况等数据
- Filebeat 搜集文件数据
- Winlogbeat 搜集 Windows 事件日志数据
工作原理 :在需要收集日志的所有服务上部署 filebeat(不推荐使用 logstash 来收集日志,因为 logstash 相对来说极为耗费系统内存),logstash 用于监控并过滤收集日志,日志收集在一起交给全文搜索服务 ElasticSearch ,可以用 ElasticSearch 进行自定义搜索通过 Kibana 来结合自定义搜索进行页面展示。
0.工作流程
0.1 ELK
0.2 ELFK
0.3 架构演进
- ELK缺点:ELK架构,并且Spring Boot使用 logstash-logback-encoder 直接发送给 Logstash,缺点就是Logstash是重量级日志收集server,占用cpu资源高且内存占用比较高
ELFK缺点:一定程度上解决了ELK中Logstash的不足,但是由于Beats 收集的每秒数据量越来越大,Logstash 可能无法承载这么大量日志的处理
0.4 日志新贵ELK + Filebeat + Kafka
随着 Beats 收集的每秒数据量越来越大,Logstash 可能无法承载这么大量日志的处理。虽然说,可以增加 Logstash 节点数量,提高每秒数据的处理速度,但是仍需考虑可能 Elasticsearch 无法承载这么大量的日志的写入。此时,我们可以考虑 引入消息队列 ,进行缓存:
Beats 收集数据,写入数据到消息队列中。
- Logstash 从消息队列中,读取数据,写入 Elasticsearch 中
如下就是其工作流程
传统关系型数据库和非关系型数据库ES的对比
Relational DB | Elasticsearch |
---|---|
数据库(database) | 索引(index) |
表(tables) | 类型(type) |
行(rows) | 文档(docments) |
字段(columns) | 字段(fields) |
- 关系型数据库中的数据库(DataBase),等价于ES中的索引(Index)
- 一个数据库下面有N张表(Table),等价于1个索引Index下面有N多类型(Type)
- 一个数据库表(Table)下的数据由多行(ROW)多列(column,属性)组成,等价于1个Type由多个文档(Document)和多Field组成。
- 在一个关系型数据库里面,schema定义了表、每个表的字段,还有表和字段之间的关系。 与之对应的,在ES中:Mapping定义索引下的Type的字段处理规则,即索引如何建立、索引类型、是否保存原始索引JSON文档、是否压缩原始JSON文档、是否需要分词处理、如何进行分词处理等。
- 在数据库中的增insert、删delete、改update、查search操作等价于ES中的增PUT/POST、删Delete、改_update、查GET。
搭建一个集群我们需要考虑如下几个问题:
1.我们需要多大规模的集群?
ES可以作为一个独立的单个搜索服务器。不过,为了处理大型数据集,实现容错和高可用性,ES可以运行在许多互相合作的服务器上。这些服务器的集合称为集群。
需要从以下两个方面考虑:
1.1 当前的数据量有多大?数据增长情况如何?
1.2 你的机器配置如何?cpu、多大内存、多大硬盘容量?
推算的依据:
ES JVM heap 最大可以设置32G 。
30G heap 大概能处理的数据量 10 T。如果内存很大如128G,可在一台机器上运行多个ES节点实例。
备注:集群规划满足当前数据规模+适量增长规模即可,后续可按需扩展。
两类应用场景:
A. 用于构建业务搜索功能模块,且多是垂直领域的搜索。数据量级几千万到数十亿级别。一般2-4台机器的规模。
B. 用于大规模数据的实时OLAP(联机处理分析),经典的如ELK Stack,数据规模可能达到千亿或更多。几十到上百节点的规模。
2.集群中的节点角色如何分配?
2.1 节点角色:
Master
node.master: true 节点可以作为主节点
DataNode
node.data: true 默认是数据节点。
Coordinate node 协调节点
如果仅担任协调节点,将上两个配置设为false。
说明:
一个节点可以充当一个或多个角色,默认三个角色都有
协调节点:一个节点只作为接收请求、转发请求到其他节点、汇总各个节点返回数据等功能的节点。就叫协调节点
2.2 如何分配:
A. 小规模集群,不需严格区分。
B. 中大规模集群(十个以上节点),应考虑单独的角色充当。特别并发查询量大,查询的合并量大,可以增加独立的协调节点。角色分开的好处是分工分开,不互影响。如不会因协调角色负载过高而影响数据节点的能力。
3.如何避免脑裂问题?
3.1 脑裂问题:
一个集群中只有一个A主节点,A主节点因为需要处理的东西太多或者网络过于繁忙,从而导致其他从节点ping不通A主节点,这样其他从节点就会认为A主节点不可用了,就会重新选出一个新的主节点B。过了一会A主节点恢复正常了,这样就出现了两个主节点,导致一部分数据来源于A主节点,另外一部分数据来源于B主节点,出现数据不一致问题,这就是脑裂。
3.2 尽量避免脑裂,需要添加最小数量的主节点配置:
discovery.zen.minimum_master_nodes: (有master资格节点数/2) + 1
这个参数控制的是,选举主节点时需要看到最少多少个具有master资格的活节点,才能进行选举。官方的推荐值是(N/2)+1,其中N是具有master资格的节点的数量。
3.3 常用做法(中大规模集群):
- Master 和 dataNode 角色分开,配置奇数个master,如3
- 单播发现机制,配置master资格节点:
- discovery.zen.ping.multicast.enabled: false —— 关闭多播发现机制,默认是关闭的
- discovery.zen.ping.unicast.hosts: [“master1”, “master2”, “master3”] —— 配置单播发现的主节点ip地址,其他从节点要加入进来,就得去询问单播发现机制里面配置的主节点我要加入到集群里面了,主节点同意以后才能加入,然后主节点再通知集群中的其他节点有新节点加入
- 配置选举发现数,及延长ping master的等待时长
- discovery.zen.ping_timeout: 30(默认值是3秒)——其他节点ping主节点多久时间没有响应就认为主节点不可用了
- discovery.zen.minimum_master_nodes: 2 —— 选举主节点时需要看到最少多少个具有master资格的活节点,才能进行选举
4.索引应该设置多少个分片?
在 ES 中, 索引是一组文档的集合。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。
当有大量的文档时,由于内存的限制、磁盘处理能力不足、无法足够快的响应客户端的请求等,一个节点可能不够。这种情况下,数据可以分为较小的分片。每个分片放到不同的服务器上。当你查询的索引分布在多个分片上时,ES会把查询发送给每个相关的分片,并将结果组合在一起,而应用程序并不知道分片的存在。即:这个过程对用户来说是透明的。需要注意:在创建索引的时候就确定好主分片的数量,并且永远不能改变这个数量。
说明:分片数指定后不可变,除非重索引,比如开始设置为5个分片在一个节点上,后来扩容到5个节点,每个节点有一个分片。如果继续扩容,是不能自动切分进行数据迁移的。官方文档的说法是分片切分成本和重新索引的成本差不多,所以建议干脆通过接口重新索引。
思考:
分片对应的存储实体是什么?
存储的实体是索引
分片是不是越多越好?
不是
分片多有什么影响?
分片多浪费存储空间、占用资源、影响性能4.1 分片过多的影响:
每个分片本质上就是一个Lucene索引, 因此会消耗相应的文件句柄, 内存和CPU资源。
每个搜索请求会调度到索引的每个分片中. 如果分片分散在不同的节点倒是问题不太. 但当分片开始竞争相同的硬件资源时, 性能便会逐步下降。
ES使用词频统计来计算相关性. 当然这些统计也会分配到各个分片上. 如果在大量分片上只维护了很少的数据, 则将导致最终的文档相关性较差。4.2 分片设置的可参考原则:
ElasticSearch推荐的最大JVM堆空间是30~32G, 所以把你的分片最大容量限制为30GB, 然后再对分片数量做合理估算. 例如, 你认为你的数据能达到200GB, 推荐你最多分配7到8个分片。
在开始阶段, 一个好的方案是根据你的节点数量按照1.5~3倍的原则来创建分片. 例如,如果你有3个节点, 则推荐你创建的分片数最多不超过9(3x3)个。当性能下降时,增加节点,ES会平衡分片的放置。
对于基于日期的索引需求, 并且对索引数据的搜索场景非常少. 也许这些索引量将达到成百上千, 但每个索引的数据量只有1GB甚至更小. 对于这种类似场景, 建议只需要为索引分配1个分片。如日志管理就是一个日期的索引需求,日期索引会很多,但每个索引存放的日志数据量就很少。4.3 如何知道一个文档应该存放到哪个分片中呢?
当索引一个文档的时候,文档会被存储到一个主分片中。
首先这肯定不会是随机的,否则将来要获取文档的时候我们就不知道从何处寻找了。实际上,这个过程是根据下面这个公式决定的:
shard = hash(routing) % number_of_primary_shards
routing 是一个可变值,唯一不可重复,默认是文档的_id ,也可以设置成一个自定义的值。routing 通过hash函数生成一个数字,然后这个数字再除以 number_of_primary_shards(主分片的数量)后得到余数 。这个分布在0到number_of_primary_shards-1之间的余数,就是我们所寻求的文档所在分片的位置。
这就解释了为什么我们要在创建索引的时候就确定好主分片的数量 并且永远不会改变这个数量:因为如果数量变化了,那么所有之前路由的值都会无效,文档也再也找不到了。
所有的文档 API(get、index、delete、bulk、update以及mget)都接受一个叫做routing的路由参数,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。5.为提高查询吞吐量或实现高可用性,可以使用分片副本
副本是一个分片的精确复制,每个分片可以有零个或多个副本。ES中可以有许多相同的分片,其中之一被选择更改索引操作,这种特殊的分片称为主分片。
当主分片丢失时,如:该分片所在的数据不可用时,集群将副本提升为新的主分片。
Elasticsearch 禁止同一个分片的主分片和副本分片在同一个节点上,所以如果是一个节点的集群是不能有副本的。
它在节点失败的情况下提供高可用性。由于这个原因,需要注意的是,副本分片永远不会分配到与主分片相同的节点上。
说明:副本数是可以随时调整的!
副本的用途是什么?
备份数据保证高可用数据不丢失,高并发的时候参与数据查询
针对它的用途,我们该如何设置它的副本数?
一般一个分片有1-2个副本即可保证高可用
集群规模没变的情况下副本过多会有什么影响?
副本多浪费存储空间、占用资源、影响性能5.1 副本设置基本原则:
为保证高可用,副本数设置为2即可。要求集群至少要有3个节点,来分开存放主分片、副本。
如发现并发量大时,查询性能会下降,可增加副本数,来提升并发查询能力。
注意:新增副本时主节点会自动协调,然后拷贝数据到新增的副本节点6.全文检索
全文检索就是对一篇文章进行索引,可以根据关键字搜索,类似于mysql里的like语句。
全文索引就是把内容根据词的意义进行分词,然后分别创建索引,例如”你们的激情是因为什么事情来的” 可能会被分词成:“你们“,”激情“,“什么事情“,”来“ 等token,这样当你搜索“你们” 或者 “激情” 都会把这句搜出来。