首页 > 网络 > 云计算 >

PPTV大数据基础平台升级总结

2016-09-12

伴随着PPTV各项业务的快速发展,为了方便各业务部门洞察相关业务情况,我们于2011年底启动了内部大数据平台的建设。PPTV大数据基础平台升级总结

伴随着PPTV各项业务的快速发展,为了方便各业务部门洞察相关业务情况,我们于2011年底启动了内部大数据平台的建设。目前,我们已建成大数据分析基础平台和大数据应用平台。基础分析平台主要是基于Hadoop生态圈建立起从数据收集到业务自助分析报表的整个数据流通过程;应用平台则是在基础平台之上,建立起数据模型,为挖掘、推荐、推送、DMP等关键业务提供数据服务。

基于业务规模、系统兼容性等因素考虑,我们最终选择了基于CDH构建整个数据平台,为了适配外部多种数据源,我们开发了内部ETL工具logtransform, logtransform是一个单一的MR Job,将存放在HDFS上的各种原始日志进行清洗、维度填充,最终转换成RCFile格式的文件存放到Hive中,用于后续的查询分析。同时,我们平台中大部分自助报表和ad-hoc查询都是基于Hive的,随着平台用户越来越多,各种不同频率的业务报表也随之增多,报表之间的依赖也越来越复杂,我们使用Oozie作为调度工具,构建了报表自动提交系统,能够自动分析出报表间依赖,在报表满足执行条件后自动提交报表。

整个数据平台大部分是基于MapReduce任务完成,在14年初,生产环境演进到cdh4.5,整个Hadoop集群计算节点两百多台,存储节点300多台,存储容量6PB,此外还有一个各包含二十多台机器的HBase集群和用于实时计算的Storm集群,每天处理原始日志2TB,大约一千多个报表、三千多个任务稳定运行。

随着社区的快速发展,到16年初,CDH已发布基于Hadoop2.6的5.5稳定版,相对于4.5,Hadoop/Hive在功能和性能上都有比较大的提升,为了能利用最新的技术提升为业务服务的效率,同时解决Hadoop与大数据生态里其他组件的兼容性,我们决定将CHD升级到最新的稳定版。整个过程中,我们做了以下主要工作:

升级调度框架,将MR1全部升级成Yarn 建立预发环境,及早发现问题修改业务代码,升级Jar包,测试兼容性阅读官方文档,制定详细计划升级数据节点,集群调优

升级调度框架

CDH4.5于2011年底发布,已包含Yarn相关功能,相较于MR1的JobTracker, Yarn主要是将资源调度和任务管理功能分开,分离后的ResourceManager负责资源分配和管理,MRAppMaster负责单个任务的监控管理,这样提高了资源管理能力和可靠性,方便了集群规模的扩展。也许当时Yarn还不是很成熟的原因,官方文档上有很多Yarn的介绍,但并没有推荐在生产环境部署。Yarn是一个资源调度框架,不仅可以管理MR这样批处理任务,也可以管理类似Storm长期执行的任务,由于它是无状态的,计算数据从HDFS等外部存储系统加载,因此升级Yarn不存在数据丢失问题,只需升级后保证以前的任务能在预定的时间内执行成功即可。CDH5.x版本中官方已推荐使用Yarn,在正式升级到5.x之前,我们决定先在4.x基础上将调度框架升级成Yarn,这样既能降低风险,又能积累Yarn相关经验,为后续整个Hadoop升级做好准备工作。

在保持生产环境HDFS正常运行的情况下,我们在集群中开辟了一台机器作ResourceManager,外加三十台机器作NodeManager,MR1和Yarn共享HDFS。由于Yarn完全兼容MR1 API,只需更改相关配置就能在这两种调度方式间来回替换,除了更改一般配置外,我们主要对Container相关参数进行配置调优,主要有以下几个参数:

yarn.nodemanager.reource.memory-mb: 单个Node上Yarn管理的最大内存,根据Node可使用RAM分配

yarn.scheduler.minimum-allocation-mb: 每个container的最小内存

mapreduce.map.memory.mb: 每个map container的大小,应大于minimum-allocation-mb

mapreduce.reduece.memory.mb: 每个reduce container的大小,一般应大于mapreduce.map.memory.mb

mapreduce.map.java.opts: 启动Map Child的选项,-Xmx应小于mapreduce.map.memory.mb

mapreduce.reudece.java.opts: 启动Reduce Child的选项,-Xmx应小于mapreduce.reduce.memory.mb

yarn.nodemanager.resource.cpu-vcores: 单个Node上可分配最大vcore数,一般一个物理core对应一到两个vcore

yarn.scheduler.minimum-allocation-vcores: 每个Container最小vcore数

mapreduce.map.cpu.vcores: 每个map child分配的vcore数,应大于等于yarn.scheduler.minimum-allocation-vcores

mapreduce.reduce.cpu.vcores: 每个reduce child分配的vcore数,一般大于等于mapreduce.map.cpu.vcores

注意以上container大小是逻辑上物理内存限制,并不是实际分配物理内存大小,当实际需分配的大小超过逻辑限制时,container会被RM kill掉,分配请求不会被满足。我们先确保Yarn配置正确,验证hive on yarn没有性能问题后,将部分MR job迁移到yarn上执行,经过一个星期左右的观察和调整,同时根据业务重要性和集群资源基于fairscheduler对查询任务划分了不同优先级的可用资源池,最终将大部分的查询任务平稳地迁移到yarn上,为后续整个平台升级做好了计算引擎的升级工作。

建立预发环境

为了方便此次升级前的验证工作,同时也为了减少平时线上发布的错误,我们clone生产环境,建立了一个大约线上十分之一规模的预发环境,仅保留最近一周的数据,部署了主要的业务系统,选择部分重要业务日志在流入生产环境的同时也流入预发环境,将一些重要业务报表在预发环境也进行调度执行,验证预发环境的正确性和计算速度。我们将升级和回退方案在预发集群上演练了两遍,避免了升级过程中的操作失误,也帮助测试了业务正确性和兼容性,极大提高了大家对成功升级的信心,为后续业务发展、上线提供了基础环境和流程规范。

升级业务代码

在正式升级Hadoop之前,我们先升级了HBase, 升级HBase后发现cdh4.5相关的客户端无法直接访问Hbase,主要原因是hadoop相关组件使用protobuf进行序列化,而cdh4.5中使用的是protobuf2.4, cdh5.x使用protobuf2.5,很多最新的hadoop生态中的软件也都依赖protobuf2.5,而这两个版本之间并不兼容,升级业务代码时需要去掉所有对protobuf2.4的依赖。

同时,我们开发了全新的业务调度系统赤兔,将系统中ETL、维度同步、业务监控等很多通过crontab调度的业务通过赤兔进行统一调度管理,这样既利于对业务的监控,也方便后续业务间的融合。

制定升级方案

保证平台能够正常运行的主要组件是Hadoop、Hive和Oozie,Hadoop是重中之重,Hive和Oozie升级相对方便容易,参考Cloudera官方文档中从CDH4升级到CDH5的步骤,以及升级可能的问题,我们制定了如下升级步骤:

JDK升级

生产环境中CDH4.5使用了Java 1.6,但是CDH5.x并不能在JDK1.6上运行,根据官方文档版本兼容关系,我们选择Java 1.7.0_75作为升级后的java版本,此版本既能运行CDH5.x,也兼容CDH4.x。升级JDK很简单,只需将集群中所有节点上的java替换成1.7后重起相关服务即可。

HDFS升级

CDH4.5升级前NameNode和ResourceManager都存在单点故障问题,我们将这两个重要服务升级成HA模式。HDFS保存着整个系统的数据,是平台的基石,保证数据不丢失是衡量升级是否成功的重要标志,元数据是HDFS的核心,升级HDFS就是升级元数据和数据块。元数据升级时先在主NN上以非HA模式升级成功后,再将变更同步至备NN扩展成HA。

1.在安全模式下生成最新的元数据镜像。

hdfs dfsadmin -safemode enter

hdfs dfsadmin -saveNamespace //保存在${dfs.name.dir}/current目录下

2.生成旧版本文件列表,用于升级后对比。

hadoop fsck / -files > dfs-v-old-fsck-1.log

3.停止所有服务,备份所有配置。备份元数据,即NN上dfs.name.dir/current目录;备份DataNode上{dfs.datnode.data.dir}/current/VERSION文件,方便回退。DataNode升级并不需要双倍的空间,cdh4.5与cdh5.5的HDFS格式并没有改变,备份过程中如果current目录中有in_user.lock文件,代表有服务未停止,需先停止服务后再备份。

4.安装CDH5.5,可事先安装但不启动服务,同时安装业务使用但cdh pacakage不包含的库,比如hadoop-lzo-xxx-snapshot.jar,$HADOOP_HOME/lib/native/目录下动态库,本地动态库需针对目标机器编译。

5.在主NN上根据实际情况修改环境变量hadoop-env.sh及HDFS相关配置core-site.xml、hdfs-site.xml,注意此时配置为非HA。

6.主NN上升级元数据。

$HADOOP_HOME/sbin/hadoop-daemon.sh --config $HADOOP_HOME/etc/hadoop_noha start namenode -upgrade

7.主NN升级成功后关闭主NN,修改配置为HA。

8.启动JournalNode,JournalNode是轻量级的,应至少配置三个后台进程,用于在主NN和备NN之间同步editlog,保证主NN和备NN具有一致的元数据。

$HAOOP_HOME/sbin/hadoop-daemon.sh start journalnode

$HADOO_HOME/bin/hdfs namenode -initializeSharedEdits //主NN上执行,初始化JournalNode

9.启动主NN。

$HADOOP_HOME/sbin/hadoop-daemon.sh start namenode

10.启动备NN。

$HADOOP_HOME/bin/hdfs namenode -bootstrapStandby

$HADOOP_HOME/sbin/hadoop-daemon.sh start namenode //元数据同步,UI上可看到同步进度

11.启动ZKFC,ZKFC在每个NN上运行,监控NN的状态,维持NN与zookeeper之间的联系,使NN失败后能自动切换。

hdfs start zkfc -formatZK //某台NN上执行,创建znode

$HADOOP_HOME/sbin/hadoop-daemon.sh start zkfc //两台NN节点自动zkfc

12.启动所有DataNode。

$HADOOP_HOME/sbin/hadoop-daemon.sh start datanode

13.生成新版本文件列表,与旧版本对比,验证升级正确性。

$HADOOP_HOME/bin/hadoop fsck / -files > dfs-v-new-fsck-1.log

14.调整Yarn相关配置,mapred-site.xml、yarn-site.xml等, 由于oozie原因mapreduce.jobhistory.done-dir和mapreduce.jobhistory.intermediate-done-dir目录需配置成一样。

15.启动ResourceManager和JobHistory。

$HADOOP_HOME/sbin/yarn-daemon.sh start resourcemanager

$HADOOP_HOME/sbin/mr-jobhistory-daemon.sh start historyserver

16.启动所有Nodemanager。

$HADOOP_HOME/sbin/yarn-daemon.sh start nodemanager

17.确认hdfs升级成功后,删除DN上升级过程中产生的临时文件,谨慎执行。

$HADOOP_HOME/bin/hdfs dfsadmin -finalizeUpgrade //任意NN节点执行

HDFS回滚

如果HDFS无法升级成功,为了保证数据不丢失,必须进行回退。

1.关闭所有服务,恢复相关配置。

2.主NN回退。

$HADOOP_HOME/sbin/hadoop-daemon.sh start namenode -rollback

3.回退所有DN。

用备份的VERSION文件替换current目录下的VERSION

$HADOOP_HOME/sbin/hadoop-daemon.sh start datanode -rollback

4.生成回退文件列表,验证回退是否成功。

hadoop fsck / -files > dfs-v-old-fsck-rollback.log

Hive升级

Hive升级相对容易,主要是meta表结构可能有变化,官方提供了升级工具,提前备份好MySQL中的metadata,即使升级失败也容易回退。

1.停止所有Hive相关服务及,备份Mysql元数据库

2.可事先安装新版本,修改相关配置(hive-env.sh、hive-site.xml)。

3.复制MySQL对应版本JDBC Jar包都$HIVE_HOME/lib目录下。

4.升级Hive Metadata。

$HIVE_HOME/bin/schematool -dbType mysql -upgradeSchemaFrom 0.10.0

5.由于NameNode变更,需要修改hive metadata表中location相关字段,在MySQL中批量更新。

update DBS set DB_LOCATION_URI = replace(DB_LOCATION_URI,"10.208.30.41:9000","biphdfs");

update SDS set LOCATION = replace(LOCATION,"10.208.30.41:9000","biphdfs");

6.启动MetaStore。

$HIVE_HOME/bin/hive --service metastore >/home/logs/hive/metastore.log 2>&1 &

7.启动HiveServer2。

$HIVE_HOME/bin/hive --service hiveserver2 >/home/logs/hive/thriftserver2.log 2>&1 &

8.使用Beeline验证。

$HIVE_HOME/bin/beeline -u jdbc:hive2://hiveserer2_host:10000

Oozie升级

Oozie升级也很容易,只需安装成功,保证Workflow能正常提交调度即可,因为历史Workflow并不重要,丢弃也不会对新任务有影响。

1.安装新版本。

2.修改配置(oozie-env.sh、oozie-site.xml),在Oozie Conf目录下创建到Hadoop Conf的软链接。

ln -s $HADOOP_CONF_DIR $OOZIE_CONF_DIR/conf/hadoop-conf //hadoop conf变更后oozie需重启才能生效

3.HDFS上创建Oozie Action使用的sharelib。

删除oozie-sharelib-4.1.0-cdh5.5.4.tar.gz,保留oozie-sharelib-4.1.0-cdh5.5.4-yarn.tar.gz

$OOZIE_HOME/bin/oozie-setup.sh sharelib create -fs hdfs://biphdfs

4.复制Hadoop相关jar包到$OOZIE_HOME/libext。

cp $OOZIE_HOME/src/hadooplibs/hadoop-cdh5mr2/target/hadooplibs/hadooplib-2.6.0-cdh5.5.4.oozie-4.1.0-cdh5.5.4/* $OOZIE_HOME/libext

cp ext-2.2.zip $OOZIE_HOME/libext

5.复制连接MySQL的JDBC JAR包到$OOZIE_HOME/lib及libext目录下。

6.初始化数据库。

$OOZIE_HOME/bin/ooziedb.sh create -sqlfile $OOZIE_HOME/bin/oozie.sql

$OOZIE_HOME/bin/oozie-setup.sh db create -run -sqlfile $OOZIE_HOME/bin/oozie.sql

7.安装Oozie UI war包。

$OOZIE_HOME/bin/oozie-setup.sh prepare-war

正式升级

升级过程中影响的基本都是离线相关业务,实时性不强,我们沟通各业务方做了容错性处理,保证在两天之内升级成功即可。虽然在预发布环境做了充分的演练测试,毕竟预发布与生产环境还有量的差别,我们评估了升级过程中可能出现的问题,主要是hdfs升级过程中可能数据丢失,以及升级后计算速度慢两大问题。

少量数据块丢失

按照预先步骤,首先进行HDFS升级,在fsck生成机器文件列表时还是出现了小插曲,最后我们按文件重要性分类,对重要目录进行fsck,保证重要目录不会出现数据丢失,最终经过四到五个小时,HDFS升级完成;当时升级完成后,出现了一个DataNode上数据块无法加载,由于HDFS多备份冗余性,直接下线有问题的DataNode,并不会丢失数据。

计算慢

在升级到Yarn后,遇到了无法正常调度计算的问题,当时有很多任务提交,reduce占用资源无法结束,而map又获取不到足够资源,整个job不能正常完成,后续任务不能正常调度,最终通过减少reduce占用vcore资源的数量,以及推迟reduce启动时机,将reduce启动时机参数mapreduce.job.reduce.slowstart.completedmaps设置为1,在一个job中所有map执行完成后才启动reduce,这样虽然降低了资源利用率,增加了job整体完成时间,但job能顺利完成,暂时解决了资源无法正常调度问题。

此外,我们的原始日志进行解析后使用了gzip压缩格式存储,gzip模块依赖Native库,与OS版本有关,最初我们没有注意到集群中Linux内核版本有差异,在一台机器上编译生成native库后直接复制到其他机器上,导致有些机器上解析后的日志不可读,最后针对特定OS编译本地库安装即可。

在Hive升级后还出现有些hql由于语法不兼容无法运行的问题,整个升级过程有惊无险,在整个team的共同努力,解决了一个个升级过程中的坑,最终集群平稳升级,所有业务数据恢复正常。

升级经验及未来规划

正式升级前,存储重要业务数据的Hbase已提前升级,实时计算基本不依赖HDFS,我们将平台各个组件分开依次升级,降低了各个组件间影响;整个升级,对开发、测试和运维是一次重新审视整个平台和业务的过程,升级后,大家对平台理解更深刻,流程也更加规范了。虽然整个升级过程并没有我们预想的那么顺利,但事先做好充足的准备和计划是升级成功的重要保证,能让大家保持充足的信心,临危不乱。

CDH5.5包含了最新的特性,对Hadoop生态中其他组件提供了良好的兼容性和支持,升级后关键组件都具有了HA特性,HiveServer2替换了HiveServer,具有更高的安全性和可靠性,此次升级为平台后续更快更好地为业务服务奠定了良好的基础。此外,我们计划在平台中利用以下特性提升效率:

使用beeline,beeline是官方推荐的hive查询工具,在cdh5.x后,原始的cli已被废弃利用Hue通过web方式查询hive/oozie/hbase相关数据使用Tez作为hive的执行引擎,Tez能够极大的优化hive的查询效率将spark相关的任务迁移至大集群,共享资源利用kylin构建cube进行多维数据分析

相关文章
最新文章
热点推荐