zoukankan      html  css  js  c++  java
  • 【面试题】大数据开发第1轮面试

    面试总结:

    1、HDFS小文件

    小文件的产生原因
    1) 数据本身的特点:比如我们在 HDFS 上存储大量的图片、短视频、短音频等文件,这些文件本身较小,达不到一个block的大小,而且数量众多。
    2) MapReduce产生:例如使用查询一张含有海量数据的表,然后存储在另外一张表中,而这个查询只有简单的过滤条件(比如 select * from iteblog where from = 'hadoop'),这种情况只会启动大量的 Map 来处理,这种情况可能会产生大量的小文件。Reduece 设置不合理,也会产生大量小文件。
    3)实时流处理:比如我们使用 Spark Streaming 从外部数据源接收数据,然后经过 ETL 处理之后存储到 HDFS 中。这种情况下在每个 Job 中会产生大量的小文件。

    小文件的影响
    1)namenode 会记录存储文件的元数据信息,大量小文件会占用大量的namenode内存,从而影响到HDFS的横向扩展能力。
    2)使用mapreduce处理这些小文件,每个小文件会启动一个mapreduce,开启一个JVM,这样会占用集群的大量资源。

    小文件解决办法
    1)使用 HAR File:
    运行一个 MapReduce 任务将小文件打包成 HAR 文件,使用 HAR 文件对客户端没有任何影响,所有的原始文件都可见并且可访问的(通过 har://URL)。但在 HDFS 端它内部的文件数减少了。
    Hadoop 在进行最终文件的读取时,需要先访问索引数据,所以在效率上会比直接读取 HDFS 文件慢一些。
    2)Sequence Files
    Sequence Files 使用小文件名作为 key,并且文件内容作为 value,实践中这种方式非常管用。
    和 HAR 不同的是,这种方式还支持压缩。该方案对于小文件的存取都比较自由,不限制用户和文件的多少,但是 SequenceFile 文件不能追加写入,适用于一次性写入大量小文件的操作。
    3)HBase存储
    小文件存储到类似于 HBase 的 KV 数据库里面,也可以将 Key 设置为小文件的文件名,Value 设置为小文件的内容,相比使用 SequenceFile 存储小文件,使用 HBase 的时候我们可以对文件进行修改,甚至能拿到所有的历史修改版本。
    4)从 Hadoop 底层解决小文件问题 - HDFS-8998
    小文件占用了一个block,把小block合并成大block。

    5)从 Hadoop 底层解决小文件问题 - HDFS-8286
    把 NameNode 管理的元数据从保存在内存转向保存到第三方KV存储系统里,从而减缓 NameNode 的内存使用。

    参考资料:
    https://mp.weixin.qq.com/s/2KFZp4bHKw9iNyDPOTim1A
    https://issues.apache.org/jira/browse/HDFS-8998
    https://issues.apache.org/jira/browse/HDFS-8286

    2、kafka 如何实现高吞吐

    1)顺序读写
    kafka的消息是不断追加到文件中的,这个特性使kafka可以充分利用磁盘的顺序读写性能。
    顺序读写不需要硬盘磁头的寻道时间,只需很少的扇区旋转时间,所以速度远快于随机读写。
    顺序 I/O: 600MB/s
    随机 I/O: 100KB/s
    2)零拷贝
    零拷贝(zero-copy)"是一种系统调用机制,就是跳过“用户缓冲区”的拷贝,建立一个磁盘空间和内存的直接映射,数据不再复制到“用户态缓冲区”。
    系统上下文切换减少为2次,可以提升一倍的性能
    3)文件分段
    kafka的队列topic被分为了多个区partition,每个partition又分为多个段segment,所以一个队列中的消息实际上是保存在N多个片段文件中
    kafka的队列topic被分为了多个区partition,每个partition又分为多个段segment,所以一个队列中的消息实际上是保存在N多个片段文件中
    4)批量发送
    Kafka允许进行批量发送消息,先将消息缓存在内存中,然后一次请求批量发送出去
    比如可以指定缓存的消息达到某个量的时候就发出去,或者缓存了固定的时间后就发送出去
    如100条消息就发送,或者每5秒发送一次
    这种策略将大大减少服务端的I/O次数
    5)数据压缩
    Kafka还支持对消息集合进行压缩,Producer可以通过GZIP或Snappy格式对消息集合进行压缩
压缩的好处就是减少传输的数据量,减轻对网络传输的压力
Producer压缩之后,在Consumer需进行解压,虽然增加了CPU的工作,但在对大数据处理上,瓶颈在网络上而不是CPU,所以这个成本很值得。

    参考资料:
    https://mp.weixin.qq.com/s/vf4su_rl-UOGS8vHTCeDrg

    3. Spark Streaming 如何消费 Kafka 的数据

    两种方式:Receiver-based Approach、Direct Approach (No Receivers)
    1)Receiver-based Approach
    Receiver 的实现使用了 Kafka 的高级消费者 API,对于所有的 Receivers,接收到的数据将会保存在 Spark executors 中,然后由 SS 启动的 Job 来处理这些数据。

    2)Direct Approach (No Receivers)
    定期地从 Kafka 的 topic+partition 中查询最新的偏移量,再根据定义的偏移量范围在每个批处理时间间隔里面处理数据。当作业需要处理的数据来临时,Spark 通过调用 Kafka 的低级消费者 API 读取一定范围的数据。

    优缺点:
    Direct 比 Receiver 好的地方:简化并行、高效、恰好一次语义。
    Direct 缺点:需要手动维护读取 Kakfa 的偏移量到 ZooKeeper。

    参考资料:
    https://mp.weixin.qq.com/s/C-m1ATNL2udLqo51zSe2Ow

    4、Scala 隐式转换

    隐式转换:我们需要某个类中的一个方法,但是这个类没有提供这样的一个方法,所以我们需要隐式转换,转换成提供了这个方法的类,然后再调用这个方法。
    隐式转换实现的方式:
    1)通过伴生对象实现
    2)写一个专门的类用于转换,需要手动导入方式

    5、堆排序

    堆排序是利用堆的性质进行的一种选择排序。
    堆实际上是一棵完全二叉树,其满足性质:任何一结点大于等于或者小于等于其左右子树结点。
    堆分为大顶堆和小顶堆,满足 “任何一结点大于等于其左右子树结点” 的称为大顶堆,满足 “任何一结点小于等于其左右子树结点” 的称为小顶堆。
    大顶堆的堆顶肯定是最大的,小顶堆的堆顶是最小的。

    void HeapAdjust(int array[], int left, int right)
    {
        int index = left;
      
        for (int i = left * 2; i <= right; i = i * 2)
        {
            if (i < right && array[i] < array[i + 1])  // 找到孩子中较大者
                i++;
            if (array[index] > array[i])
                return;
            swap(array[index], array[i]);
            index = i;
        }
    }
    
    void HeapSort(int array[], int left, int right)
    {
        int len = right - left + 1;
      
        for (int i = len / 2; i >= left; i--)  // 把数组调整成大顶堆
            HeapAdjust(array, i, right);
      
        for (int i = right; i > left; i--)     // 排序
        {
            swap(array[left], array[i]);
            HeapAdjust(array, left, i - 1);
        }
    }
    

    堆排序时间复杂度:O(nlogn)
    参考资料:
    https://mp.weixin.qq.com/s/0H9jQDjG4oMv3nxEcJiCOw

    7、Linux 如何查看端口是否占用

    netstat -anp | grep 3306
    如果端口的连接状态是 listen,说明被占用了。

    tcp6       0      0 :::3306                 :::*                    LISTEN      5364/mysqld
    tcp6       0      0 192.168.56.10:3306      192.168.56.10:35180     ESTABLISHED 5364/mysqld
    tcp6       0      0 192.168.56.10:3306      192.168.56.10:35174     ESTABLISHED 5364/mysqld
    

    参考资料:
    https://www.cnblogs.com/shining5/p/8074080.html

    8、Impala 和 Spark SQL 的比较

    两者都可以很好地处理结构化数据,都是基于内存计算的。
    Imapla 是 MPP 分布式查询引擎,适用于即席查询。
    Spark SQL 常用于基于Spark RDD 的运算。

    个人经验:
    实际生产中使用 impala 场景比较多,impala 查询速度快,性能好。但是有一点需要注意,impala 的元数据缓存机制,在写入数据到hive后,不能立即用 impala 查询到数据,因为有缓存机制。需要清理缓存重新索引后,才能在 impala 上查到数据。

    invalidata metadata <tablename> ;
    或者
    refresh <tablename> ; 
    

    这两个方式也有区别,涉及到 schema 变动的,必须使用 invalidata metadata ;

    参考资料:
    https://mp.weixin.qq.com/s/w7p2oZ-Yt_QYr7kbIkzgrg
    https://blog.csdn.net/qq_35995514/article/details/102897599

    9、Redis 持久化策略

    RDB、AOF持久化策略。

    RDB(=Redis DataBase):把数据以快照的形式保存在磁盘上,这是默认的持久化策略,在配置文件里可以配置触发持久化操作的条件。

    AOF(Append Only File):将每一个收到的写命令都通过write函数追加到文件中。

    优缺点:
    1)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
    2)在数据丢失的情况下,AOF 丢失的数据比 RDB 少。
    3)RDB 文件比 AOF 小

    项目 RDB AOF
    启动优先级
    文件体积
    恢复速度
    数据安全性 丢数据 根据策略决定
    轻重

    参考资料:
    https://segmentfault.com/a/1190000016021217

    10、 Redis 集群

    Redis 集群的三种模式:
    主从模式复制、哨兵模式、Cluster 模式。
    1)主从复制模式
    以主库为准,从库内容异步复制主数据库,从而达成主从内容基本一致的情况。
    特点:
    1.master一般是接受读写的,slave只接受读操作。
    2.当master接受写操作后会将命令发送给slave执行,从而实现数据一致性
    3.一个master下面可以有多个slave,但是一个slave上面只能有一个master
    原理:
    1 从服务器连接主服务器发送sync命令。
    2 主服务器持久化数据生成rdb文件并缓存这段时间的写命令
    3 主服务器向从服务器发送rdb文件和缓存的命令
    4 从服务器载入rdb快照后执行缓存的命令(从服务器初始化完成)
    5 主服务器每接收到一个写命令就发送给从服务器执行(从服务器初始化完成后的操作)

    2)哨兵模式
    哨兵模式是建立在主从模式基础之上,从节点使用哨兵模式进行监控主节点,如果主挂了,从库自动升级为主节点,等待主库恢复了,主库会自动变为从库。
    此时,如果升级为主库的从节点挂了,此时变为从库的主节点不会变为主库,出现这种问题,我们一般采用的是主从都进行哨兵模式配置,互相监控对方,从而达到高可用。

    3)Cluster 模式
    cluster模式采用了无中心节点的方式来实现,每个主节点都会与其它主节点保持连接。节点间通过gossip协议交换彼此的信息,同时每个主节点又有一个或多个从节点。
    客户端连接集群时,直接与redis集群的每个主节点连接,根据hash算法取模将key存储在不同的哈希槽上;
    在集群中采用数据分片的方式,将redis集群分为16384个哈希槽。这些哈希槽分别存储于三个主节点中。
    每个节点会保存一份数据分布表,节点会将自己的slot信息发送给其他节点,节点间不停的传递数据分布表。
    客户端连接集群时,通过集群中某个节点地址进行连接。客户端尝试向这个节点执行命令时,比如获取某个key值,如果key所在的slot刚好在该节点上,则能够直接执行成功。如果slot不在该节点,则节点会返回MOVED错误,同时把该slot对应的节点告诉客户端,客户端可以去该节点执行命令。

    参考资料:
    https://mp.weixin.qq.com/s/S1n16saQwuv51rsNvCrlnQ
    https://mp.weixin.qq.com/s/oH2uzyVJTiU031WzuehDHA

    11.如果目前有一个实际的业务场景,如何数据建模?

    1)数仓分层:ODS层 -> DW层(DWD|DWS|DWB) -> ADS层
    好处:清晰数据结构、数据血缘追踪、数据血缘追踪、把复杂问题简单化、把复杂问题简单化。

    2)建模方法:维度建模 or 关系建模
    维度建模:
    维度建模以分析决策的需求出发构建模型,构建的数据模型为分析需求服务,因此它重点解决用户如何更快速完成分析需求,同时还有较好的大规模复杂查询的响应性能,更直接面向业务。
    星型模型:由一个事实表和一组维表组成。每个维表都有一个维作为主键,所有这些维的主键组合成事实表的主键。强调的是对维度进行预处理,将多个维度集合到一个事实表,形成一个宽表。
    优点:技术要求不高,快速上手,敏捷迭代,快速交付;更快速完成分析需求,较好的大规模复杂查询的响应性能
    缺点:维度表的冗余会较多,视野狭窄

    关系建模:
    是数据仓库之父Inmon推崇的、从全企业的高度设计一个3NF模型的方法,用实体加关系描述的数据模型描述企业业务架构,在范式理论上符合3NF,站在企业角度面向主题的抽象,而不是针对某个具体业务流程的实体对象关系抽象。
    雪花模型:一个或多个维表没有直接连接到事实表上,而是通过其他维表连接到事实表上时,其图解就像多个雪花连接在一起。
    优点:规范性较好,冗余小,数据集成和数据一致性方面得到重视,比如运营商可以参考国际电信运营业务流程规范(ETOM),有所谓的最佳实践。
    缺点:需要全面了解企业业务、数据和关系;实施周期非常长,成本昂贵;对建模人员的能力要求也非常高,容易烂尾。

    个人理解:
    在上一家公司使用的是维度建模,快速迭代快速交付,因为公司业务以及部门之间的协同关系,没办法从一个全局的高度来架构整个数据仓库,只能先跟着项目需求走,完成数据仓库的搭建和后续的报表、用户画像的需求开发。

    参考资料:
    https://mp.weixin.qq.com/s/lo_nIKpIl5G47XUvsEWtYw

  • 相关阅读:
    AngularJs $http.post 数据后台获取不到数据问题 的解决过程
    网络安全学习和CTF必不可少的一些网站
    汇编语言学习资料汇总
    链表的归并排序
    数学常用模板——矩阵 高精度
    Gym100810J Journey to the "The World's Start" (二分答案+动态规划)
    图论:最短路
    Codeforces Round #642 (Div. 3)补题
    离散数学真值表的计算
    【C/C++】字典树
  • 原文地址:https://www.cnblogs.com/bigband/p/13582388.html
Copyright © 2011-2022 走看看