首页 文章 精选 留言 我的

精选列表

搜索[学习],共10000篇文章
优秀的个人博客,低调大师

Git学习-->关于Jenkins编译时候,如何获取Git分支的当前分支名?

一、背景 因为代码都迁移到了Gitlab,所以Jenkins编译的时候我们都需要将之前的SVN信息换成现在的Git信息。最近编译一个Lib库的时候,因为团队规定上传Release版本的AAR到Maven的话,必须需要在Jenkins上编译而且Git Branch 必须是master分支才能够上传到Maven。 因此我们就需要在Gradle脚本中,获取Git Branch ,Git Commit等相关信息。但是在获取Git Branch的时候出现了问题,在本地Android Studio编译的时候能够获取到Git Branch的名字,但是使用Jenkins编译的时候,一直获取不到信息。 下面是我写的一份gradle文件,用于获取Git和Jenkins的相关信息 /** * 获取Git 分支名 */ def getGitBranch() { return 'git symbolic-ref --short -q HEAD'.execute().text.trim() } /** * 获取Git 版本号 */ def getGitSHA() { return 'git rev-parse --short HEAD'.execute().text.trim() } /** * 获取Git Tag */ def getGitTag() { return 'git describe --tags'.execute([], project.rootDir).text.trim() } /** * 获取Git 提交次数 */ def getGitCommitCount() { return 100 + Interger.parse('git rev-list --count HEAD'.execute([], project.rootDir).text.trim()) } /** * 判断是否有jenkins */ boolean isInJenkins() { Map<String, String> map = System.getenv() if (map == null) { return false } String str = map.get("Path") if (str != null) { //it's windows return false } else { str = "" Iterator it = map.iterator() while (it.hasNext()) { str += it.next() } return str.contains("jenkins") } } /** * 获取jenkins任务名 */ def getJenkinsName() { boolean flag = isInJenkins() if (flag) { ext.env = System.getenv() ext.name = env.JOB_URL String[] stringArray = ext.name.split("/") if (stringArray.length > 0) { return stringArray[stringArray.length - 1] } else { return "Local" } } else { return "Local" } } /** * 获取Jenkins Build 号 * @return */ def getJenkinsBuildCode() { boolean flag = isInJenkins() if (flag) { ext.env = System.getenv() ext.buildNumber = env.BUILD_NUMBER?.toInteger() return "$buildNumber" } else { return 0 } } /** * 定义几个变量,在build.gradle里面引用 */ ext { gitTag = getGitTag() gitBranch = getGitBranch() gitSHA = getGitSHA() jenkinsRevision = getJenkinsBuildCode() jenkinsName = getJenkinsName() } 其中的方法,getGitBranch方法在Android Studio编译的时候,能够正常获取到Git分支名。 println "pom_version_type = " + pom_version_type println "jenkinsName = " + jenkinsName println "gitBranch = " + gitBranch 我在进行编译的时候,是会通过如上代码打印出Git Branch的信息。 在Android Studio 本地编译的时候,是可以打印出相关的信息的。 但是在Jenkins编译的时候,是不能够上传的,如下所示: 二、解决方法 后来我尝试找了很多种方法去获取Git Branch的名字,在Android Studio本地都可以获取到,如下所示: 参考链接:https://stackoverflow.com/questions/6245570/how-to-get-the-current-branch-name-in-git 方法1、git symbolic-ref --short -q HEAD D:\GitLab Source\XTCLint>git symbolic-ref --short -q HEAD master D:\GitLab Source\XTCLint> 方法2、git rev-parse --abbrev-ref HEAD D:\GitLab Source\XTCLint>git rev-parse --abbrev-ref HEAD master 方法3、git branch | grep \* | cut -d ' ' -f2 D:\GitLab Source\XTCLint>git branch | grep \* | cut -d ' ' -f2 master 方法4、git symbolic-ref HEAD | sed -e "s/^refs\/heads\///" D:\GitLab Source\XTCLint>git symbolic-ref HEAD | sed -e "s/^refs\/heads\///" master 以上所有的方法,仅仅在Android Studio的终端或者本地gradle代码中有效,然而在Jenkins服务器编译的时候都是获取为空。 后来我查看了Jenkins的Git插件上的介绍,参考链接:https://wiki.jenkins.io/display/JENKINS/Git+Plugin 如上所示,在上面的链接中有介绍,有几个Environment variables环境变量可以使用。 Environment variables The git plugin sets several environment variables you can use in your scripts: GIT_COMMIT - SHA of the current GIT_BRANCH - Name of the remote repository (defaults to origin), followed by name of the branch currently being used, e.g. “origin/master” or “origin/foo” GIT_LOCAL_BRANCH - Name of the branch on Jenkins. When the “checkout to specific local branch” behavior is configured, the variable is published. If the behavior is configured as null or **, the property will contain the resulting local branch name sans the remote name. GIT_PREVIOUS_COMMIT - SHA of the previous built commit from the same branch (the current SHA on first build in branch) GIT_PREVIOUS_SUCCESSFUL_COMMIT - SHA of the previous successfully built commit from the same branch. GIT_URL - Repository remote URL GIT_URL_N - Repository remote URLs when there are more than 1 remotes, e.g. GIT_URL_1, GIT_URL_2 GIT_AUTHOR_NAME and GIT_COMMITTER_NAME - The name entered if the “Custom user name/e-mail address” behaviour is enabled; falls back to the value entered in the Jenkins system config under “Global Config user.name Value” (if any) GIT_AUTHOR_EMAIL and GIT_COMMITTER_EMAIL - The email entered if the “Custom user name/e-mail address” behaviour is enabled; falls back to the value entered in the Jenkins system config under “Global Config user.email Value” (if any) 然后我将这几个变量,在一个app的Jenkins任务中,编译完成后的邮件内容中添加了这几个变量的内容,如下所示: 在构建后的操作中,Editable Email Notification的邮件通知中,将邮件内容改为如下所示的代码。 $DEFAULT_CONTENT <br /> <font color="#0B610B">单元测试</font> <li>Launcher单元测试报告&nbsp;:<a href="${BUILD_URL}testReport">点击查看测试报告</a></li> <li>Launcher代码覆盖率&nbsp;:<a href="${BUILD_URL}jacoco">点击查看代码覆盖率</a></li> <li>Launcher Android Lint&nbsp;:<a href="${BUILD_URL}androidLintResult">点击查看Android Lint</a></li> <br /> <li>GIT_COMMIT&nbsp;:${GIT_COMMIT}</a></li> <li>GIT_BRANCH&nbsp;:${GIT_BRANCH}</a></li> <li>GIT_LOCAL_BRANCH&nbsp;:${GIT_LOCAL_BRANCH}</a></li> <li>GIT_PREVIOUS_COMMIT&nbsp;:${GIT_PREVIOUS_COMMIT}</a></li> <li>GIT_PREVIOUS_SUCCESSFUL_COMMIT&nbsp;:${GIT_PREVIOUS_SUCCESSFUL_COMMIT}</a></li> <li>GIT_URL&nbsp;:${GIT_URL}</a></li> <li>GIT_URL_N&nbsp;:${GIT_URL_N}</a></li> <li>GIT_AUTHOR_NAME&nbsp;:${GIT_AUTHOR_NAME}</a></li> <li>GIT_COMMITTER_NAME&nbsp;:${GIT_COMMITTER_NAME}</a></li> <li>GIT_AUTHOR_EMAIL&nbsp;:${GIT_AUTHOR_EMAIL}</a></li> <li> GIT_COMMITTER_EMAIL&nbsp;:${ GIT_COMMITTER_EMAIL}</a></li> 这样编译完后,收到的邮件内容如下: 如上所示,收到的邮件内容包含了Git的相关信息: GIT_COMMIT :118fa74e6a09c8c5ae713523692add256bfa6afb GIT_BRANCH :origin/feature/UseByAnonymousDBMigrateAndApiChange GIT_LOCAL_BRANCH :${GIT_LOCAL_BRANCH} GIT_PREVIOUS_COMMIT :118fa74e6a09c8c5ae713523692add256bfa6afb GIT_PREVIOUS_SUCCESSFUL_COMMIT :118fa74e6a09c8c5ae713523692add256bfa6afb GIT_URL :git@172.28.1.116:Android/WatchApp/Third/NetEaseCloudMusic.git GIT_URL_N :${GIT_URL_N} GIT_AUTHOR_NAME :${GIT_AUTHOR_NAME} GIT_COMMITTER_NAME :${GIT_COMMITTER_NAME} GIT_AUTHOR_EMAIL :${GIT_AUTHOR_EMAIL} GIT_COMMITTER_EMAIL :${ GIT_COMMITTER_EMAIL} 其中,GIT_BRANCH这个环境变量的值为origin/feature/UseByAnonymousDBMigrateAndApiChange,代表Jenkins上/UseByAnonymousDBMigrateAndApiChange分支远程Gitlab上该分支映射的远程分支。因此我们可以对GIT_BRANCH这个环境变量做做文章。 将之前gradle脚本中的getGitBranch方法,做如下修改,区分编译环境是Jenkins还是本地。环境不同,运行不同的脚本获取Git Branch的名字。当处于Jenkins环境的时候,先通过GIT_BRANCH这个环境变量获取到Jenkins拉下来的分支对应的远程分支,然后通过字符串分离,获取到分支名。 /** * 获取Git 分支名 * *参考Jenkins git 创建文档: https://wiki.jenkins.io/display/JENKINS/Git+Plugin * Environment variables The git plugin sets several environment variables you can use in your scripts: GIT_COMMIT - SHA of the current GIT_BRANCH - Name of the remote repository (defaults to origin), followed by name of the branch currently being used, e.g. "origin/master" or "origin/foo" GIT_LOCAL_BRANCH - Name of the branch on Jenkins. When the "checkout to specific local branch" behavior is configured, the variable is published. If the behavior is configured as null or **, the property will contain the resulting local branch name sans the remote name. GIT_PREVIOUS_COMMIT - SHA of the previous built commit from the same branch (the current SHA on first build in branch) GIT_PREVIOUS_SUCCESSFUL_COMMIT - SHA of the previous successfully built commit from the same branch. GIT_URL - Repository remote URL GIT_URL_N - Repository remote URLs when there are more than 1 remotes, e.g. GIT_URL_1, GIT_URL_2 GIT_AUTHOR_NAME and GIT_COMMITTER_NAME - The name entered if the "Custom user name/e-mail address" behaviour is enabled; falls back to the value entered in the Jenkins system config under "Global Config user.name Value" (if any) GIT_AUTHOR_EMAIL and GIT_COMMITTER_EMAIL - The email entered if the "Custom user name/e-mail address" behaviour is enabled; falls back to the value entered in the Jenkins system config under "Global Config user.email Value" (if any) * * */ def getGitBranch() { //判断是否处于Jenkins编译环境 boolean flag = isInJenkins() if (flag) { ext.env = System.getenv() ext.gitBranch = env.GIT_BRANCH String[] stringArray = ext.gitBranch.split("/") if (stringArray.length > 0) { return stringArray[stringArray.length - 1] } else { return "UnKnown Branch" } } else { return 'git symbolic-ref --short -q HEAD'.execute().text.trim() } } 完整代码如下所示: /** * 获取Git 分支名 * *参考Jenkins git 创建文档: https://wiki.jenkins.io/display/JENKINS/Git+Plugin * Environment variables The git plugin sets several environment variables you can use in your scripts: GIT_COMMIT - SHA of the current GIT_BRANCH - Name of the remote repository (defaults to origin), followed by name of the branch currently being used, e.g. "origin/master" or "origin/foo" GIT_LOCAL_BRANCH - Name of the branch on Jenkins. When the "checkout to specific local branch" behavior is configured, the variable is published. If the behavior is configured as null or **, the property will contain the resulting local branch name sans the remote name. GIT_PREVIOUS_COMMIT - SHA of the previous built commit from the same branch (the current SHA on first build in branch) GIT_PREVIOUS_SUCCESSFUL_COMMIT - SHA of the previous successfully built commit from the same branch. GIT_URL - Repository remote URL GIT_URL_N - Repository remote URLs when there are more than 1 remotes, e.g. GIT_URL_1, GIT_URL_2 GIT_AUTHOR_NAME and GIT_COMMITTER_NAME - The name entered if the "Custom user name/e-mail address" behaviour is enabled; falls back to the value entered in the Jenkins system config under "Global Config user.name Value" (if any) GIT_AUTHOR_EMAIL and GIT_COMMITTER_EMAIL - The email entered if the "Custom user name/e-mail address" behaviour is enabled; falls back to the value entered in the Jenkins system config under "Global Config user.email Value" (if any) * * */ def getGitBranch() { //判断是否处于Jenkins编译环境 boolean flag = isInJenkins() if (flag) { ext.env = System.getenv() ext.gitBranch = env.GIT_BRANCH String[] stringArray = ext.gitBranch.split("/") if (stringArray.length > 0) { return stringArray[stringArray.length - 1] } else { return "UnKnown Branch" } } else { return 'git symbolic-ref --short -q HEAD'.execute().text.trim() } } /** * 获取Git 版本号 */ def getGitSHA() { return 'git rev-parse --short HEAD'.execute().text.trim() } /** * 获取Git Tag */ def getGitTag() { return 'git describe --tags'.execute([], project.rootDir).text.trim() } /** * 获取Git 提交次数 */ def getGitCommitCount() { return 100 + Interger.parse('git rev-list --count HEAD'.execute([], project.rootDir).text.trim()) } /** * 判断是否有jenkins */ boolean isInJenkins() { Map<String, String> map = System.getenv() if (map == null) { return false } String str = map.get("Path") if (str != null) { //it's windows return false } else { str = "" Iterator it = map.iterator() while (it.hasNext()) { str += it.next() } return str.contains("jenkins") } } /** * 获取jenkins任务名 */ def getJenkinsName() { boolean flag = isInJenkins() if (flag) { ext.env = System.getenv() ext.name = env.JOB_URL String[] stringArray = ext.name.split("/") if (stringArray.length > 0) { return stringArray[stringArray.length - 1] } else { return "Local" } } else { return "Local" } } /** * 获取Jenkins Build 号 * @return */ def getJenkinsBuildCode() { boolean flag = isInJenkins() if (flag) { ext.env = System.getenv() ext.buildNumber = env.BUILD_NUMBER?.toInteger() return "$buildNumber" } else { return 0 } } /** * 定义几个变量,在build.gradle里面引用 */ ext { gitTag = getGitTag() gitBranch = getGitBranch() gitSHA = getGitSHA() jenkinsRevision = getJenkinsBuildCode() jenkinsName = getJenkinsName() } 现在测试下Jenkins编译是否正常,可以看到一切都正常了。 参考链接 https://wiki.jenkins.io/display/JENKINS/Git+Plugin https://stackoverflow.com/questions/6245570/how-to-get-the-current-branch-name-in-git 作者:欧阳鹏 欢迎转载,与人分享是进步的源泉! 转载请保留原文地址:http://blog.csdn.net/ouyang_peng/article/details/77802596 如果觉得本文对您有所帮助,欢迎您扫码下图所示的支付宝和微信支付二维码对本文进行随意打赏。您的支持将鼓励我继续创作!

优秀的个人博客,低调大师

一步一步学习大数据:Hadoop生态系统与场景

Hadoop概要 到底是业务推动了技术的发展,还是技术推动了业务的发展,这个话题放在什么时候都会惹来一些争议。 随着互联网以及物联网的蓬勃发展,我们进入了大数据时代。IDC预测,到2020年,全球会有44ZB的数据量。传统存储和技术架构无法满足需求。在2013年出版的《大数据时代》一书中,定义了大数据的5V特点:Volume(大量)、Velocity(高速)、Variety(多样)、Value(低价值密度)、Veracity(真实性)。 当我们把时间往回看10年,来到了2003年,这一年Google发表《Google File System》,其中提出一个GFS集群中由多个节点组成,其中主要分为两类:一个Master node,很多Chunkservers。之后于2004年Google发表论文并引入MapReduce。2006年2月,Doug Cutting等人在Nutch项目上应用GFS和 MapReduce思想,并演化为Hadoop项目。 Doug Cutting曾经说过他非常喜欢自己的程序被千万人使用的感觉,很明显,他做到了;下图就是本尊照片,帅气的一塌糊涂 2008年1月, Hadoop成为Apache的开源项目。 Hadoop的出现解决了互联网时代的海量数据存储和处理,其是一种支持分布式计算和存储的框架体系。假如把Hadoop集群抽象成一台机器的话,理论上我们的硬件资源(CPU、Memoery等)是可以无限扩展的。 Hadoop通过其各个组件来扩展其应用场景,例如离线分析、实时处理等。 Hadoop相关组件介绍 本文主要是依据Hadoop2.7版本,后面没有特殊说明也是按照此版本 HDFS HDFS,Hadoop Distributed File System (Hadoop分布式文件系统)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。它和现有的分布式文件系统有很多共同点,例如典型的Master/Slave架构(这里不准备展开介绍);然而HDFS是一个高度容错性的系统,适合部署在廉价的机器上。 关于HDFS主要想说两点。 HDFS中的默认副本数是3,这里涉及到一个问题为什么是3而不是2或者4。 机架感知(Rack Awareness)。 只有深刻理解了这两点才能理解为什么Hadoop有着高度的容错性,高度容错性是Hadoop可以在通用硬件上运行的基础。 Yarn Yarn,Yet Another Resource Negotiator(又一个资源协调者),是继Common、HDFS、MapReduce之后Hadoop 的又一个子项目。Yarn的出现是因为在Hadoop1.x中存在如下几个问题: 扩展性差。JobTracker兼备资源管理和作业控制两个功能。 可靠性差。在Master/Slave架构中,存在Master单点故障。 资源利用率低。Map Slot(1.x中资源分配的单位)和Reduce Slot分开,两者之间无法共享。 无法支持多种计算框架。MapReduce计算框架是基于磁盘的离线计算 模型,新应用要求支持内存计算、流式计算、迭代式计算等多种计算框架。 Yarn通过拆分原有的JobTracker为: 全局的 ResourceManager(RM)。 每个Application有一个ApplicationMaster(AM)。 由Yarn专门负责资源管理,JobTracker可以专门负责作业控制,Yarn接替 TaskScheduler的资源管理功能,这种松耦合的架构方式 实现了Hadoop整体框架的灵活性。 Hive Hive的是基于Hadoop上的数据仓库基础构架,利用简单的SQL语句(简称HQL)来查询、分析存储在HDFS的数据。并且把SQL语句转换成MapReduce程序来数据的处理。 Hive与传统的关系数据库主要区别在以下几点: 存储的位置 Hive的数据存储在HDFS或者Hbase中,而后者一般存储在裸设备或者本地的文件系统中。 数据库更新 Hive是不支持更新的,一般是一次写入多次读写。 执行SQL的延迟 Hive的延迟相对较高,因为每次执行HQL需要解析成MapReduce。 数据的规模上 Hive一般是TB级别,而后者相对较小。 可扩展性上 Hive支持UDF/UDAF/UDTF,后者相对来说较差。 HBase HBase,是Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统。它底层的文件系统使用HDFS,使用Zookeeper来管理集群的HMaster和各Region server之间的通信,监控各Region server的状态,存储各Region的入口地址等。 HBase是Key-Value形式的数据库(类比Java中的Map)。那么既然是数据库那肯定就有表,HBase中的表大概有以下几个特点: 大:一个表可以有上亿行,上百万列(列多时,插入变慢)。面向列:面向列(族)的存储和权限控制,列(族)独立检索。 稀疏:对于为空(null)的列,并不占用存储空间,因此,表可以设计的非常稀疏。 每个cell中的数据可以有多个版本,默认情况下版本号自动分配,是单元格插入时的时间戳。 HBase中的数据都是字节,没有类型(因为系统需要适应不同种类的数据格式和数据源,不能预先严格定义模式)。 Spark Spark是由伯克利大学开发的分布式计算引擎,解决了海量数据流式分析的问题。Spark首先将数据导入Spark集群,然后再通过基于内存的管理方式对数据进行快速扫描 ,通过迭代算法实现全局I/O操作的最小化,达到提升整体处理性能的目的,这与Hadoop从“计算”找“数据”的实现思路是类似的。 Other Tools Phoneix 基于Hbase的SQL接口,安装完Phoneix之后可以适用SQL语句来操作Hbase数据库。 Sqoop Sqoop的主要作用是方便不同的关系数据库将数据迁移到Hadoop,支持多种数据库例如Postgres,Mysql等。 Hadoop集群硬件和拓扑规划 规划这件事情并没有最优解,只是在预算、数据规模、应用场景下之间的平衡。 硬件配置 Raid 首先Raid是否需要,在回答这个问题之前,我们首先了解什么是Raid0以及Raid1。 Raid0是提高存储性能的原理是把连续的数据分散到多个磁盘上存取,这样,系统有数据请求就可以被多个磁盘并行的执行,每个磁盘执行属于它自己的那部分数据请求。这种数据上的并行操作可以充分利用总线的带宽,显著提高磁盘整体存取性能。(来源百度百科) 当Raid0与Hadoop结合在一起会产生什么影响呢? 优势: 提高IO。 加快读写。 消除单块磁盘的读写过热的情况。 然而在Hadoop系统中,当Raid0中的一块磁盘数据出现问题(或者读写变得很慢的时候)时,你需要重新格式化整个Raid,并且数据需要重新恢复到DataNode中。整个周期会随着数据的增加而逐步增加。 其次Raid0的瓶颈是Raid中最慢的那一块盘,当你需要替换其中最慢的那一块盘的时候就会重新格式化整个Raid然后恢复数据。 RAID 1通过磁盘数据镜像实现数据冗余,在成对的独立磁盘上产生互 为备份的数据。当原始数据繁忙时,可直接从镜像拷贝中读取数据,因此RAID 1可以提高读取性能。RAID 1是磁盘阵列中单位成本最高的,但提供了很高的数据安全性和可用性。当一个磁盘失效时,系统可以自动切换到镜像磁盘上读写,而不需要重组失效的数据。(来源百度百科) 所以Raid1的本质是提高数据的冗余,而Hadoop本身默认就是3个副本,所以当存在Raid1时候,副本数将会变成6,将会提高系统对于硬件资源的需求。 所以在Hadoop系统中不建议适用Raid的,其实更加推荐JBOD,当一块磁盘出现问题时,直接unmount然后替换磁盘(很多时候直接换机器的)。 集群规模及资源 这里主要依据数据总量来推算集群规模,不考虑CPU以以及内存配置。 一般情况来说,我们是根据磁盘的的需求来计算需要机器的个数。 首先我们需要调研整个系统的当量以及增量数据。 举个例子来说,假如现在系统中存在8T的数据,默认副本数为3,那么所需要的存储=8T*3/80% = 30T左右。 每台机器存储为6T,则数据节点个数为5。 加上Master节点,不考虑HA的情况下,大概是6台左右机器。 软件配置 根据业务需求是否需要配置HA方案进行划分,由于实际场景复杂多变,下面方案仅供参考。 1.非HA方案 一般考虑将所有的管理节点放在一台机器上,同时在数据节点上启动若干个Zookeeper服务(奇数)。 管理节点:NameNode+ResourceManager+HMaster 数据节点:SecondaryNameNode 数据节点:DataNode +RegionServer+Zookeeper 2.HA方案 在HA方案中,需要将Primary Node 与Standby Node 放在不同的机器上,一般在实际场景中,考虑到节省机器,可能会将不同的组件的Master节点进行交叉互备,如A机器上有Primary NameNonde 以及 Standby HMaster ,B机器上有Standby NameNode 以及 Primary Master。 管理节 点:NameNode(Primary)+HMaster(Standby) 管理节点:NameNode(Standby)+HMaster(Primary) 管理节点:ResourceManager 数据节点:DataNode +RegionServer+Zookeeper Hadoop的设计目标和适用场景 其实在上面的Hadoop概要上我们就可以看到Hadoop当初的设计目标是什么。Hadoop在很多场合下都是大数据的代名词。其主要是用来处理半结构以及非结构数据(例如MapReduce)。 其本质也是通过Mapreduce程序来将半结构化或者非结构化的数据结构化继而来进行后续的处理。 其次由于Hadoop是分布式的架构,其针对的是大规模的数据处理,所以相对较少的数据量并不能体现Hadoop的优势。例如处理GB级别的数据量,利用传统的关系型数据库的速度可能相对较快。 基于上述来看Hadoop的适用场景如下: 离线日志的处理(包括ETL过程,其实本质就是基于Hadoop的数据仓库)。 大规模并行计算。 Hadoop的架构解析 Hadoop由主要由两部分组成: 分布式文件系统(HDFS),主要用于大规模的数据存储。 分布式计算框架MapReduce,其主要用来对HDFS上的数据进行运算处理。 HDFS主要由NameNode(Master)以及DataNode(Slave)组成。前者主要是对命名空间管理:如对HDFS中的目录、文件和块做类似 文件系统的创建、修改、删除、列表文件和目录等基本操作。后者存储实际的数据块,并与NameNode保持一定的心跳。 MapReduce2.0的计算框架本质是有Yarn来完成的,Yarn是关注点分离的思路,由Yarn专门负责资源管理 ,JobTracker可以专门负责作业控制,Yarn接替 TaskScheduler的资源管理功能,这种松耦合的架构方式 实现了Hadoop整体框架的灵活性。 MapReduce工作原理和案例说明 MapReduce可谓Hadoop的精华所在,是用于数据处理的编程模型。MapReduce从名称上面可以看到Map以及Reduce两个部分。其思想类似于先分后合,Map对与数据进行抽取转换,Reduce对数据进行汇总。其中需要注意的是Map任务将输出结果存储在本地磁盘,而不是HDFS。 在我们执行MapReduce的过程中,根据Map与数据库的关系大体上可以分为三类: 数据本地 机架本地 跨机架 从上述几种可以看出来,假设一个MapReduce过程中存在大量的数据移动对于执行效率来说是灾难性。 MapReduce数据流 从数据流来看MapReduce的关系大体可以分为以下几类: 单Reduce 多Reduce 无Reduce 然而无论什么MapReduce关系如何,MapReduce的执行流程都如下图所示: 其中在执行每个Map Task时,无论Map方法中执行什么逻辑,最终都是要把输出写到磁盘上。如果没有Reduce阶段,则直接输出到HDFS上。如果有Reduce作业,则每个Map方法的输出在写磁盘前线在内存中缓存。每个Map Task都有一个环状的内存缓冲区,存储着Map的输出结果,默认100m,在每次当缓冲区快满的时候由一个独立的线程将缓冲区的数据以一个溢出文件的方式存放到磁盘,当整个Map Task结束后再对磁盘中这个Map Task产生的所有溢出文件做合并,被合并成已分区且已排序的输出文件。然后等待Reduce Task来拉数据。 上述这个过程其实也MapReduce中赫赫有名的Shuffle过程。 MapReduce实际案例 Raw Data原始的数据文件是普通的文本文件,每一行记录中存在一个年份以及改年份中每一天的温度。 MapMap过程中,将每一行记录都生成一个key,key一般是改行在文件中的行数(Offset),例如下图中的0,106代表第一行、第107行。其中粗体的地方代表年份以及温度。 Shuffle该过程中获取所要的记录组成键值对{年份,温度}。 Sort将上一步过程中的相同key的value组成一个list,即{年份,List<温度>},传到Reduce端。 ReduceReduce端对list进行处理,获取最大值,然后输出到HDFS中。 上述过程进行总结下来流程如下: 本文作者:Lee 来源:51CTO

优秀的个人博客,低调大师

《认知设计:提升学习体验的艺术》——为什么大脑就像一个衣橱

为什么大脑就像一个衣橱思考一个主题,并与你所擅长的专业联系起来。你会有怎样的思维模式呢?像下面哪种情形?如果你是专家,很可能你会拥有第一种思维模式—规范有序,有许多不同的类别,分不同的区域,有一个精密的信息组织方式。如果你是一名新手,你对所了解的信息只能有很简陋的架构。如果有人将一件蓝色的毛衣交给专家,让他将这件毛衣放进衣橱里,他能够快速地决定将这件毛衣放在哪里,因为他已经非常了解衣橱里的结构(放在毛衣的衣架上,就在冬季衣服的旁边,按照重量或款式,甚至颜色进行排序)。但当你将相关内容交给一名初学者,他们将会很为难地看着这块他们所不知道的信息,耸耸肩,然后将它丢到信息衣橱中,任由它们堆在那里。我们都有过这些培训经历,在那里你获得一堆信息,你所能做的只是尽力使自己跟上。更大的问题出现在当你希望某人重新检索这些信息时。作为专家,你有各种

优秀的个人博客,低调大师

Yann LeCun连发三弹:人人都懂的深度学习基本原理(附视频)

一名 AI 专家值多少钱? “基于我个人经验,一名计算机领域的 AI 专家对于企业的价值,至少为 500-1000 万美元。为了争夺这些少数的人才,正在开展竞标大战。” 这是卡耐基梅隆大学计算机科学院院长 Andrew Moore 教授在 11 月 30 日美国参议院听证会上 ,所说的话。 这场听证会名为“AI 破晓”(The Dawn of Artificial Intelligence),由参议员泰德·科鲁兹主持,主题是探讨人工智能当前的形势,对政策的影响及其对商业形态的改变。共有 5 位 AI 专家出席,分别是: Eric Horvitz(微软研究实验室总经理,人工智能伙伴关系委员会临时共同主席) Andrew Moore(卡耐基梅隆大学计算机科学院院长) Andrew Futreal(德州大学安德森癌症中心基因医学教授) Greg Br

优秀的个人博客,低调大师

【巨头升级寡头】AI产业数据称王,GAN和迁移学习能否突围BAT垄断?

AI时代,数据为王让巨头越来越难以被打败 上周,谷歌和 CMU 的一项合作研究,为拥有大数据优势的技术巨头们带来了喜讯:在不调整现有算法、只是给模型多得多的数据的情况下,图像识别结果取得了较大提升。 这一波人工智能的兴起主要有三大因素推动——计算力、数据和算法。而谷歌和 CMU 的这项合作研究可能会将“数据”这一项进一步高亮显示。 据 Wired 报道,研究结果一方面印证了通过给模型喂食多得多的数据,同样的算法也能显著提升性能,另一方面,这也是对拥有海量数据的技术巨头的喜讯。无论是谷歌、Facebook 还是微软,都会更加坚信自己手中的数据是决胜的王牌。虽然从1百万扩充到3百万数据集,对象检测的结果只提高了3个百分点,但研究者表示,他们相信如果对软件进行调整,使其更适应于超大数据集,那么优势还将扩大。退一万步说,即使没有扩大

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册