HadoopMapreduce
HadoopMapreduce
我们假设有一个1T的文本数据,对其中的"出场"二字进行统计。
《斗罗大陆》的艺术成就主要是在人物形象塑造方面的体现,较为突出人物个性。与传统文学相比,《斗罗大陆》有着自己的特点,具体表现为:
对人物的刻画倾向于突出个性,忽略人物外貌的特点。没有硬性规范人物的形象,对于作品中人物的外貌都没有细致描写,模糊了主人公的外观。语言文学的这种模糊性与简洁性,给了读者极大的想象空间。譬如说仅仅给出年龄和生活的环境的简单介绍让读者用想象结合经验创造一个属于自己的主角,调动了读者阅读的兴趣与积极性
人物的出场各具特点。每个人的出场情节都是各有特点,有别于一般传统小说人物出场时先对人物的衣着、神情、语言一一描写,而在文中人物出现时,都会事先对于当时的场景进行细腻的描写,以情节的发展渲染气氛而推出重要人物,这是文中人物出场的表现方式。虽然,许多文章会在介绍人物之前对周边环境进行叙述但侧重点依然是人物的外貌介绍。文中喜欢使用欲扬先抑的写作手法,例如,文中唐三的出场,前世因违背了门规追杀而死后穿越成为异世的一员,开始新的闯荡的一生。这就是对于唐三的出场,一种从生到死,由死而生的轮回之感。在文中有一个新生命的开始,开始了新生活的延续。而他前身出身唐门给予他得天独厚的能力,也为后文中他留了强大的力量左右了另一个世界。而另一位的出场则是运用了传统的先声夺人的写作,经常利用对比的方法反转人物出场时的第一印象,使人物给人一种新鲜的感受,不拘泥于传统式出场后的定位一般会表现出人物的性格后发生巨大改变
用战斗突出人物的性格,用战斗中的心理描写体现人物的多面性。对故事的情节进行侧重描写,把战斗过程作为描写的侧重点。在《斗罗大路》中有很多战斗的场面,每场战斗都具有自己的特色,文中的战斗就如同婴孩的成长历程,可以分成几个阶段,从初出茅庐到年少骄傲,从千手修罗到温婉公子,从国仇家恨到最终的完结,战斗陪伴他成长。在前往斗罗帝国的路上,按大师要求参加比赛,与凶神战队的比赛中,第一次杀人,使他们认识到世界的黑暗面,这是他们的第一次成长,文章对赛后他们每个人的反应进行细致的刻画,以此呈现每个人不同的性格特点。大陆精英赛是史莱克七怪的拼搏之路,他们与不同的敌人战斗,在压力下不断成长。在星罗皇家帝国时,经历皇室兄弟间的厮杀,使他们认识到权力之争的残酷,了解了权力的重要性,还明白有足够的实力才能掌握自己的命运,一场皇权之争使他们开始接触政治。这两次战斗经历在文中起着关键作用,对后文的情节发展起推动作用。《斗罗大陆》中的战斗与其他网络小说不同,场面并非宏大或血腥,给读者留下深刻印象,并向读者表达着主人公在每场战斗中的成长,所以文章虽然频繁描写战斗场景,但是充分体现了网络文学的美,以战斗为文章主线,将小说中的人物自然分成两大阵营,塑造不同的场景,如代表正义势力的唐三家族与代表反派力量的武魂殿势力,在文中形成对比;文中还对美与丑进行对比,通过战前对比比东准备的描写,可以看出比比东是被丑化了的角色,是文中的反派,因爱恨,使他的一生发生了改变,这就是文学艺术中美学形象的体现,对人物形象进行丑化,如比比东在文中的存在就是美学中丑化的具体体现,无论任何原因都不能改变的丑角形象,他是自我矛盾的对比,与文中的美形成鲜明对比,是文中典型的对比艺术形象,是一种区别于美的另一种形式,这也是一种美。在文中唐三是智者的代表,在文章开始就表现得淋漓尽致,如去史莱克学院的入学考试时,同实力相差悬殊的老师进行对战尽管输了,但也是展现了他的聪慧。战前,对每个人进行分析,战斗中知道自己的身体已经到达极限后依然计算着如何应对老师,这份智,使他每每在危险关头生存下来,这也是他性格中的重要标签之一。另外在史莱克七怪中,奥斯卡的坚持也让人感慨颇深,他是文中最弱的人,但内心的坚持最强,对于荣荣的情,从最初的朦朦胧胧到付出一切后的有情人终成眷属使他走出了属于自己的一条路,也是他坚持的最好体现。他的坚持让他如愿以偿,在生死中间不断徘徊,不断突破自己。同时,文中深情的小舞,冷情的竹清,柔情的荣荣等等,都有独特个性,在文中无论发生什么,角色本质都从未改变。也是在这个基础上他们性格各异,却融合成为一体。这是文中的一个重要特色,没有具体的人物描写,只以人物的个性为特点突出人物形象,形成独特的协作特点...... -百度百科
Map阶段
Block块切分
首先:MapReduce计算所需要的数据是必须在hdfs中存在的,我们需要先将文件上传至hdfs。
将文本数据放入hdfs后,hdfs会按照每个block块默认128MB的方式切分该文本数据,直至切分至总block块可以完整的存入该数据的内容。
切片split
map阶段,先将数据按照逻辑划分若干个切片,默认与block块大小一致。倒数两个block块,会将实际存储的大小加起来,与128*1.1进行比较,若比这个值大,则两个block块分别切片,若小于这个值,则只会产生一个切片。
切片数==map任务数。
思考:map任务的数量可以自己控制吗?
答:不能直接设置map任务的数量,map任务取决于split切片的个数,但我们可以通过调整split切片的大小,来影响split切片的数量,进而调整map任务的数量。
MapTask
map任务中的逻辑是作用在每一行的,一行数据一旦被map任务读取到,就会被封装成<key,value>的格式,这一行数据经过map任务的处理之后出来的数据同样也是<key,value>的形式
而这个处理的过程需要经过map()函数,该map()函数则由我们用户自定义处理逻辑。
但是内存的大小是有限的,如果每个任务随机的去占用内存,会导致内存不可控。多个任务同时执行有可能内存溢出(OOM)
如果把数据都直接放到硬盘,效率太低
于是我们引入下一个环节:
环形缓冲区
环形缓冲区:基于内存构建一种数据结构,主要解决的问题是内存的输出速度与磁盘的写入速度不匹配。默认大小是100M【可以修改】。
数据进入到环形缓冲区做的事情:
1、进入环形缓冲区的数据是map任务计算后的结果数据,依旧是一个键值对类型的数据;先针对键进行哈希计算,公式与reduce的个数reduce的个数,将来可以自定义】有关。
公式:hash("出场")% number(reduce)= 编号将来我们的reduce个数设置为2,结果只能是0或1。假设所有“出场”的编号是0,“人物”的编号都是1
编号的目的:决定了将来该条数据会被哪一个reduce所拉取处理。
2、对环形缓冲区的数据进行排序【快速排序】
3、当环形缓冲区,达到80%的内容的时候,将这80%的内存一起写入到一个磁盘文件中。每达到一次80%的时候,都会生成一个磁盘文件。默认情况下,一个map任务会产生两个小文件。
分区partition(环形缓冲区处理)
根据Key直接计算出对应的Reduce
分区的数量和Reduce的数量是相等的
hash(key) % partation(reduce的数量) = num
默认分区的算法是Hash然后取余
Object的hashCode()—equals()
如果两个对象equals,那么两个对象的hashcode一定相等
如果两个对象的hashcode相等,但是对象不一定equlas
排序sort(环形缓冲区处理)
快速排序,对前面分区后的编号进行排序,使得相同编号的在一起
对要溢写的数据进行排序(QuickSort)
按照先Partation后Key的顺序排序–>相同分区在一起,相同Key的在一起
我们将来溢写出的小文件也都是有序的
溢写(环形缓冲区处理)
将内存中的数据循环写到硬盘,不用担心OOM问题
每次会产生一个80M的文件
如果本次Map产生的数据较多,可能会溢写多个文件
合并(环形缓冲区处理)
因为溢写会产生很多有序(分区 key)的小文件,而且小文件的数目不确定
后面向reduce传递数据带来很大的问题
所以将小文件合并成一个大文件,将来拉取的数据直接从大文件拉取即可
合并小文件的时候同样进行排序(归并 排序),最终产生一个有序的大文件
组合器Combiner
集群的带宽限制了mapreduce作业的数量,因此应该尽量避免map和reduce任务之间的数据传输,hadoop允许用户对map的输出数据进行处理,用户可自定义combiner函数(如同map函数和reduce函数一般,其逻辑一般和reduce函数一样,combiner的输入是map的输出,combiner的输出作为reduce的输入,很多情况下可以i直接将reduce函数作为conbiner函数来试用(job.setCombinerClass(FlowCountReducer.class))。
combiner属于优化方案,所以无法确定combiner函数会调用多少次,可以在环形缓存区溢出文件时调用combiner函数,也可以在溢出的小文件合并成大文件时调用combiner,但是要保证不管调用多少次,combiner函数都不影响最终的结果,所以不是所有处理逻辑都可以i使用combiner组件,有些逻辑如果试用了conbiner函数会改变最后reduce的输出结果(如求几个数的平均值,就不能先用conbiner求一次各个map输出结果的平均值,再求这些平均值的平均值,那样会导致结果的错误)。
combiner的意义就是对每一个maptask的输出进行局部汇总,以减小网络传输量:
原先传给reduce的数据时a1 a1 a1 a1 a1
第一次combiner组合后变成a(1,1,1,1,1)
第二次combiner后传给reduce的数据变为a(5,5,6,7,23,...)
Fetch拉取
属于map到reduce的过渡阶段
我们需要将Map的临时结果拉取到Reduce节点
第一种方式:两两合并
第二种方式:相同的进一个reduce
第三种对第二种优化,排序
第四种对第三种优化:如果一个reduce处理两种key,而key分布一个首一个尾,解决不连续的问题,给个编号,这个编号怎么算呢,`回到分区,排序`
拉取原则:
相同的Key必须拉取到同一个Reduce节点
但是一个Reduce节点可以有多个Key
未排序前拉取数据的时候必须对Map产生的最终的合并文件做全序遍历
而且每一个reduce都要做一个全序遍历
如果map产生的大文件是有序的,每一个reduce只需要从文件中读取自己所需的即可
Reduce阶段
合并merge
因为reduce拉取的时候,会从多个map拉取数据
那么每个map都会产生一个小文件,这些小文件(文件与文件之间无序,文件内部有序)
为了方便计算(没必要读取N个小文件),需要合并文件
归并算法合并成2个相同的key都在一起
归并Reduce
将文件中的数据读取到内存中
一次性将相同的key全部读取到内存中
直接将相同的key得到结果–>最终结果
写出(reduce任务总流程)
1、reduce的个数,在mr执行之前就可以设置好,直接通过配置文件,命令,代码的方式进行修改。
2、reduce先将每一个map任务产生文件中拉取对应分区编号的键值对数据,每次从一个map任务结果文件中拉取一次,就会在reduce内部产生一个文件,拉取n次,就会产生n个文件。数据一旦被拉取到reduce中,分区编号的作用就结束了,会将分区编号去掉。
3、将所有拉取过来的小文件进行合并【归井排序】
4、相同的键会成为一个组,相同键的值会被封装在一个迭代器中作为一个键的值
5、每一个分组键值对,都会执行一遍reduce的代码逻辑,得到一个键值对结果,写入到一个文件中
6、一个reduce任务会产生一个结果文件,若有n个reduce任务,就会产生n个结果文件。
7、结果文件保存在HDFS中的一个目录,这个目录由mapreduce作业来进行创建,不需要手动创建
浙公网安备 33010602011771号