对大数据平台的一些理解
大数据是目前比较火的领域,它涉及的领域比较广泛,例如数据挖掘、机器学习等等;所有这些基于数据的操作能够正常工作的前提是:搭建相应的大数据收集平台,在该平台中能够通过主动和被动的方式收集到足够的数据;一般情况下,大数据平台里的数据来源主要有:
(1) 日志数据,相对于大数据平台,这是一种主动收集数据的方式;这种方式可能是大数据平台中最主要的数据来源,并且随着用户请求量、服务数量的增长,日志数据的数据将会成倍增长;此种方式收集的数据可能会有大量的无效数据(可能当前我们用不到这些数据),但是对于后续的数据挖掘会有较大的用处;
(2) 上报数据,相对于大数据平台,这是一种被动收集数据的方式,这种方式收集的数据针对性强,基本都是有效数据,而且格式比较统一,便于数据分析和处理;
我们为什么要做大数据平台?
这与我们采用的技术方案有关,我们在组建后台研发团队后做的第一个项目是:推送系统,要求支持千万级在线用户,显然它的潜在要求是支持高并发,高可靠性;另外,由于目前用量还不够多,因此整个系统要能够动态扩缩容;为了设计支持如此的需求,我们采用了分布式服务的架构(其实我们一直很避讳谈微服务,我认为的微服务就是分布式服务的更规范化、通用化、自动化的一种实现形式),这样我们的推送就被设计成了多个独立的子服务程序,服务之间采用rpc通信(rpc框架使用了我们最为熟悉的Thrift),这一切都很顺利,我们整个系统最小化的集群部署(每个服务都是一个实例运行)可以轻松超越1500qps,整个系统的容量、并发性也都能随着水平扩展而增加,基本上满足了需求;后续我们逐步新增加了类似设计思想的IM、VOIP等业务以及分布式ID生成器、通用评论系统等等一系列平台性服务。等到这些服务陆续上线的之后,我们面临的问题逐渐出现了(只列出一部分):
(1) 当使用过程中遇到问题时,我们就得找运维同事把全部相关子服务日志都弄下来,对于运维,需要挨个机子把这些服务的日志文件取下来,对于研发来说,我们需要从第一个服务程序开始,挨个查找每个服务的日志文件,不仅非常麻烦,而且不利于定位问题!
(2) 每个服务上的日志文件都有一定的保存期限,例如保留最近7天的日志文件,这样当我们想要分析7天之前的日志时可能就找不到了;
(3) 有时候,一些问题可能要跨越好几天的日志文件,我们也不知道到底该要哪一天的日志,这时就得对每个服务的每天的日志都进行分析,这个工作量太大了;
不过,好的一点是我们提前对后台业务的日志格式做了规定:
(1) 我们要求所有的日志输出都必须带日志索引;
(2) 日志索引必须在每条日志的特定位置以特殊形式加进来;
(3) 所有的接口函数必须在第一个参数提供日志索引,让调用方传递日志索引进来;
(4) 在服务的入口处,需要从我们自研的分布式ID生成器中获取一个唯一的日志ID;
这样一个请求进入到系统,它的所有日志输出都是使用同一个日志ID,只要我们找到了对应请求的日志ID,就可以寻找到这个请求在所有服务中的日志信息;只是,我们目前得拿着这个日志ID到每个服务的日志文件里面去寻找!
为了解决这个问题,我们决定搭建自己的大数据平台,其实对于这个问题,有很多公司采用了常用的ELK三件套来解决,我们则考虑了如下几点:
(1) 支撑各种日志的高效解析、处理和分析,我们未来的业务量可能会非常大,涉及到的新服务也会越来越多,我们就需要这个系统能够接受并解析各种日志;
(2) 随着后续业务的发展,这些日志数据不仅能被用来解决“查找日志难”的问题,还可以做更多的数据分析,因此我们不仅需要ES的数据检索功能,还需对全部原日志数据的存储功能,以便后续spark做更复杂的分析和处理;
(3) ES中的数据存在也有冷热之分,越是近期的数据越有可能被访问,越是时间久的数据其热度月底,可能一个月之前的数据就不会被我们通过es来检索了。因此ES中的数据在一定时期内要定期清除,这时,我们就需要一个地方来存储全部的源日志数据,以便后续spark进行更为复杂的离线数据分析;
(4) 这套系统不仅应该能主动收集各服务的日志数据,还可以接受阁各种数据传入,即它是一个数据平台,而非一个日志分析工具;
我们如何构建自己的大数据平台?
针对我们当时的分析,并结合前几年曾经使用过的方案,最终决定采用如下方式:flume+Kafka+strom+ElasticSearch+Kibana+HDFS+Spark
这套新方案的大概思路为:
这里:
(1) Flume agent部署在每个服务上,它读取每个服务的日志文件,并将读取的结果发送到kafka中;
(2) 数据上报服务是自研的服务中心,它主要用于接收所有的上报数据,包括客户端上报的数据以及部分业务服务上报的数据,主要用于后续的统计分析;
(3) Kafka主要对来自各种数据源的数据进行汇总,当storm处理的速度大于这些数据上报的数据时,Kafka还可以对数据进行缓冲;
(4) ES作为搜索引擎,它存储了最近一个月的数据,并对数据提供检索以及部分统计功能;
(5) HDFS负责存储所有的数据,我们在storm处理中,几乎任何源数据都会存储在HDFS中一份;
(6) Strom 集群中,是每个类型的业务数据一个topology,例如:尽管我们统一了后台各服务的日志格式,但是由于后台采用的语言不同,并且还有很多采用开源软件,对于这部分与我们规定不一样的日志格式,就需要特殊处理;另外,ES为了加快检索速度,需要对关键字段进行提取,并组装成json格式,这部分的处理工作也是有ES来完成;以日志处理为例:我们需要从日志中提取出来时间、服务名称、线程名、文件名、行号、类名、方法名、日志索引等检索关键词,然后将这些关键词以及源数据组装成json格式存储到ES里,并且还要将日志按照各服务名称存储到HDFS中;
(7) Kibana是ES的展示界面,我们主要通过Kibana来对es中的数据进行检索;
(8) Spark主要用于离线数据处理。
如何实施大数据平台?
大数据平台已经上线一年多了,期间遇到的各种问题也逐渐解决,系统已经进入稳定运营和使用阶段,回顾过去实施的经历,还是有不小感慨:小步慢跑,千万别急;大数据平台听着比较热,如果没有实际业务趋势,很难在公司里引起重视,并且实施下去,大家都是呼声高做起来难!这就要求我们在架构设计时要能够迭代,无论是搭建这样大数据平台,还是前期设计各种分布式服务的应用都是如此;我们在搭建这套服务的时候基本分为了这样几个过程:
(1) 预研并且搭建起来flume+kafka+storm,能够将数据收集过来并且传入到storm;
(2) Storm对接es、Kibana,让整个流程跑通;
(3) 根据我们的业务,对storm的topology进行设计和分析,然后再进行topology的开发;
(4) 对上述业务上线运营;
(5) 新增全数据存储功能,引入HDFS;
(6) 扩展数据源,引入数据上报服务中各种的数据,当然这一步也要对应的storm的topology来进行处理;
在我们实践过程中遇到的问题以及解决办法:
(1) flume多行日志合并收集;原生的flume是逐条从日志文件中收集日志数据,不支持多行日志的归并收集,这种场景主要针对java服务程序;例如:我们的java服务程序,在抛出异常时,要打印异常堆栈,这些堆栈信息都是每个调用占用一行,如此以来一条java异常日志内容将会被打印多行,flume现在无法处理这个问题:flume按行进行处理,它每收集一行日志就将之丢到kafka,Kafka会把每个丢过了的数据作为一个独立的整体,我们从storm中再也无法将这些多行的日志合并到了同一行中;
我们解决的办法是修改flume的源码:由于我们自研java程序都有日志规范,我们可以据此来识别出哪一行是日志的开始,哪一行不是!这样在flume进行日志手机的时候,进行延迟一条上报,即如果新读取的一行数据是一条新日志的开始,则将缓存的数据上交给kafaka,如果不是,则这条日志数据与本地缓存中的拼接起来;
(2) flume 的断点续传;例如,当flume挂掉再重启的时候,要能够从上次读取到的位置继续读取,不能文件的开头读,这样会在日志系统中出现大量的重复日志数据;断点续传是flume本身就具备的功能,使用时进行相关配置即可;
(3) storm连接es时,必须在topology中配置全部(或者尽可能多的)的es地址,不然,一旦所连接的es挂掉,es就会出现进程假死的问题。
作者:Alukar
链接:https://www.jianshu.com/p/5dfa0f3367a9