数极客首页

从日志统计到大数据分析(五)——楚汉争霸

痛定思痛,我们觉得主要问题出在数据源上。百度有上百条业务线(有一定业务规模的),牵涉到数千个日志模块,每个模块的日志格式都是不一样的。甚至就连Web Server这层,有用Apache的,有用Lighpd的,也有用Nginx的,用的软件版本可能还是不同的。日志格式五花八门,输出的是非结构化的文本字符串,比如Nginx一条日志:

219.136.113.46 – – [09/Dec/2015:15:06:12 +0800] “GET /manual/edu_case.html HTTP/1.1” 200 6339 “数据分析 | Sensors Analytics 使用手册” “Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 UBrowser/5.5.7852.9 Safari/537.36”

这里包括了IP、时间、访问的URL、Referral、User Agent字段(Windows 7,UC浏览器),许多日志要比这个复杂的多。这一行日志的字段是用空格分割的,但User Agent里又包含了空格,如果你要去解析出来各个字段,逻辑就会很复杂且耗费计算资源。如果URL中还包括多个参数,比如tn=3&fn=5之类的,那就很难分别是什么含义了,除非是最初设计这个参数的人。

归结起来主要有这么四个问题:

(1)数据解析效率低——为了解析出来各个字段,使用正则表达式外加一堆逻辑,很消耗计算资源,还容易出现错乱。

(2)数据内容不可理解——不知道一些字段是什么含义,需要和系统开发者去沟通确认。

(3)格式变更影响下游——如果你要增加个参数、变更个字段类型,都需要和下游的使用方去确认。比如像网页搜索那样的业务线,大量的业务线依赖于其生成的数据,真的不敢轻举妄动,一般约定往最后追加字段。中间废弃的字段,也不敢轻易删除,否则下游的解析全部出错。

(4)占用存储空间大——因为是文本字符串,比如12345678,就占用了8个字节,但如果作为一个整数存放,只占用4个字节。当然,可以采用将搜到的日志后续压缩的方式,但压缩过程又会好用大量的计算资源。

这么多的问题,有没有办法解决呢?这里就要隆重引入本篇的主角——Google Protocol Buffer(简称PB),它是Google对外开源的一种数据格式,用于网络通讯或者数据存储。下面是个简单的例子:

message Person {

required string name = 1;

required int32 id = 2;

optional string email = 3;

}

这里定义了一个类型叫Person的proto,里面有三个字段,name、id、email。每个字段都被编号,并且带有类型。这很像C语言中的结构体。那它有什么好处呢?我归结起来有以下四点:

(1)数据解析效率高——你可以理解为将一个二进制的结构体序列化存盘后再读取加载到内存,和文本字符串的反解,性能不在一个量级,且不会解析错乱。

(2)数据带有Schema——每个PB数据文件,配上一个proto定义文件,就可以当成一个数据库的数据表来理解了,每个字段含义明确。

(3)格式变更向前向后兼容——一个程序向前兼容不难理解,新版本的word能够读取出来旧版本的word文档(如.doc)。但向后word能够读取出来旧版本的word文档。但向后兼容就不容易了,也就是旧版本的word能够读取出来新版本word文档(如.docx),这个就很难保证了。但PB就有这个优势,对于一个旧版本protoproto文件对应的解析程序,在读取proto文件对应的解析程序,在读取新版本proto文件时,新增加的字段不会读取,已有字段能够顺利读出proto文件对应的解析程序,在读取新版本proto文件时,新增加的字段不会读取,已有字段能够顺利读出。这样就完美解决了字段变更的问题(主要是增加新字段)。proto文件对应的解析程序,在读取新版本proto文件时,新增加的字段不会读取,已有字段能够顺利读出。这样就完美解决了字段变更的问题(主要是增加新字段),下游不关心新字段的根本不用改动。

(4)节省存储和带宽——PB文件自带压缩功能,相比文本格式,正常能够减少30%-50%的数据量。如果只是一个几百M的文件,体现不出优势来,如果是100个PB呢?

说了这么多的好处,那有哪些不足呢?

(1)原生支持的语言有限——Java、Python、C++(在前一段开放的v3版本,已经支持了更广泛的语言。)。而在百度用的比较多的还有PHP,没有原生支持,只有一个充满bug性能低下的第三方开源版本。

(2)没有原生RPC,模块之间传递PB数据,需要额外开发(v3版本也有了RPC)。

(3)PB文件不可直接阅读,不利于工程师Debug。

(4)需要编译。定义好了proto格式,还需要使用compiler编译为指定的语言。这可没工程师直接printf来的自在。

讲了这么多文本日志和PB日志的优缺点,我们还是回到PB在百度的推进过程。

我最早是在2010年初的时候接触到PB,那个时候在网页搜索部已经开始尝试这种数据格式,但我对它的价值认识不清楚。Log平台最早支持的Schema功能,也支持输出Json格式。在2011年下半年我们开展UDW项目的时候,ETL过程分成两个阶段。第一个阶段将文本日志转成PB格式,第二个阶段将PB格式再转换到UDW大表中。你可能会问为啥不直接在源头输出成PB格式,这个就叫做尾大不掉,让已有运行的好好的业务线切换一下输出格式,并且对产品绩效毫无影响,这是很难接受的,我们就采用了这种折中的方式。但在2012年下半年的时候我们逐步意识到这里所存在的维护问题。当时从腾讯过来了一个架构师,他深受Google技术的影响,你可能还依稀记得当时腾讯从Google请了几个人做自己的搜索,将Google的技术理念都带了过去,这位架构师就是深受影响。他在熟悉了百度的数据业务之后,就强烈建议从源头改成打印PB格式,这样很有助于长远发展。我向来是一个对最好的理念抱有乐观态度的人。我俩一拍即合,积极的推进数据源的PB化工作。

为了实现数据源的PB化,有一系列的工具需要配合,我们先后做了这么几件事:

(1)开发PHP版本的PB库——这个主要基于开源版本的修改,主要是修复bug和提升数据写入效率。

(2)实现PB的RPC框架——这个是由另一个部门的一个同学友情实现的。

(3)开发了一个反解PB到文本格式的工具Codex,部署在所有的服务器,方便工程师阅读PB内容。

(4)开发了一套PB格式审查系统,保证每个数据源的格式变更,都是经过管理员审核的,避免数据的胡乱打印。

(5)制定了一套全公司统一数据打印规范,哪些公共字段必须要打,哪些是可以灵活添加的。

做完这几件事情差不多就到2013年中了,之后就是推动工作了。有时候实现一个系统不是最难的,难的是推动已有的业务切换过去。好在我在推动Log平台在全公司使用,推动UDW在全公司的使用,可以说是早已习惯了这样的工作。当时为了激励团队,我安排开发了个中国地图,把核心业务线都标记为省市,如果完成到PB的切换,就插红旗,如果正在进行,就插绿旗,就这样看看万里江山慢慢被红旗插遍。个中痛苦,只有经历的人可知。但这是我在百度第二有成就感的事情。我回顾在百度这几年,许多时候是花一个季度开发一个系统,又花两个季度替换旧的系统,迁移成本很高。

这种日志结构化的方式,让数据的接入代价提升,但一旦接入,就变成可维护的,并且不需要ETL就可以直接使用。在2012年初老大给我讲Google那边能够打了日志马上就可以分析,我都觉得很不可思议,那时候百度的延迟至少是小时级的。可经过两年多的努力,我们也达到了这一点。

我这里梳理一下为达到这点所牵涉到的组件:

(图1 数据流相关组件)

自底向上,我们可以把数据源从产生到最终可视化,看做一条流。这种数据流的意识,是在我做了3~4年的数据工作之后才主要认识清晰的。从源头来说,我们通过日志打印库完成数据的生成工作。然后通过一个叫Minos的系统完成数据的实时传输,这个系统类似Scribe和Flume,在运维性上,要好非常多。如果需要入UDW,就通过ETL框架实现,否则就直接存放为PB格式。通过Query Engine提供查询服务,这基于Hive修改,后来我们开发了一套叫Wing的查询引擎,比Hive性能提升很多。通过Insight来实现数据的报表、曲线之类的可视化。此外,还需要有Meta Server管理元数据,通过Scheduler完成任务调度,这些都是我们自己开发的。

使用PB直接进行数据分析,还是基于UDW进行,这是两种理念,也就是我题目中的楚汉争霸。

讲到这里,我在百度的故事就要完了。总结这整个过程,我越来越发现对数据平台来说,有两点是最关键的,一点是数据源,要高质量,一点是元数据,所有模块都和它打交道。这两点如果做好了,数据平台就不会太差。在下一篇中,我会讲解根据数据源的流向不同,常见的三种数据分析模式。

本文采用「CC BY-SA 4.0 CN」协议转载学习交流,内容版权归原作者所有,如涉作品、版权和其他问题请联系「我们」处理。

发表评论

评论已关闭。

相关文章