大数据面试题(十)

JAVA相关

Java 基础

看过哪些jdk 源码和常用的库

答:1) java.lang包 java.lang包 是Java中最常用的包,程序不需要注入,就可以使用该包中的类,利用包中的类可以设计最基本的Java程序。

2)java.awt包 java.awt包中的类提供了图形界面的创建方法,包括按钮、文本框、列表框、容器、字体、颜色和图形等元素的建立和设置。

3) javax.swing包 javax.swing包为Java编写的图形界面提供创建类,利用javax.swing包的类建立的界面元素可调整为各种操作系统的界面风格,支持各种操作平台的界面的开发。此外,swing包还提供了树形控件、标签页控件、表格控件的类。Java.swing包中的很多类都是从java.awt包的类继承而来,Java保留使用java.awt包是为了保持技术的兼容性,但应尽量地使用javax.swing包来开发程序界面。

4)java.io包 java.io包的类提供数据流方式的系统输入输出控制、文件和对象的读写串行化处理,比较常用的类包括:BufferInputStream、BufferOutputStream、BufferedReader、BufferedWriter、DataInputStream、DataOutputStream、FileInputStream和FileOutputStream等。

5)java.util包 java.util包提供时间日期、随机数以及列表、集合、哈希表和堆栈等创建复杂数据结构的类,比较常见的类有:Date、Timer、Random和LinkedList等。

 

用哪种Resultful风格

答:Restfule风格是一种软件架构风格,而不是标准,只是提供了一种设计原则和约束条件。主要适用于客户端和服务器端交互的软件。是基于http协议实现。目的是为了提高系统的可伸缩性,降低应用之间的耦合度,方便框架分布式处理程序。基于这个风格的软件可更加的简单、更有层次,更易于实现缓存的机制。

     在resultful风格中,用户请求的url使用同一个URL而用请求方式:get/post/delete/put等方式对请求的处理方法进行区分。这样可以在前后台分离的开发中让前端开发人员不会对请求的资源地址产生混淆,形成一个统一的接口。

     GET,对应select:是从服务器查询,可以在服务器通过请求的参数区分查询的方式。

    POST,对应Create:在服务器新建立一个资源,调用insert操作。

    PUT,对应update操作:在服务器更新资源,调用update操作。

    PATCH,对应update操作,在服务器更新资源,客户端提供改变的属性。(目前JDK7没有实现,tomcat7也不行。)

    DELETE,对应DELETE操作,从服务器删除资源,调用delete语句。

    Spring MVc 对resstful应用提供了以下支持。利用@RequestMapping 指定要处理请求的url模板和http请求的动作类型。利用@PathVariable将url请求模板中的变量映射到处理方法参数上。前台利用AJAX,在客户端发出put、delete动作的请求。

 

    一般的应用格式如下:

    @RequestMapping(value="/{id}",method=RequestMethod.GET)

    @RequestMapping(value="/{id}",method=RequestMethod.POST)

    @RequestMapping(value="/{id}",method=RequestMethod.DELETE)

    @RequestMapping(value="/{id}",method=RequestMethod.PUT)

 

多线程synchronized和lock的区别

答:首先来说synchronized 是Java的关键字,是Java的内置特性,在JVM层面实现了对临界资源的同步互斥访问,通过对对象的头文件来操作,从而达到加锁和释放锁的目的。

synchronized的缺点:

1)不能响应中断;

2)同一时刻不管是读还是写都只能有一个线程对共享资源操作,其他线程只能等待

3)锁的释放由虚拟机来完成,不用人工干预,不过此即使缺点也是优点,优点是不用担心会造成死锁,缺点是由可能获取到锁的线程阻塞之后其他线程会一直等待,性能不高。

而lock接口的提出就是为了完善synchronized的不完美的,首先lock是基于jdk层面实现的接口,和虚拟机层面不是一个概念;其次对于lock对象中的多个方法的调用,可以灵活控制对共享资源变量的操作,不管是读操作还是写操作;

那么lock和synchronized的区别对比如下:

1)synchronized 在成功完成功能或者抛出异常时,虚拟机会自动释放线程占有的锁;而Lock对象在发生异常时,如果没有主动调用unLock()方法去释放锁,则锁对象会一直持有,因此使用Lock时需要在finally块中释放锁;

2)lock接口锁可以通过多种方法来尝试获取锁包括立即返回是否成功的tryLock(),以及一直尝试获取的lock()方法和尝试等待指定时间长度获取的方法,比synchronized;相对灵活了许多。

3) 通过在读多,写少的高并发情况下,我们用ReentrantReadWriteLock分别获取读锁和写锁来提高系统的性能,因为读锁是共享锁,即可以同时有多个线程读取共享资源,而写锁则保证了对共享资源的修改只能是单线程的。

 

写哪些多线程的代码

答:例如生产者消费者模式,基于socket的通信小项目需要注意会被问到项目具体功能以及实现技术细节

 

5 Jvm 内存模型和垃圾回收机制

答:一 jvm内存模型:

1)程序计数器

多线程时,当线程数超过CPU数量或CPU内核数量,线程之间就要根据时间片轮询抢夺CPU时间资源。因此每个线程有要有一个独立的程序计数器,记录下一条要运行的指令。线程私有的内存区域。如果执行的是JAVA方法,计数器记录正在执行的java字节码地址,如果执行的是native方法,则计数器为空。

2)虚拟机栈

线程私有的,与线程在同一时间创建。管理JAVA方法执行的内存模型。每个方法执行时都会创建一个桢栈来存储方法的的变量表、操作数栈、动态链接方法、返回值、返回地址等信息。栈的大小决定了方法调用的可达深度(递归多少层次,或嵌套调用多少层其他方法,-Xss参数可以设置虚拟机栈大小)。栈的大小可以是固定的,或者是动态扩展的。如果请求的栈深度大于最大可用深度,则抛出stackOverflowError;如果栈是可动态扩展的,但没有内存空间支持扩展,则抛出OutofMemoryError。

3)本地方法区

和虚拟机栈功能相似,但管理的不是JAVA方法,是本地方法,本地方法是用C实现的。

4)JAVA堆

线程共享的,存放所有对象实例和数组。垃圾回收的主要区域。可以分为新生代和老年代(tenured)。

新生代用于存放刚创建的对象以及年轻的对象,如果对象一直没有被回收,生存得足够长,老年对象就会被移入老年代。

新生代又可进一步细分为eden、survivorSpace0(s0,from space)、survivorSpace1(s1,to space)。刚创建的对象都放入eden,s0和s1都至少经过一次GC并幸存。如果幸存对象经过一定时间仍存在,则进入老年代(tenured)。

4)方法区

线程共享的,用于存放被虚拟机加载的类的元数据信息:如常量、静态变量、即时编译器编译后的代码。也成为永久代。如果hotspot虚拟机确定一个类的定义信息不会被使用,也会将其回收。回收的基本条件至少有:所有该类的实例被回收,而且装载该类的ClassLoader被回收

二 垃圾回收算法

1)标记-清除算法(Mark-Sweep)

从根节点开始标记所有可达对象,其余没标记的即为垃圾对象,执行清除。但回收后的空间是不连续的。

2)复制算法(copying)

将内存分成两块,每次只使用其中一块,垃圾回收时,将标记的对象拷贝到另外一块中,然后完全清除原来使用的那块内存。复制后的空间是连续的。复制算法适用于新生代,因为垃圾对象多于存活对象,复制算法更高效。在新生代串行垃圾回收算法中,将eden中标记存活的对象拷贝未使用的s1中,s0中的年轻对象也进入s1,如果s1空间已满,则进入老年代;这样交替使用s0和s1。这种改进的复制算法,既保证了空间的连续性,有避免了大量的内存空间浪费。

3)标记-压缩算法(Mark-compact)

适合用于老年代的算法(存活对象多于垃圾对象)。

标记后不复制,而是将存活对象压缩到内存的一端,然后清理边界外的所有对象。

 

 

6 classloader的功能和工作模式

答:每个运行中的线程都有一个成员contextClassLoader,用来在运行时动态地载入其它类

系统默认的contextClassLoader是systemClassLoader,所以一般而言java程序在执行时可以使用JVM自带的类、$JAVA_HOME/jre/lib/ext/中的类和$CLASSPATH/中的类

可以使用Thread.currentThread().setContextClassLoader(...);更改当前线程的contextClassLoader,来改变其载入类的行为

ClassLoader被组织成树形,一般的工作原理是:

1) 线程需要用到某个类,于是contextClassLoader被请求来载入该类

2) contextClassLoader请求它的父ClassLoader来完成该载入请求

3) 如果父ClassLoader无法载入类,则contextClassLoader试图自己来载入

Java中一共有四个类加载器,之所以叫类加载器,是程序要用到某个类的时候,要用类加载器载入内存。

    这四个类加载器分别为:Bootstrap ClassLoader、Extension ClassLoader、AppClassLoader

和URLClassLoader

Bootstrap ClassLoader是在JVM开始运行的时候加载java的核心类,是用C++编写的,它用来加载核心类库

Extension ClassLoader是用来加载扩展类,即/lib/ext中的类。

AppClassLoader用来加载Classpath的类,是和我们关系最密切的类。

URLClassLoader用来加载网络上远程的类

Java 的加载方式分为隐式加载( implicit )和显示加载( explicit )

通过 Class 类的 forName (String s) 方法把自定义类 TestClass 加载进来,并通过 newInstance ()方法把实例初始化。事实上 Class 类还很多的功能,这里就不细讲了,有兴趣的可以参考 JDK 文档。

Class 的 forName() 方法还有另外一种形式: Class forName(String s, boolean flag, ClassLoader classloader) , s 表示需要加载类的名称, flag 表示在调用该函数加载类的时候是否初始化静态区, classloader 表示加载该类所需的加载器。

forName (String s) 是默认通过 ClassLoader.getCallerClassLoader() 调用类加载器的,但是该方法是私有方法,我们无法调用,如果我们想使用 Class forName(String s, boolean flag, ClassLoader classloader) 来加载类的话,就必须要指定类加载器

 

7 Hashmap 原理

HashMap内部实现是一个桶数组,每个桶中存放着一个单链表的头结点。其中每个结点存储的是一个键值对整体(Entry),HashMap采用拉链法解决哈希冲突

1、HashMap首先初始化一个默认长度的数组

2、调用put保存数据时使用hashCode算法散列到数组的某个位置去存储(为避免散列的位置重复太多,还应该检查这个数组是否应该扩容)

3、如果散列到的位置已经有数据了,会形成一个链表结构,新的数据会放前面(get区的时候就取得最新的一条),旧的数据就压在下面

 

8 Hashmap的扩容机制,currenthashmap原理

答:在使用HashMap的过程中,我们经常会遇到这样一个带参数的构造方法。

public HashMap(int initialCapacity, float loadFactor) ;

第一个参数:初始容量,指明初始的桶的个数;相当于桶数组的大小。

第二个参数:装载因子,是一个0-1之间的系数,根据它来确定需要扩容的阈值,默认值是0.75。

当map中包含的Entry的数量大于等于threshold = loadFactor * capacity的时候,且新建的Entry刚好落在一个非空的桶上,此刻触发扩容机制,将其容量扩大为2倍。(为什么2倍,而不是1.5倍,3倍,10倍;解释见最后的补充)

当size大于等于threshold的时候,并不一定会触发扩容机制,但是会很可能就触发扩容机制,只要有一个新建的Entry出现哈希冲突,则立刻resize。

jdk1.5的3种并发集合类型(concurrent,copyonwrite,queue)中的ConcurrentHashMap

分析Hashtable就知道,synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。ConcurrentHashMap内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

 

 

9 A和B对象互相引用,是否垃圾回收

答:给对象共添加一个引用计数器,每当有引用对他进行引用时,计数器的值就加1,当引用失效,也就是不在执行此对象是,他的计数器的值就减1,若某一个对象的计数器的值为0,那么表示这个对象没有人对他进行引用,也就是意味着是一个失效的垃圾对象,就会被gc进行回收。

假设有A和B两个对象之间互相引用,也就是说A对象中的一个属性是B,B中的一个属性时A,这种情况下由于他们的相互引用,从而是垃圾回收机制无法识别。 

 

10 String对象内存地址

答:string不是基本数据类型,那么一个string的内存位置是什么呢?一共有两种情况:

  1、string直接赋值:

    String s = "haha";

    s的引用存在栈内存中,引用指向的haha存在方法区的常量池中(先判断常量池中是否有一个haha,存在则直接指向)

  2、string对象new创建

    String s = new String("haha");

    s的引用存在于栈内存中,引用指向的haha对象,存在堆内存中(每new一次,在堆中创建一个新的haha对象)

总结:

  1、string类型的引用,都是存在栈内存中的;

  2、string引用指向,直接赋值存在栈内存,new出来的存在栈内存。

 

1-1)List 与set 的区别?

List特点:容器保证存储顺序,元素可重复 ;Set特点:元素不能保证存储顺序,元素不可重复。

 

1-2)数据库的三大范式?

1NF:第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项(无重复的列)

2NF:第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分

                                               (属性完全依赖于主键  [消除部分子函数依赖])

3NF:第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。(创建外键表时只使用唯一或联合键关联主键表中的主键或唯一键,在外键表中不能包含主键表中其他列信息)(属性不依赖于其它非主属性  [消除传递依赖])

 

1-4)对象与引用对象的区别

JVM存储区在创建对象时new操作符完成对象的实例化,将该对象分配堆中;通过变量获取对象是实例化的地址,该变量为引用对象,并且该变量分配在栈存储区。

 

1-5)谈谈你对反射机制的理解及其用途?

反射机制对在JVM中对象的字节码进行运行时分析,反射机制能够分析字节码的完整体系(包类、属性、方法等);反射在项目中和java设计模式配合使用,增强代码表现力、减少代码,提高可维护能力;

 

1-6)列出至少五种设计模式(总结出常见设计模式名称和原理)

1       创建型模式

这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活    

工厂模式(Factory Pattern—简单工厂模式(静态工厂)、抽象工厂模式、工厂方法模式)

抽象工厂模式(Abstract Factory Pattern)

单例模式(Singleton Pattern):懒汉模式、饿汉模式

public class Lazy {

   private static Lazy run;

   //构造方法

   private Lazy() {}

  

   public static Lazy getRun() {

      if (run == null) {

         run = new Lazy();

      }

      return run;

   }

public class Hungry {

   private static Hungry run = new Hungry();

   //构造方法

   private Hungry() {}

  

   public static Hungry getRun() {

      return run;

   }

}

建造者模式(Builder Pattern)

原型模式(Prototype Pattern)

2       结构型模式

这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。        

适配器模式(Adapter Pattern)

桥接模式(Bridge Pattern)

过滤器模式(Filter、Criteria Pattern)

组合模式(Composite Pattern)

装饰器模式(Decorator Pattern)

外观模式(Facade Pattern)

享元模式(Flyweight Pattern)

代理模式(Proxy Pattern)

3       行为型模式

这些设计模式特别关注对象之间的通信。        

责任链模式(Chain of Responsibility Pattern)

命令模式(Command Pattern)

解释器模式(Interpreter Pattern)

迭代器模式(Iterator Pattern)

中介者模式(Mediator Pattern)

备忘录模式(Memento Pattern)

观察者模式(Observer Pattern)

状态模式(State Pattern)

空对象模式(Null Object Pattern)

策略模式(Strategy Pattern)

模板模式(Template Pattern)

访问者模式(Visitor Pattern)

1-7)RPC 原理?

RPC(Remote Procedure Call Protocol)——远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP/IP或UDP,为通信程序之间携带信息数据。RPC将原来的本地调用转变为调用远端的服务器上的方法,给系统的处理能力和吞吐量带来了近似于无限制提升的可能。在OSI网络通信模型中,RPC跨域了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

 

1-8)ArrayList、Vector、LinkedList 的区别及其优缺点?HashMap、HashTable 的区别及优缺点?

    ArrayList 和 Vector 是采用数组方式存储数据的,是根据索引来访问元素的,都可以

根据需要自动扩展内部数据长度,以便增加和插入元素,都允许直接序号索引元素,Vector的方法都是线程安全(使用 synchronized 同步)。

    LinkedList 使用双向链表实现存储,所以插入数度较快!

 

HashMap、HashTable 的区别及其优缺点:

     HashTable 中的方法是同步的 HashMap 的方法在缺省情况下是非同步的 因此在多线程环境下需要做额外的同步机制。

    HashTable 不允许有 null 值 key 和 value 都不允许,而 HashMap 允许有 null 值 key和 value 都允许。

     Hashtable 是 Dictionary 的子类,HashMap 是 Map 接口的一个实现类。

1-9)String,StringBuffer和StringBuilder的区别?

   String是字符串的常量,不能修改,StringBuffer和StringBuilder允许修改;StringBuffer中的方法是线程安全;StringBuilder的方法非线程安全;

StringBuilder、StringBuffer可以和String之间相互转换;

 

1-10)集合的扩充

ArrayList  list = new ArrayList(90000); list扩充多少次??

 public ArrayList() {

        this(10);

}

ArrayList默认的扩充是10

 

 

1-12)Java中Class.forName和ClassLoader.loadClass的区别

Class.forName("xx.xx")等同于Class.forName("xx.xx",true,CALLClass.class.getClassLoader()),第二个参数(bool)表示装载类的时候是否初始化该类,即调用类的静态块的语句及初始化静态成员变量。

 

ClassLoader loader = Thread.currentThread.getContextClassLoader(); //也可以用(ClassLoader.getSystemClassLoader())

 

Class cls = loader.loadClass("xx.xx"); //这句话没有执行初始化

 

forName可以控制是否初始化类,而loadClass加载时是没有初始化的。

 

1-15)请使用JAVA实现二分查找

一般的面试者都是些向看看你的思路,所以一般答题时只需要把思路写出来即可。

具体的实现如下:

二分查找就是折半查找,要想折半就必须把原来的数据进行排序,才能方便的查找:

实现代码如下:

 public static int binarySearch(int[] srcArray, int des){  

        int low = 0;  

        int high = srcArray.length-1;  

        while(low <= high) {  

            int middle = (low + high)/2;  

            if(des == srcArray[middle]) {  

                return middle;  

            }else if(des <srcArray[middle]) {   

                high = middle - 1;  

            }else {  

                low = middle + 1;  

            } 

        } 

        return -1; 

   }

 

 

1-16)java 中有两个线程怎样等待一个线程执行完毕

可以使用java线程合并操作,使用join完成两个线程对象的合并;

 

1-17)hashmap hashtable currentHashMap的使用区别

     HashMap和HashTable的区别同上。

     ConcurrentHashMap是使用了锁分段技术技术来保证线程安全的。所分段的技术是:把数据分成一段一段的储存,给每一段的数据添加一把锁,当线程访问一个数据时,其他的数据可以被访问。

 

1-18)JVM垃圾回收机制?

JVM的内存管理采用分代的策略。

1)年轻代(Young Gen):年轻代主要存放新创建的对象,内存大小相对会比较小,垃圾回收会比较频繁。(年轻代分成1个Eden Space和2个Suvivor Space(命名为A和B)。当对象在堆创建时,将进入年轻代的Eden Space。垃圾回收器进行垃圾回收时,扫描Eden Space和A Suvivor Space,如果对象仍然存活,则复制到B Suvivor Space,如果B Suvivor Space已经满,则复制到Old Gen。同时,在扫描Suvivor Space时,如果对象已经经过了几次的扫描仍然存活,JVM认为其为一个持久化对象,则将其移到Old Gen。扫描完毕后,JVM将Eden Space和A Suvivor Space清空,然后交换A和B的角色(即下次垃圾回收时会扫描Eden Space和BSuvivor Space。这么做主要是为了减少内存碎片的产生我们可以看到:Young Gen垃圾回收时,采用将存活对象复制到到空的Suvivor Space的方式来确保尽量不存在内存碎片,采用空间换时间的方式来加速内存中不再被持有的对象尽快能够得到回收。)。

2)年老代(Tenured Gen):年老代主要存放JVM认为生命周期比较长的对象(经过几次的Young Gen的垃圾回收后仍然存在),内存大小相对会比较大,垃圾回收也相对没有那么频繁(譬如可能几个小时一次)。年老代主要采用压缩的方式来避免内存碎片(将存活对象移动到内存片的一边,也就是内存整理)。当然,有些垃圾回收器(譬如CMS垃圾回收器)出于效率的原因,可能会不进行压缩。

3)持久代(Perm Gen):持久代主要存放类定义、字节码和常量等很少会变更的信息。

 

1-19) ACID数据库事务执行的四个基本要素

         A:原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,过程中发生错误,回滚(Rollback)至事务开始前的状态。

         B:一致性:主要特征是保护性和不变性,即使事务是多个并发,系统也必须如同串行事务一样操作。例如:转账,五个账户,每个账户余额100元,如果同时发生多个转账,保证五个账户总额还是500元。

C:隔离性:如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。在同一时间仅有一个请求用于同一数据

D:持久性:在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。(改完就是改了)

Linux 相关

2-1)关闭不必要的服务

A、使用ntsysv命令查看开启与关闭的服务

B、停止打印服务

[root@hadoop1 /]# /etc/init.d/cups stop

[root@hadoop1 /]# chkconfig cups off

2-2)关闭IP6

[root@hadoop1 /]# vim /etc/modprobe.conf

在下面添加一下配置:

alias net-pf-10 off

alias ipv6 off

2-3)调整文件的最大的打开数

查看当前的文件的数量:[root@hadoop1 /]#ulimit -a

修改配置:

[root@hadoop1 /]# vi /etc/security/limits.conf 在文件最后加上:

* soft nofile 65535

* hard nofile 65535

* soft nproc 65535

* hard nproc 65535

2-4)修改 linux 内核参数

[root@hadoop1 /]# vi /etc/sysctl.conf

在文本的最后追加一下内容:

net.core.somaxconn = 32768

 

表示物理内存使用到 90%(100-10=90)的时候才使用 swap 交换区

2-5)关闭 noatime

在最后追加一下内容

/dev/sda2 /data ext3 noatime,nodiratime 0 0

 

 

2-6)请用shell命令把某一个文件下的所有的文件分发到其他的机器上

Scp  -r  /user/local   hadoop2:/user/local

 

2-7)echo 1+1 && echo "1+1" 会输出什么

 

[root@hadoop1 ~]# echo 1+1 && echo "1+1"

1+1

1+1

 

[root@hadoop1 ~]# echo 1+1 && echo "1+1" && echo "1+" 1

1+1

1+1

1+ 1

 

2-8)在当前的额目录下找出包含祖母a并且文件的额大小大于55K的文件

[root@hadoop1 test]# find  .|  grep -ri "a"

a.text:a

 

后半句没有写出来,有时间在搞

 

 

2-9)linux用什么命令查看cpu,硬盘,内存的信息?

Top 命令

==============================================================================

Hadoop相关

3-1)简单概述hdfs原理,以及各个模块的职责

1、Namenode

Namenode是整个文件系统的管理节点。它维护着整个文件系统的文件目录树,文件/目录的元信息和每个文件对应的数据块列表, 接收用户的操作请求。

文件包括:

①fsimage:元数据镜像文件。存储某一时段NameNode内存元数据信息。

②edits:操作日志文件。

③fstime:保存最近一次checkpoint的时间

以上这些文件是保存在linux的文件系统中。通过hdfs-site.xml的dfs.namenode.name.dir属性进行设置。

 

查看NameNode的fsimage与edits内容

这个两个文件中的内容使用普通文本编辑器是无法直接查看的,是hadoop使用oev(查看日志)和oiv(查看镜像),可以使用hdfs调用执行。

 

 2、Datanode

提供真实文件数据的存储服务。

文件块( block): 最基本的存储单位。

对于文件内容而言,一个文件的长度大小是size,那么从文件的0偏移开始,按照固定的大小,顺序对文件进行划分并编号,划分好的每一个块称一个Block。 HDFS默认Block大小是128MB, 因此,一个256MB文件,共有256/128=2个Block.

与普通文件系统不同的是,在 HDFS中,如果一个文件小于一个数据块的大小,并不占用整个数据块存储空间。

Replication:多复本。默认是三个。通过hdfs-site.xml的dfs.replication属性进行设置。

3、Secondary namenode

 其重要作用是定期将编辑日志和元数据信息合并,防止编辑日志文件过大,并且能保证其信息与namenode信息保持一致。(SN一般在另一台单独的物理计算机上运行,因为它需要占用大量CPU时间来与namenode进行合并操作,一般情况是单独开一个线程来执行操作过程。)

 

3-2)  SecondaryNameNode执行合并的时机决定于(Checkpoint触发时机):

   1. 配置文件设置的时间间隔fs.checkpoint.period,默认为3600秒。

   2. 配置文件设置edits log大小fs.checkpoint.size,规定edits文件的最大值默认是64MB

3-3)  CheckPoint是什么?

   DFS会将整个名字空间保存在内存中。由inode数据及每个文件包含的所有blocks列表组成的名字系统元数据叫做image。保存在本机本地文件系统中的该image的一个持久化记录称为一个checkpoint

 

3-4) HDFS读文件操作过程?

1 使用HDFS提供的客户端Client, 向远程的Namenode发起读请求;

2 Namenode会视情况返回文件block列表, 对于每个block, Namenode都会返回有该block拷贝的DataNode地址;

3客户端会选取离客户端最近的DataNode来读取block; 如果客户端本身就是DataNode, 那么将从本地直接获取数据;

4读取完当前block的数据后, 关闭当前的DataNode链接, 并为读取下一个block寻找最佳的DataNode;

5 当读完列表block后, 且文件读取还没有结束, 客户端会继续向Namenode获取下一批的block列表;

6读取完一个block都会进行checksum验证, 如果读取datanode时出现错误, 客户端会通知Namenode, 然后再从下一个拥有该block拷贝的datanode继续读。

代码版

1.首先调用FileSystem对象的open方法,其实是一个DistributedFileSystem的实例。

2.DistributedFileSystem通过rpc获得文件的第一批block的locations,同一个block按照重复数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面。

3.前两步会返回一个FSDataInputStream对象,该对象会被封装DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream最会找出离客户端最近的datanode并连接。

4.数据从datanode源源不断的流向客户端。

5.如果第一块的数据读完了,就会关闭指向第一块的datanode连接,接着读取下一块。这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流。

6.如果第一批block都读完了, DFSInputStream就会去namenode拿下一批block的locations,然后继续读,如果所有的块都读完,这时就会关闭掉所有的流。

 

3-5) 当读取发生异常?

在读数据的时候, DFSInputStream和datanode的通讯发生异常,就会尝试正在读的block的排序第二近的datanode,并且会记录哪个datanode发生错误,剩余的blocks读的时候就会直接跳过该datanode。 DFSInputStream也会检查block数据校验和,如果发现一个坏的block,就会先报告到namenode节点,然后DFSInputStream在其他的datanode上读该block的镜像。

 

3-6) 写文件操作?

1使用HDFS提供的客户端向远程的Namenode发起写请求

2 Namenode会检查要创建的文件是否已经存在, 创建者是否有权限进行操作, 成功则会为文件创建一个记录, 否则会让客户端抛出异常;

3当客户端开始写入文件的时候, 客户端会将文件切分成多个packets, 并在内部以数据队列“data queue( 数据队列) ”的形式管理这些packets, 并向Namenode申请blocks, 获取用来存储replicas的合适的datanode列表, 列表的大小根据Namenode中replication的设定而定;

4 客户端完成数据的写入后, 会对数据流调用close()方法, 关闭数据流;

 

 

只要写入了dfs.replication.min的复本数( 默认为1),写操作就会成功, 并且这个块可以在集群中异步复制, 直到达到其目标复本数(replication的默认值为3),因为namenode已经知道文件由哪些块组成, 所以它在返回成功前只需要等待数据块进行最小量的复制。

 

1.客户端通过调用DistributedFileSystem的create方法创建新文件。

2.DistributedFileSystem通过RPC调用namenode去创建一个没有blocks关联的新文件,创建前, namenode会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过, namenode就会记录下新文件,否则就会抛出IO异常。

3.前两步结束后,会返回FSDataOutputStream的对象,与读文件的时候相似, FSDataOutputStream被封装成DFSOutputStream。DFSOutputStream可以协调namenode和datanode。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小的packet,然后排成队列data quene。

4.DataStreamer会去处理接受data quene,它先询问namenode这个新的block最适合存储的在哪几个datanode里(比如重复数是3,那么就找到3个最适合的datanode),把他们排成一个pipeline。DataStreamer把packet按队列输出到管道的第一个datanode中,第一个datanode又把packet输出到第二个datanode中,以此类推。

5.DFSOutputStream还有一个对列叫ack quene,也是由packet组成,等待datanode的收到响应,当pipeline中的所有datanode都表示已经收到的时候,这时akc quene才会把对应的packet包移除掉。

6.客户端完成写数据后调用close方法关闭写入流。

7.DataStreamer把剩余得包都刷到pipeline里,然后等待ack信息,收到最后一个ack后,通知datanode把文件标视为已完成

 

3-7)写的过程中某个datanode发生错误,会采取以下几步?

1) pipeline被关闭掉;

2)为了防止防止丢包ack quene里的packet会同步到data quene里;

3)把产生错误的datanode上当前在写但未完成的block删掉;

4)block剩下的部分被写到剩下的两个正常的datanode中;

5)namenode找到另外的datanode去创建这个块的复制。当然,这些操作对客户端来说是无感知的。

3-7) 谈谈数据倾斜,如何发生的,并给出优化方案

     数据的倾斜主要是两个的数据相差的数量不在一个级别上,在只想任务时就造成了数据的倾斜,可以通过分区的方法减少reduce数据倾斜性能的方法,例如;抽样和范围的分区、自定义分区、数据大小倾斜的自定义侧咯

 

3-8)简单概括安装hadoop的步骤

1.创建 hadoop 帐户。

2.setup.改 IP。

3.安装 java,并修改/etc/profile 文件,配置 java 的环境变量。

4.修改 Host 文件域名。

5.安装 SSH,配置无密钥通信。

6.解压 hadoop。

7.配置 conf 文件下 hadoop-env.sh、core-site.sh、mapre-site.sh、hdfs-site.sh。

8.配置 hadoop 的环境变量。

9.Hadoop namenode -format

10.Start-all.sh

 

3-9)简单概述hadoop中的角色的分配以及功能

Namenode:负责管理元数据的信息

SecondName:做namenode冷备份,对于namenode的机器当掉后能快速切换到制定的Secondname上

DateNode:主要做储存数据的。

JobTracker:管理任务,并把任务分配到taskTasker

TaskTracker:执行任务的

 

3-10)怎样快速的杀死一个job

1、执行hadoop  job -list  拿到job-id

2、Hadoop job kill hadoop-id

 

3-11)新增一个节点时怎样快速的启动

Hadoop-daemon.sh start datanode

 

3-12)你认为用java , streaming , pipe 方式开发map/reduce,各有什么优点

开发mapReduce只用过java与hive,不过使用java开发mapreduce显得笨拙,效率也慢,基于java慢的原因于是hive,这样就方便了查询与设计

 

3-13)简单概述hadoop的join的方法

Hadoop 常用的jion有reduce side join  , map side  join ,  SemiJoin 不过reduce side join 与 map side join 比较常用,不过都是比较耗时的。

 

3-14)简单概述hadoop的combinet与partition的区别

combine和partition都是函数,中间的步骤应该只有shuffle! combine分为map端和reduce端,作用是把同一个key的键值对合并在一起,可以自定义的,partition是分割map每个节点的结果,按照key分别映射给不同的reduce,也是可以自定义的。这里其实可以理解归类。

3-15 ) hdfs 的数据压缩算法

 Hadoop 的压缩算法有很多,其中比较常用的就是gzip算法与bzip2算法,都可以可通过CompressionCodec来实现

3-8) 安装hadoop完全分布式步骤?

1使用root账户登录

2 修改IP

3 修改host主机名

4 配置SSH免密码登录

5 关闭防火墙

6  安装JDK

7 解压hadoop安装包

8 配置hadoop的核心文件(/home/hadoop/hadoop-2.9.0/etc/hadoop)

 hadoop-env.sh:添加jdk环境

core-site.xml :指定NameNode,运行时产生文件的储存路径

hdfs-site.xml:守护进程配置:NameNode、DataNode、备份节点数、备用NameNode

mapred-site.xml :yuarn运行mapreduce

yarn-site.xml:资源管理器的主机名(master),mapreduce_shuffle

 /home/hadoop/hadoop-2.9.0/etc/hadoop/slaves:添加DataNode节点计算机名称

9 配置hadoop环境变量

10 格式化 hadoop namenode-format

11 启动节点 start-all.sh

1. spark为什么比hadoop快

答:Spark和Hadoop的根本差异是多个任务之间的数据通信问题:Spark多个任务之间数据通信是基于内存,而Hadoop是基于磁盘。
所说的是spark的数据缓存技术,如将RDD数据缓存至内存,但并没有实现持久化。缓存数据是可以擦除的,擦除后同样是需要我们重新计算的。Spark的数据处理是在内存中进行的,这话并没有错,其实当前的所有操作系统的数据处理都是在内存中进行的。所以,这内存计算并不是Spark的特性。Spark是内存缓存,所以数据只加载一次,Hadoop则需要反复加载。实际情况下,Spark通常比Hadoop快十倍以内是合理的。
区别:Spark比MapReduce运行速度快的原因主要有以下几点:
    task启动时间比较快,Spark是fork出线程;而MR是启动一个新的进程;
更快的shuffles,Spark只有在shuffle的时候才会将数据放在磁盘,而MR却不是。
更快的工作流:典型的MR工作流是由很多MR作业组成的,他们之间的数据交互需要把数据持久化到磁盘才可以;而Spark支持DAG以及pipelining,在没有遇到shuffle完全可以不把数据缓存到磁盘。
   缓存:虽然目前HDFS也支持缓存,但是一般来说,Spark的缓存功能更加高效,特别是在SparkSQL中,我们可以将数据以列式的形式储存在内存中。

2. spark只能在内存中计算吗

答:对Spark最大的误解就是spark一种内存技术。其实没有一个Spark开发者正式说明这个,这是对Spark计算过程的误解。
什么样是内存技术?就是允许你将数据持久化在RAM中并有效处理的技术。然而Spark并不具备将数据数据存储在RAM的选项,虽然我们都知道可以将数据存储在HDFS, HBase等系统中,但是不管是将数据存储在磁盘还是内存,都没有内置的持久化代码。它所能做的事就是缓存数据,而这个并不是数据持久化。已经缓存的数据可以很容易地被删除,并且在后期需要时重新计算。
 其实这道题问的是Spark基本工作原理:
1. Client客户端:我们在本地编写了spark程序,打成jar包,或python脚本,通过spark submit命令提交到Spark集群; 
  2. 只有Spark程序在Spark集群上运行才能拿到Spark资源,来读取数据源的数据进入到内存里; 
3. 客户端就在Spark分布式内存中并行迭代地处理数据,注意每个处理过程都是在内存中并行迭代完成;注意:每一批节点上的每一批数据,实际上就是一个RDD!!!一个RDD是分布式的,所以数据都散落在一批节点上了,每个节点都存储了RDD的部分partition。 
4. Spark与MapReduce最大的不同在于,迭代式计算模型:MapReduce,分为两个阶段,map和reduce,两个阶段完了,就结束了,所以我们在一个job里能做的处理很有限; Spark,计算模型,可以分为n个阶段,因为它是内存迭代式的。我们在处理完一个阶段以后,可以继续往下处理很多个阶段,而不只是两个阶段。所以,Spark相较于MapReduce来说,计算模型可以提供更强大的功能。
 Spark并不是基于内存的技术!它其实是一种可以有效地使用内存LRU策略的技术。

3. spark的RDD算子分两种,有什么区别

答:RDD支持两种类型的操作算子:Transformation(转换)与Action(行动)。
 1、Transformation(变换)操作会由一个RDD生成一个新的 RDD。Transformation操作是延迟计算的,也就是说从一个RDD转换生成另一个RDD的转换操作不是马上执行,需要等到Actions操作时,才真正开始运算。在transformations算子中再将数据类型细分为value数据类型和key-value对数据类型的transformations算子。
    1)Value型数据的算子封装在RDD类中可以直接使用。
    2)Key-value对数据类型的算子封装于PairRDDFunctions类中,用户需要引入import org.apache.spark.SparkContext._才能够使用。
 2、Action(行动)操作会对 RDD 计算出一个结果,并把结果返回到驱动器程序中,或把结果存储到外部存储系统(如 HDFS)中。
    transformations操作和Action操作的区别在于Spark计算RDD 的方式不同。对于在任何时候得到的新的RDD,Spark只会惰性计算。只有在一个行动操作中用到时,才会真正计算。这种策略也是spark性能高的部分原因。如果一个程序里有多个action算子,顺序完成action操作,每个action算子产生一个job,上一job的结果转换成RDD,继续给后续的action使用。多数action返回结果都不是RDD,而transformation算子的返回结果都是RDD,但可能是多个RDD(如:randomSplit,将一个RDD切分成多个RDD)。

4. RDD不复用多次创建会有什么问题

答:开发一个Spark作业时,首先是基于某个数据源(比如Hive表或HDFS文件)创建一个初始的RDD;接着对这个RDD执行某个算子操作,然后得到下一个RDD;以此类推,循环往复,直到计算出最终我们需要的结果。在这个过程中,多个RDD会通过不同的算子操作(比如map、reduce等)串起来,这个“RDD串”,就是RDD lineage,也就是“RDD的血缘关系链”。
   对于同一份数据,只应该创建一个RDD,不能创建多个RDD来代表同一份数据。
   在开发RDD lineage极其冗长的Spark作业时,可能会忘了自己之前对于某一份数据已经创建过一个RDD了,从而导致对于同一份数据,创建了多个RDD。这就意味着,我们的Spark作业会进行多次重复计算来创建多个代表相同数据的RDD,进而增加了作业的性能开销。
   Spark中对于一个RDD执行多次算子的默认原理是这样的:每次你对一个RDD执行一个算子操作时,都会重新从源头处计算一遍,计算出那个RDD来,然后再对这个RDD执行你的算子操作。这种方式的性能是很差的。
    建议是:对多次使用的RDD进行持久化。此时Spark就会根据你的持久化策略,将RDD中的数据保存到内存或者磁盘中。以后每次对这个RDD进行算子操作时,都会直接从内存或磁盘中提取持久化的RDD数据,然后执行算子,而不会从源头处重新计算一遍这个RDD,再执行算子操作。

5. RDD存在内存里吗

  答: 弹性分布式数据集,即内存中的数据库.RDD 只读、可分区,这个数据集的全部或部分可以缓存在内存中,在多次计算间重用.所谓弹性,是指内存不够时可以与磁盘进行交换.这涉及到了RDD的另一特性:内存计算,就是将数据保存到内存中.同时,为解决内存容量限制问题,Spark为我们提供了最大的自由度,所有数据均可由我们来进行cache的设置,包括是否cache和如何cache.
   Spark的持久化级别(持久化级别      含义解释)
        MEMORY_ONLY:使用未序列化的Java对象格式,将数据保存在内存中。如果内存不够存放所有的数据,则数据可能就不会进行持久化。那么下次对这个RDD执行算子操作时,那些没有被持久化的数据,需要从源头处重新计算一遍。这是默认的持久化策略,使用cache()方法时,实际就是使用的这种持久化策略。
        MEMORY_AND_DISK:使用未序列化的Java对象格式,优先尝试将数据保存在内存中。如果内存不够存放所有的数据,会将数据写入磁盘文件中,下次对这个RDD执行算子时,持久化在磁盘文件中的数据会被读取出来使用。
        MEMORY_ONLY_SER:基本含义同MEMORY_ONLY。唯一的区别是,会将RDD中的数据进行序列化,RDD的每个partition会被序列化成一个字节数组。这种方式更加节省内存,从而可以避免持久化的数据占用过多内存导致频繁GC。
        MEMORY_AND_DISK_SER:基本含义同MEMORY_AND_DISK。唯一的区别是,会将RDD中的数据进行序列化,RDD的每个partition会被序列化成一个字节数组。这种方式更加节省内存,从而可以避免持久化的数据占用过多内存导致频繁GC。
        DISK_ONLY:使用未序列化的Java对象格式,将数据全部写入磁盘文件中。
        MEMORY_ONLY_2, MEMORY_AND_DISK_2, 等等
        对于上述任意一种持久化策略,如果加上后缀_2,代表的是将每个持久化的数据,都复制一份副本,并将副本保存到其他节点上。这种基于副本的持久化机制主要用于进行容错。假如某个节点挂掉,节点的内存或磁盘中的持久化数据丢失了,那么后续对RDD计算时还可以使用该数据在其他节点上的副本。如果没有副本的话,就只能将这些数据从源头处重新计算一遍了。

 

6. 同样做单词统计,说一下在mapreduce和spark里分别怎么做

答:一 mapreduce单词统计
   Mapper 任务的运行过程分为六个阶段。
        第一阶段是把输入文件按照一定的标准分片(InputSplit),每个输入片的大小是固定的。默认情况下,输入片(InputSplit)的大小与数据块(Block)的大小是相同的。每一个输入片由一个 Mapper 进程处理。这里的三个输入片,会有三个 Mapper 进程处理。
        第二阶段是对输入片中的记录按照一定的规则解析成键值对。 有个默认规则是把每一行文本内容解析成键值对。 “键”是每一行的起始位置(单位是字节), “值”是本行的文本内容。
        第三阶段是调用 Mapper 类中的 map 方法。 第二阶段中解析出来的每一个键值对, 调用一次 map 方法。如果有 1000 个键值对,就会调用 1000 次 map 方法。每一次调用 map 方法会输出零个或者多个键值对。
        第四阶段是按照一定的规则对第三阶段输出的键值对进行分区。比较是基于键进行的。比如我们的键表示省份(如北京、上海、山东等),那么就可以按照不同省份进行分区,同一个省份的键值对划分到一个区中。默认是只有一个。分区的数量就是 Reducer 任务运行的数量。默认只有一个 Reducer 任务。
        第五阶段是对每个分区中的键值对进行排序。首先,按照键进行排序,对于键相同的键值对,按照值进行排序。比如三个键值对<2,2>、<1,3>、<2,1>,键和值分别是整数。那么排序后的结果是<1,3>、<2,1>、<2,2>。如果有第六阶段,那么进入第六阶段;如果没有,直接输出到本地的 linux 文件中。
        第六阶段是对数据进行归约处理,也就是 reduce 处理。键相等的键值对会调用一次reduce 方法。经过这一阶段,数据量会减少。归约后的数据输出到本地的 linux 文件中。
    Reducer任务的执行过程
        第一阶段是 Reducer 任务会主动从 Mapper 任务复制其输出的键值对。 Mapper 任务可能会有很多,因此 Reducer 会复制多个 Mapper 的输出。
        第二阶段是把复制到 Reducer 本地数据,全部进行合并,即把分散的数据合并成一个大的数据。再对合并后的数据排序。
        第三阶段是对排序后的键值对调用 reduce 方法。 键相等的键值对调用一次 reduce 方法,每次调用会产生零个或者多个键值对。最后把这些输出的键值对写入到 HDFS 文件中。
二 Spark作业执行流程描述:
        客户端提交作业给Master
        Master让一个Worker启动Driver,即SchedulerBackend。Worker创建一个DriverRunner线程,DriverRunner启动SchedulerBackend进程。
        另外Master还会让其余Worker启动Executor,即ExecutorBackend。Worker创建一个ExecutorRunner线程,ExecutorRunner会启动ExecutorBackend进程。
        ExecutorBackend启动后会向Driver的SchedulerBackend注册。SchedulerBackend进程中包含DAGScheduler,它会根据用户程序,生成执行计划,并调度执行。对于每个stage的task,都会被存放到TaskScheduler中,ExecutorBackend向SchedulerBackend汇报的时候把TaskScheduler中的task调度到ExecutorBackend执行。
        所有stage都完成后作业结束。

7. MapReduce数据倾斜怎么解决

    答:1.增加jvm内存,这适用于第一种情况(唯一值非常少,极少数值有非常多的记录值(唯一值少于几千)),这种情况下,往往只能通过硬件的手段来进行调优,增加jvm内存可以显著的提高运行效率。
        2.增加reduce的个数,这适用于第二种情况(唯一值比较多,这个字段的某些值有远远多于其他值的记录数,但是它的占比也小于百分之一或千分之一),我们知道,这种情况下,最容易造成的结果就是大量相同key被partition到一个分区,从而一个reduce执行了大量的工作,而如果我们增加了reduce的个数,这种情况相对来说会减轻很多,毕竟计算的节点多了,就算工作量还是不均匀的,那也要小很多。
        3.自定义分区,这需要用户自己继承partition类,指定分区策略,这种方式效果比较显著。
        4.重新设计key,有一种方案是在map阶段时给key加上一个随机数,有了随机数的key就不会被大量的分配到同一节点(小几率),待到reduce后再把随机数去掉即可。
        5.使用combinner合并,combinner是在map阶段,reduce之前的一个中间阶段,在这个阶段可以选择性的把大量的相同key数据先进行一个合并,可以看做是local reduce,然后再交给reduce来处理,这样做的好处很多,即减轻了map端向reduce端发送的数据量(减轻了网络带宽),也减轻了map端和reduce端中间的shuffle阶段的数据拉取数量(本地化磁盘IO速率),推荐使用这种方法。

8. spark的sql和streaming都学了吗,有什么功能

答:Spark SQL提供三种主要功能以使用结构化及半结构化数据:
    1. 在Python、Java与Scala中提供DataFrame抽象以简化结构化数据集的处理方式。DataFrame类似于关系数据库中的表。
    2. 它能够对多种结构化格式进行数据读取及写入(例如JSON、Hive Tables以及Parquet)。
    3. 允许大家利用SQL进行数据查询,适用范围包括Spark程序之内以及通过标准数据库连接器(JDBC/ODBC)接入Spark SQL的外部工具,
    Spark Streaming 是Spark核心API的一个扩展,可以实现高吞吐量的、具备容错机制的实时流数据的处理。支持从多种数据源获取数据,包括Kafk、Flume、Twitter、ZeroMQ、Kinesis 以及TCP sockets,从数据源获取数据之后,可以使用诸如map、reduce、join和window等高级函数进行复杂算法的处理。最后还可以将处理结果存储到文件系统,数据库和现场仪表盘。

9. zookeeper用了么,有什么功能

答:ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,它是集群的管理者,监视着集群中各个节点的状态根据节点提交的反馈进行下一步合理操作。最终,将简单易用的接口和性能高效、功能稳定的系统提供给用户
 ZooKeeper提供:
    1.命名服务   2.配置管理   3.集群管理   4.分布式锁  5.队列管理 6.Zookeeper命名服务

10. zookeeper集群配了几个,随意吗,多少有什么影响

答:Zookeeper的大部分操作都是通过选举产生的。比如,标记一个写是否成功是要在超过一半节点发送写请求成功时才认为有效。同样,Zookeeper选择领导者节点也是在超过一半节点同意时才有效。最后,Zookeeper是否正常是要根据是否超过一半的节点正常才算正常。
    zookeeper有这样一个特性:集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的。

11. 每个节点都配一个zookeeper吗?

    每个节点可以配置多个zk,

12. 领导选举出的leader是干什么的

答:一个zookeeper 集群 只有一个leader: 类似master/slave模式。客户端提交请求之后,先发送到leader,leader作为接收者,广播到每个server。在folloer上创建:也会同步到leader  ,一个节点上的数据发生变化后,通知其他节点。

13.hive如何数据清洗

答:hive流程 :创建源表 → 加载日志数据到源表中→过滤字段(在hive数据清洗这里总结三种常用的去重方式distinct、group by、row_number) →字段格式化
    数据清洗的任务是过滤那些不符合要求的数据,将过滤的结果交给业务主管部门,确认是否过滤掉还是由业务单位修正之后再进行抽取。不符合要求的数据主要有不完整的数据、错误的数据和重复的数据三大类。

14.hive如何去重

答:在hive数据清洗这里总结三种常用的去重方式distinct、group by、row_number

15.spark和MapReduce区别。

答:1、spark把运算的中间数据存放在内存,迭代计算效率更高;mapreduce的中间结果需要落地,需要保存到磁盘,这样必然会有磁盘io操做,影响性能。
2、spark容错性高,它通过弹性分布式数据集RDD来实现高效容错,RDD是一组分布式的存储在节点内存中的只读性质的数据集,这些集合是弹性的,某一部分丢失或者出错,可以通过整个数据集的计算流程的血缘关系来实现重建;mapreduce的话容错可能只能重新计算了,成本较高。
3、spark更加通用,spark提供了transformation和action这两大类的多个功能api,另外还有流式处理sparkstreaming模块、图计算GraphX等等;mapreduce只提供了map和reduce两种操作,流计算以及其他模块的支持比较缺乏。
4、spark框架和生态更为复杂,首先有RDD、血缘lineage、执行时的有向无环图DAG、stage划分等等,很多时候spark作业都需要根据不同业务场景的需要进行调优已达到性能要求;mapreduce框架及其生态相对较为简单,对性能的要求也相对较弱,但是运行较为稳定,适合长期后台运行。

16.hive多表怎么连接,几种情况。

答:内连接,hive只支持等值连接,这意味着连接的谓语条件只能使用等号。
外连接,分为左外连接、右外连接、全外连接
 半连接,其实和内连接的效果一样,只不过使用IN查询

17.hive常用函数有什么

答:数学函数round,ceil,、集合函数map_keys,size、类型转换函数cast、日期函数todate,year、条件函数if,isnull、字符函数encode,ltrim、聚合函数count,sum、表生成函数explode,stack

18.hive遇到数据倾斜怎么办

答:一 倾斜的原因:使map的输出数据更均匀的分布到reduce中去,是我们的最终目标。由于Hash算法的局限性,按key Hash会或多或少的造成数据倾斜。大量经验表明数据倾斜的原因是人为的建表疏忽或业务逻辑可以规避的。
二 解决思路:
Hive的执行是分阶段的,map处理数据量的差异取决于上一个stage的reduce输出,所以如何将数据均匀的分配到各个reduce中,就是解决数据倾斜的根本所在
三 具体办法:内存优化和I/O优化:
    驱动表:使用大表做驱动表,以防止内存溢出;Join最右边的表是驱动表;Mapjoin无视join顺序,用大表做驱动表;StreamTable。
    1. Mapjoin是一种避免避免数据倾斜的手段
    允许在map阶段进行join操作,MapJoin把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map是进行了join操作,省去了reduce运行的效率也会高很多
    在对多个表join连接操作时,将小表放在join的左边,大表放在Jion的右边,
    在执行这样的join连接时小表中的数据会被缓存到内存当中,这样可以有效减少发生内存溢出错误的几率
    2. 设置参数
    hive.map.aggr = true
    hive.groupby.skewindata=true 还有其他参数
    3.SQL语言调节
    比如: group by维度过小时:采用sum() group by的方式来替换count(distinct)完成计算
    4.StreamTable
    将在reducer中进行join操作时的小table放入内存,而大table通过stream方式读取
    5.索引
    Hive从0.80开始才有,提供了一个Bitmap位图索引,索引可以加快GROUP BY查询语句的执行速度,用的较少。
1 hive遇到数据倾斜怎么办

答:在hive中产生数据倾斜的原因和解决方法:

  1)group by 会产生倾斜;当按照类型进行group by的时候,会将相同的group by字段的reduce任务需要的数据拉取到同一个节点进行聚合,而当其中每一组的数据量过大时,会出现其他组的计算已经完成而这里还没计算完成,其他节点的一直等待这个节点的任务执行完成,所以会看到一直map 100%  reduce 99%的情况。

  解决方法:set hive.map.aggr=true

       set hive.groupby.skewindata=true

  原理:hive.map.aggr=true 这个配置项代表是否在map端进行聚合

map和reduce优化。

    1.当出现小文件过多,需要合并小文件。可以通过set hive.merge.mapfiles=true来解决。

       2.单个文件大小稍稍大于配置的block块的大写,此时需要适当增加map的个数。解决方法:set mapred.map.tasks个数

       3.文件大小适中,但map端计算量非常大,如select id,count(*),sum(case when...),sum(case when...)...需要增加map个数。解决方法:set mapred.map.tasks个数,set mapred.reduce.tasks个数

当HiveQL中包含count(distinct)时

         如果数据量非常大,执行如select a,count(distinct b) from t group by a;类型的SQL时,会出现数据倾斜的问题。

         解决方法:使用sum...group by代替。如select a,sum(1) from (select a, b from t group by a,b) group by a;

4)当遇到一个大表和一个小表进行join操作时。

    解决方法:使用mapjoin 将小表加载到内存中。

5)遇到需要进行join的但是关联字段有数据为空,如表一的id需要和表二的id进行关联

     解决方法1:id为空的不参与关联;

解决方法2:给空值分配随机的key值
 

20.hive是否支持模糊查询

答:hive支持模糊查询,ike与rlike的区别:like不是正则,而是通配符。这个通配符可以看一下SQL的标准,例如%代表任意多个字符。rlike是正则,正则的写法与java一样。'\'需要使用'\\',例如'\w'需要使用'\\w'。

21 linux基本命令说几个

答:linux基本命令分类:

1)系统信息:
uname -a      # 显示Linux系统信息 
uname -r      # 显示内核发布版本信息
uptime        # 显示系统已经运行的时间和系统负载
hostname      # 显示系统主机名
last reboot   # 显示系统重启历史
date          # 显示当前日期和时间
cal           # 显示本月日历 

2)用户管理

who,  useradd、userdel、groupadd

3)文件目录操作

mkdir、rm、touch、rmdir、cp

4)进程控制类:ps,kill

5)文件权限:chmod,chown

6)网络类:ifconfig,ping,wget, netstat

22 java基础,数据类型有哪些

答:java基础数据类型分为:基本类型和对象类型

基本类型有:byte,short,int,long,float,double,char,boolean

对象类型:数组,String,jdk提供的类,自定义类,枚举登录

23 vi用过么

答:切换模式: 命令模式,从键盘上输入的任何字符都被作为编辑命令来解释,vi 下很多操作如配置编辑器、文本查找和替换、选择文本等都是在命令模式下进行的。

输入模式,从键盘上输入的所有字符都被插入到正在编辑的缓冲区中,被当作正文。

末行模式,

24 是在linux环境还是window搭建的集群

答:当然linux建立集群

25 sqoop用过么

答:用过啊,我们曾经使用它向mysql导入过数据啊

原文地址:https://blog.csdn.net/cs_mycsdn/article/details/81235747

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值