10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

栏目: 服务器 · Apache · 发布时间: 5年前

内容简介:日志数据是最常见的一种海量数据,以拥有大量用户群体的电商平台为例,双 11 大促活动期间,它们可能每小时的日志数量达到百亿规模,海量的日志数据暴增,随之给技术团队带来严峻的挑战。本文将从海量日志系统在优化、部署、监控方向如何更适应业务的需求入手,重点从多种日志系统的架构设计对比;后续调优过程:横向扩展与纵向扩展,分集群,数据分治,重写数据链路等实际现象与问题展开。有过项目开发经验的朋友都知道:从平台的最初搭建到实现核心业务,都需要有日志平台为各种业务保驾护航。

日志数据是最常见的一种海量数据,以拥有大量用户群体的电商平台为例,双 11 大促活动期间,它们可能每小时的日志数量达到百亿规模,海量的日志数据暴增,随之给技术团队带来严峻的挑战。

本文将从海量日志系统在优化、部署、监控方向如何更适应业务的需求入手,重点从多种日志系统的架构设计对比;后续调优过程:横向扩展与纵向扩展,分集群,数据分治,重写数据链路等实际现象与问题展开。

日志系统架构基准

有过项目开发经验的朋友都知道:从平台的最初搭建到实现核心业务,都需要有日志平台为各种业务保驾护航。

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

如上图所示,对于一个简单的日志应用场景,通常会准备 master/slave 两个应用。我们只需运行一个 Shell 脚本,便可查看是否存在错误信息。

随着业务复杂度的增加,应用场景也会变得复杂。虽然监控系统能够显示某台机器或者某个应用的错误。

然而在实际的生产环境中,由于实施了隔离,一旦在上图下侧的红框内某个应用出现了 Bug,则无法访问到其对应的日志,也就谈不上将日志取出了。

另外,有些深度依赖日志平台的应用,也可能在日志产生的时候就直接采集走,进而删除掉原始的日志文件。这些场景给我们日志系统的维护都带来了难度。

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

参考 Logstash,一般会有两种日志业务流程:

  • 正常情况下的简单流程为: 应用产生日志→根据预定义的日志文件大小或时间间隔,通过执行 Logrotation,不断刷新出新的文件→定期查看→定期删除。

  • 复杂应用场景的流程为: 应用产生日志→采集→传输→按需过滤与转换→存储→分析与查看。

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

我们可以从实时性和错误分析两个维度来区分不同的日志数据场景:

实时,一般适用于我们常说的一级应用,如:直接面向用户的应用。我们可以自定义各类关键字,以方便在出现各种 error 或 exception 时,相关业务人员能够在第一时间被通知到。

准实时,一般适用于一些项目管理的平台,如:在需要填写工时的时候出现了宕机,但这并不影响工资的发放。

平台在几分钟后完成重启,我们可以再登录填写,该情况并不造成原则性的影响。因此,我们可以将其列为准实时的级别。

除了直接采集错误与异常,我们还需要进行分析。例如:仅知道某人的体重是没什么意义的,但是如果增加了性别和身高两个指标,那么我们就可以判断出此人的体重是否为标准体重。

也就是说:如果能给出多个指标,就可以对庞大的数据进行去噪,然后通过回归分析,让采集到的数据更有意义。

此外,我们还要不断地去还原数字的真实性。特别是对于实时的一级应用,我们要能快速地让用户明白他们所碰到现象的真实含义。

例如:商家在上架时错把商品的价格标签 100 元标成了 10 元。这会导致商品马上被抢购一空。

但是这种现象并非是业务的问题,很难被发现,因此我们只能通过日志数据进行逻辑分析,及时反馈以保证在几十秒之后将库存修改为零,从而有效地解决此问题。可见,在此应用场景中,实时分析就显得非常有用。

最后是追溯,我们需要在获取历史信息的同时,实现跨时间维度的对比与总结,那么追溯就能够在各种应用中发挥其关联性作用了。

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

上述提及的各个要素都是我们管理日志的基准。 如上图所示,我们的日志系统采用的是开源的 ELK 模式:

  • ElasticSearch(后简称 ES),负责后端集中存储与查询工作。

  • 单独的 Beats 负责日志的搜集。FileBeat 则改进了 Logstash 的资源占用问题;TopBeat 负责搜集监控资源,类似系统命令 top 去获取 CPU 的性能。

由于日志服务对于业务来说仅起到了维稳和保障的作用,而且我们需要实现快速、轻量的数据采集与传输,因此不应占用服务器太多资源。

在方式上我们采用的是插件模式,包括:input 插件、output 插件、以及中间负责传输过滤的插件。这些插件有着不同的规则和自己的格式,支持着各种安全性的传输。

日志系统优化思路

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

有了上述日志的架构,我们针对各种实际的应用场景,进一步提出了四个方面的优化思路:

基础优化

内存:如何分配内存、垃圾回收、增加缓存和锁。

网络:网络传输序列化、增加压缩、策略、散列、不同协议与格式。

CPU:用多线程提高利用率和负载。

此处利用率和负载是两个不同的概念:

  • 利用率:在用满一个核后再用下一个内核,利用率是逐步升高的。

  • 负载:一下子把八个核全用上了,则负载虽然是满的,但是利用率很低。即,每核都被占用了,但是所占用的资源却不多,计算率比较低下。

磁盘:尝试通过文件合并,减少碎片文件的产生,并减少寻道次数。同时在系统级别,通过修改设置,关闭各种无用的服务。

平台扩展

做加减法,或称替代方案:无论是互联网应用,还是日常应用,我们在查询时都增加了分布式缓存,以有效提升查询的效率。另外,我们将不被平台使用到的地方直接关闭或去除。

纵向扩展:如增加扩展磁盘和内存。

横向扩展:加减/平行扩展,使用分布式集群。

数据分治

根据数据的不同维度,对数据进行分类、分级 例如:我们从日志中区分error、info、和 debug,甚至将 info 和 debug 级别的日志直接过滤掉。

数据热点:例如:某种日志数据在白天的某个时间段内呈现暴涨趋势,而晚上只是平稳产生。我们就可以根据此热点情况将它们取出来单独处理,以打散热点。

系统降级

我们在对整体业务进行有效区分的基础上,通过制定一些降级方案,将部分不重要的功能停掉,以满足核心业务。

日志系统优化实践

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

面对持续增长的数据量,我们虽然增加了许多资源,但是并不能从根本上解决问题。

特别体现在如下三方面:

  • 日志产生量庞大,每天有几百亿条。

  • 由于生产环境隔离,我们无法直接查看到数据。

  • 代理资源限制,我们的各种日志采集和系统资源采集操作,不可超过业务资源的一个核。

面对持续增长的数据量,我们虽然增加了许多资源,但是并不能从根本上解决问题。

一级业务架构

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

我们日志系统的层次相对比较清晰, 可简单分为数据接入、数据存储和数据可视化三大块。

具体包括:

  • Rsyslog,是目前我们所接触到的采集 工具 中最节省性能的一种。

  • Kafka,具有持久化的作用。当然它在使用到达一定数据量级时,会出现 Bug。

  • Fluentd,它与 Rsyslog 类似,也是一种日志的传输工具,但是它更偏向传输服务。

  • ES 和 Kibana。

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

该架构在实现上会用到 Golang、 RubyJava 、JS 等不同的语言。在后期改造时,我们会将符合 Key-Value 模式的数据快速地导入 HBase 之中。

基于 HBase 的自身特点,我们实现了它在内存层的 B+ 树,并且持久化到我们的磁盘之上,从而达到了理想的快速插入的速度。这也正是我们愿意选择 HBase 作为日志方案的原因。

二级业务架构

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

我们直接来看二级业务架构的功能图 ,它是由如下流程串联而成的:

  • 在完成了数据采集之后,为了节省自己占用磁盘的空间,许多应用会完全依赖于我们的日志系统。因此在数据采集完以后,我们增加了一个持久缓存。

  • 完成缓存之后系统执行传输。传输的过程包括:过滤和转换,这个过程可以进行数据抽稀。值得强调的是:如果业务方尽早合作并给予我们一些约定的话,我们就能够通过格式化来实现结构化的数据。

  • 随后执行的是分流,其主要包括两大块:一种是 A 来源的数据走 A 通道,B 来源的数据走 B 通道。另一种是让 A 数据流入到我们的存储设备,并触发保护机制。即为了保障存储系统,我们额外增加了一个队列。

  • 例如:队列为 100,里面的一个 chunk 为 256 兆,我们现在设置高水位为 0.7、低水位为 0.3。

  • 在写操作的堆积时,由于我们设置了 0.7,即 100 兆赫。那么在一个 256 兆会堆积到 70 个 chunk 时,我们往该存储平台的写速度就已经跟不上了。

  • 此时高水位点会被触发,不允许继续写入,直到整个写入过程把该 chunk 消化掉,并降至 30 个时,方可继续往里写入。我们就是用该保护机制来保护后台以及存储设备的。

  • 接着是存储,由于整个数据流的量会比较大,因此在存储环节主要执行的是存储的索引、压缩、和查询。

  • 最后是 UI 的一些分析算法,运用 SQL 的一些查询语句进行简单、快速地查询。

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

通常从采集(logstash/rsyslog/heka/filebeat)到面向缓存的 Kafka 是一种典型的宽依赖。

所谓宽依赖,是指每个 App 都可能跟每个 Broker 相关联。在 Kafka 处,每次传输都要在哈希之后,再把数据写到每个 Broker 上。

而窄依赖,则是其每一个 Fluentd 进程都只对应一个 Broker 的过程。最终通过宽依赖过程写入到 ES。

采集

如 Rsyslog 不但占用资源最少,而且可以添加各种规则,它还能支持像 TSL、SSL 之类的安全协议。

Filebeat 轻量,在版本 5.x 中,Elasticsearch 具有解析的能力(像 Logstash 过滤器)— Ingest。

这也就意味着可以将数据直接用 Filebeat 推送到 Elasticsearch,并让 Elasticsearch 既做解析的事情,又做存储的事情。

Kafka

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

接着是 Kafka,Kafka 主要实现的是顺序存储,它通过 topic 和消息队列的机制,实现了快速地数据存储。

而它的缺点:由于所有的数据都向 Kafka 写入,会导致 topic 过多,引发磁盘竞争,进而严重拖累 Kafka 的性能。

另外,如果所有的数据都使用统一标签的话,由于不知道所采集到的数据具体类别,我们将很难实现对数据的分治。

因此,在后面的优化传输机制方面,我们改造并自己实现了顺序存储的过程,进而解决了一定要做持久化这一安全保障的需求。

Fluentd

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

Fluentd 有点类似于 Logstash,它的文档和插件非常齐全。其多种插件可保证直接对接到 Hadoop 或 ES。

就接入而言,我们可以采用 Fluentd 到 Fluentd 的方式。即在原有一层数据接入的基础上,再接一次 Fluentd。同时它也支持安全传输。当然我们在后面也对它进行了重点优化。

ES+Kibana

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

最后我们用到了 ES 和 Kibana。ES 的优势在于通过 Lucene 实现了快速的倒排索引。

由于大量的日志是非结构化的,因此我们使用 ES 的 Lucene 进行包装,以满足普通用户执行非结构化日志的搜索。而 Kibana 则基于 Lucene 提供可视化显示工具。

问题定位与解决

下面介绍一下我们碰到过的问题和现象,如下这些都是我们着手优化的出发点:

  • 传输服务器的 CPU 利用率低下,每个核的负载不饱满。

  • 传输服务器 Full gc 的频次过高。由于我们是使用 Ruby 来实现的过程,其内存默认设置的数据量有时会过大。

  • 存储服务器出现单波峰现象,即存储服务器磁盘有时会突然出现性能直线骤升或骤降。

  • 频繁触发高水位。如前所述的高水位保护机制,一旦存储磁盘触发了高水位,则不再提供服务,只能等待人工进行磁盘“清洗”。

  • 如果 ES 的一台机器“挂”了,则集群就 hang 住了。即当发现某台机器无法通讯时,集群会认为它“挂”了,则快速启动数据恢复。而如果正值系统繁忙之时,则此类数据恢复的操作会更加拖累系统的整体性能。

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

由于所有数据都被写入 Kafka,而我们只用到了一个 topic,这就造成了每一类数据都要经过不一定与之相关的规则链,并进行不一定适用的规则判断,因此数据的传输效率整体被降低了。

Fluentd 的 host 轮询机制造成高水位频发。由于 Fluentd 在与 ES 对接时遵循一个默认策略:首选前五台进行数据写入,即与前五台的前五个接口交互。

在我们的生产环境中,Fluentd 是用 CRuby 写的。每一个进程属于一个 Fluentd 进程,且每一个进程都会对应一个 host 文件。

而该 host 文件的前五个默认值即为 ES 的写入入口,因此所有机器都会去找这五个入口。

倘若有一台机器宕机,则会轮询到下一台。如此直接造成了高水位的频繁出现、和写入速度的下降。

众所周知,对日志的查询是一种低频次的查询,即只有在出现问题时才会去查看。但是在实际操作中,我们往往通过检索的方式全部取出,因此意义不大。

另外 ES 为了达到较好的性能,会将数据存储在 raid0 中,存储的时间跨度往往会超过 7 天,因此其成本也比较高。

通过对数据的实时线分析,我们发现并未达到写入/写出的平衡状态。

为了提高 Fluentd 的利用率,我们用 Kafka 去数据的时候提高了量,原来是 5 兆,现在我们改到了 6 兆。

如果只是单纯传输,不论计算的话,其实可以改更高。只不过因为我们考虑到这里包含了计算的一些东西,所以只提到了 6 兆。

我们的 Fluentd 是基于 JRuby 的,因为 JRuby 可以多线程,但是我们的 CRuby 没有任何意义。

为了提高内存,我把 Ruby 所有的内存机制了解了一下,就是散列的一些 host 文件,因为我们每个进程都选前五列就可以了,我多开了几个口。ES 的优化这一块,在上 ES 之前,我们已经有人做过一次优化了。

因为基于我刚才说的有时候日志量很高,有时候日志量很少。我们会考虑做动态配置。

因为 ES 就是支持动态配置的,所以它动态配置的时候,我们在某些场景下可以提高它的写入速度,某些场景下可以支持它的这种查询效率。我们可以尝试去做一些动态配置负载。

改造一:存储降低

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

降低存储在整体架构上并没有太大变化,我们只是在传输到 Fluentd 时把天数降下来,改成了一天。

同时,我们直接进行了分流,把数据往 Hadoop 里写,而把一些符合 Kibana 的数据直接放入 ES。

上面提过,日志查询是低频次的,一般需要查询两天以上数据的可能性很小,因此我们降低存储是非常有意义的。

改造二:数据分治

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

我们在日志文件节点数较少(机器数量小于 5 台)的情况下,去掉了 Kafka 层。由于 Fluentd 可以支持数据和大文件存储,因此数据能够被持久化地存入磁盘。

我们给每个应用都直接对应了一个 tag,以方便各个应用对应到自己的 tag、遵循自己的固定规则、并最终写入 ES,这样就方便了出现问题的各自定位。

另外,我们运用延迟计算和文件切分也能快速地找到问题的根源。因此我们节约了 Kafka 和 ES 各种计算资源。

在实际操作中,由于 HBase 不用去做 raid,它自己完全能够控制磁盘的写入,因此我们进行了数据压缩。就其效果而言,ES 的存储开销大幅降低。

在后期,我们也尝试过一种更为极端的方案:让用户直接通过客户端的 Shell 去查询数据,并采用本地缓存的留存机制。

优化效果

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

优化的效果如下:

  • 服务器资源的有效利用。在实施了新的方案之后,我们省了很多服务器,而且单台服务器的存储资源也节省了 15%。

  • 单核处理每秒原来能够传输 3000 条,实施后提升到了 1.5~1.8 万条。而且,在服务器单独空跑,即不加任何计算时,单核每秒能传输近 3 万条。

  • 很少触发 ES 保护机制。原因就是我们已把数据分流出来了。

  • 以前历史数据只能存 7 天,由于我们节省了服务器,因此我们现在可以存储更长时间的数据。而且,对于一些他人查询过的日志,我们也会根据最初的策略,有选择性地保留下来,以便追溯。

日志系统优化总结

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

关于日志平台优化,我总结了如下几点:

  • 由于日志是低频次的,我们把历史数据存入了廉价存储之中,普通用户需要的时候,我们再导到 ES 里,通过 Kibana 的前端界面便可快速查询到。而对于 程序员 来说,则不需要到 ES 便可直接查询到。

  • 数据存在的时间越长,则意义越小。我们根据实际情况制定了有效的、留存有意义数据的策略。

  • 顺序写盘替代内存。例如:区别于平常的随机写盘,我们在操作读写一个流文件时采取的是按顺序写数据的模式。

  • 而在存储量大的时候,则应当考虑 SSD。特别是在 ES 遇到限流时,使用 SSD 可以提升 ES 的性能。

  • 提前定制规范,从而能够有效解决后期分析等工作。

日志格式

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

如上图所示,常用的日志格式类型包括:uuid、timestamp、host 等。

特别是 host,由于日志会涉及到几百个节点,有了 host 类型,我们就能判定是哪台机器上的标准。而图中其他的环境变量类型,则能够有效地追溯到一些历史的信息。

日志方案

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

如上图所示,我们通过 Rsyslog 可以直接将采集端的数据写入文件或数据库之中。

当然,对于一些暂时用不上的日志,我们不一定非要实施过滤传输的规则。

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?

如上图,Fluentd 也有一些传输的规则,包括:Fluentd 可以直接对接 Fluentd,也可以直接对接 MongoDBMySQL 等。

另外,我们也有一些组件可以快速地对接插件和系统,例如让 Fluentd 和 Rsyslog 能够直接连到 ES 上。

这是我个人给大家定制的一些最基本的基线,我认为日志从采集、缓存、传输、存储,到最终可视化,分成了三套基线。

采集到存储是最简单的一个,像 Rsyslog 到 hdfs 或者其他 filesystem,我们有这种情况。

比较常见的情况,就是从采集、传输、到存储可视化,然后形成最终我们现在最复杂的一套系统,大家可以根据实际情况取舍。

最后是我考虑到一个实际情况,假如这个案例,我们尽可能少的占有服务器,然后传输需要过滤转换,日志可以比较简单,符合这种 Key value(KV)格式。

我们可以按照取了一个 Rsyslog、取了一个 Fluentd、取了一个 Hbase,取了一个 echars 等这么一个方式做一个方案就可以了。

我觉得 Rsyslog、Fluentd、heka 这些都可以做采集。然后传输这块有 Fluentd 传输,因为 Fluentd 和 Kafka 到插件非常灵活可以直接对接我们很多存储设备,也可以对应很多的文件、连 ES 都可以。

可视化可以用 Kibana,主要是跟 ES 结合得比较紧密,它们结合在一起需要一点学习成本。

作者:杨津

编辑:陈峻、陶家龙、孙淑娟

更多技术干货分享

尽在 51CTO技术栈 微信公众号

10年大数据架构师:日访问百亿级,如何架构并优化日志系统?


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Distributed Systems

Distributed Systems

Sukumar Ghosh / Chapman and Hall/CRC / 2014-7-14 / USD 119.95

Distributed Systems: An Algorithmic Approach, Second Edition provides a balanced and straightforward treatment of the underlying theory and practical applications of distributed computing. As in the p......一起来看看 《Distributed Systems》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具