面试题3

为什么Netty使用NIO而不是AIO?

前言
AIO是异步非阻塞的,NIO是同步非阻塞的。理论上讲,AIO的吞吐量肯定比NIO的要大。两种IO的概念如下:

1,NIO模型: 同步非阻塞。服务器实现模式为一个请求一个线程,但客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
2,AIO模型: 异步非阻塞。服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。注:AIO又称为NIO2.0,在JDK7才开始支持。

为什么Netty使用NIO而不是AIO?
主要原因如下:

1,Netty不看重Windows上的使用,在Linux系统上,AIO的底层实现仍使用EPOLL,没有很好实现AIO,因此在性能上没有明显的优势,而且被JDK封装了一层不容易深度优化。
2,Netty整体架构是reactor模型, 而AIO是proactor模型, 混合在一起会非常混乱,把AIO也改造成reactor模型看起来是把epoll绕个弯又绕回来。
3,AIO还有个缺点是接收数据需要预先分配缓存, 而不是NIO那种需要接收时才需要分配缓存, 所以对连接数量非常大但流量小的情况, 内存浪费很多。
4,Linux上AIO不够成熟,处理回调结果速度跟不上处理需求,比如外卖员太少,顾客太多,供不应求,造成处理速度有瓶颈(待验证)。
作者原话引用:

作者原话:
Not faster than NIO (epoll) on unix systems (which is true)
There is no daragram suppport
Unnecessary threading model (too much abstraction without usage)

HBASE和HDFS的区别

HDFS(Hadoop Distributed File System)和HBase是Hadoop生态系统中两个不同的组件,具有不同的目的和用例。

目的和用例
HDFS是一个分布式文件系统,旨在存储大量的数据文件。它使用块存储数据,并自动将这些块副本分布到群集中的不同节点,以确保可靠性和容错性。
HBase是一个分布式非关系型数据库,旨在存储结构化数据,并支持高性能的随机访问。它建立在HDFS之上,使用HDFS来存储数据,并提供类似于关系型数据库的API和查询语言。
数据模型
HDFS存储的是文件系统中的文件,它提供的是一个类似于POSIX文件系统的命名空间。
HBase存储的是键值对,其中每个键都是唯一的,并与一个值相关联。这种模型类似于一个大型的、分布式的哈希表。
访问模式
HDFS通常用于批处理,它支持一次写入、多次读取的访问模式。例如,数据可以写入HDFS一次,然后通过MapReduce作业多次读取和处理。
HBase支持随机读写访问,这使得它适用于实时数据查询和更新。例如,HBase可以用于存储Web应用程序中的用户配置文件、社交媒体的用户帖子等。
存储方式
HDFS使用块(Block)的方式存储数据,块的大小通常为128MB或256MB。HDFS的存储模型更适合大规模的批处理,而非实时随机读写。
HBase使用HDFS作为其底层存储层,但是它以不同的方式存储数据。HBase在HDFS上实现了类似于LSM-tree(Log-Structured Merge-Tree)的数据结构,以便支持随机读写。
总的来说,HDFS适用于存储大规模的数据文件,而HBase适用于存储结构化数据,支持高性能的随机读写。在使用这些组件时,需要根据应用程序的需求和数据模型选择适当的组件。

MapReduce详细经过了哪些阶段

MapReduce 是一种用于大规模数据处理的编程模型,其经过以下阶段:

输入数据的切分:将大规模的输入数据切分成小的数据块,使得每个数据块可以被独立处理。

Map 阶段:将切分后的数据块分配给多个 Map 任务进行处理。在 Map 任务中,会将输入数据解析成一系列的 <key, value> 键值对,并对每个键值对执行一组指定的操作(通常是过滤、转换和筛选等),输出一系列的中间结果。

Shuffle 阶段:将 Map 阶段输出的中间结果根据相同的 key 进行归并排序,并将归并后的结果分发给相应的 Reduce 任务。

Reduce 阶段:将 Shuffle 阶段输出的中间结果分配给多个 Reduce 任务进行处理。在 Reduce 任务中,会对相同 key 的中间结果进行一组指定的操作(通常是合并、聚合和汇总等),并将最终结果输出。

输出结果:将 Reduce 阶段输出的结果存储到指定的输出位置。

以上是 MapReduce 的基本流程,不同的实现方式可能会有一些细节上的差别。

MapReduce用代码如何实现

以下是使用 Java 编写的一个简单的 MapReduce 实现,假设有一个输入文件 input.txt,其中包含多行文本,每行文本包含一个数字:

点击查看代码
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MapReduceExample {

    // 定义 Map 函数
    public static List<Pair<Integer, Integer>> mapper(String filename) throws IOException {
        List<Pair<Integer, Integer>> results = new ArrayList<>();
        List<String> lines = Files.readAllLines(Paths.get(filename));
        for (String line : lines) {
            int value = Integer.parseInt(line);
            results.add(new Pair<>(value, 1)); // 输出键值对 <value, 1>
        }
        return results;
    }

    // 定义 Reduce 函数
    public static Map<Integer, Integer> reducer(List<Pair<Integer, Integer>> pairs) {
        Map<Integer, Integer> result = new HashMap<>();
        for (Pair<Integer, Integer> pair : pairs) {
            int key = pair.getKey();
            int value = pair.getValue();
            if (result.containsKey(key)) {
                result.put(key, result.get(key) + value); // 对相同 key 的 value 进行累加
            } else {
                result.put(key, value);
            }
        }
        return result;
    }

    public static void main(String[] args) throws IOException {
        String inputPath = "input.txt";
        String outputPath = "output.txt";

        // Map 阶段
        List<Pair<Integer, Integer>> intermediateResults = mapper(inputPath);

        // Shuffle 阶段(省略)

        // Reduce 阶段
        Map<Integer, Integer> finalResults = reducer(intermediateResults);

        // 输出结果到文件
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<Integer, Integer> entry : finalResults.entrySet()) {
            sb.append(entry.getKey()).append("\t").append(entry.getValue()).append("\n");
        }
        Files.writeString(Paths.get(outputPath), sb.toString());
    }
}
上述实现中,Map 函数将输入文件中的每个数字转换成键值对 ,表示出现次数为 1,Reduce 函数将相同 key 的键值对进行合并,得到最终结果。在 MapReduce 中,Shuffle 阶段由框架自动完成,因此在实现中并未包含。最后,将最终结果输出到文件。

HBASE的数据结构是怎样的,举例说明

HBase 是一个基于 Hadoop 的分布式列式数据库,其数据结构由表格(Table)、行(Row)、列族(Column Family)和列(Column)四个层级组成。

表格(Table)是数据存储的最高层级,由多个行组成。表格由命名空间(Namespace)和表名(Table Name)两个标识符唯一标识。

行(Row)是表格中的一行数据,它由一个唯一的行键(Row Key)和多个列族组成。行键可以是任意字节数组,用于唯一标识该行数据。行中的列族和列定义了数据的结构和格式。

列族(Column Family)是列的逻辑分组,每个列族可以包含多个列。每个列族都有一个名称(Column Family Name)和一些属性,例如数据的压缩算法和存储在硬盘上的数据的版本数量。列族在表创建时必须预定义,而且不能在运行时添加或删除。

列(Column)是表格中的一列数据,由行键、列族和列限定符(Column Qualifier)组成。列限定符是列族中的一个子集,用于唯一标识该列。列的值可以是任意字节数组,大小可以从几个字节到几百兆字节不等。

举个例子,假设我们有一个 HBase 表格,用于存储学生成绩数据。该表格的表名为“student_scores”,包含两个列族:“personal_info”和“score_info”。每行数据的行键为学生的学号,列限定符分别为“name”、“age”、“grade”和“score”。

那么,一条学生数据的存储结构如下:

点击查看代码
rowkey: "12345" 
column family: "personal_info"
    column qualifier: "name" 
        value: "张三" 
    column qualifier: "age" 
        value: "18" 
column family: "score_info"
    column qualifier: "grade" 
        value: "一年级" 
    column qualifier: "score" 
        value: "90"
在这个例子中,“personal_info”和“score_info”分别是列族,每个列族下包含两个列限定符。这样的数据结构可以很方便地查询某个学生的个人信息和成绩信息。
posted @ 2023-03-17 16:43  卡卡罗特琪琪  阅读(14)  评论(0编辑  收藏  举报