MapReduce过程中用到了哪些数据结构和算法

MapReduce 中的数据结构和算法

✅ 一、Map 阶段使用的数据结构和算法

1. 内存缓冲区 - 环形缓冲区

数据结构: 环形缓冲区 (Circular Buffer)
算法: 环形队列操作
实现原理
// 伪代码
class MapOutputBuffer {
    private byte[] kvbuffer;  // 键值对缓冲区
    private int[] kvmeta;     // 元数据索引
    private int softLimit;    // 软限制阈值
    private int bufmark;      // 当前写入位置
    private int bufindex;     // 当前读取位置
}
特点
  • 空间效率:连续内存分配
  • 操作效率:O(1) 的插入和读取
  • 内存管理:避免频繁的内存分配

2. 排序 - 快速排序 + 归并排序

数据结构: 数组
算法: 快速排序 (QuickSort) + 归并排序 (MergeSort)
排序过程
// 溢写前排序
private void sortAndSpill() {
    // 快速排序:对内存中的键值对按 key 排序
    QuickSort.sort(kvbuffer, kvmeta, partition, sort_0, sort_1);
    
    // 归并排序:合并多个溢写文件
    MergeSort.merge(spillFiles);
}

3. 分区 - 哈希算法

数据结构: 散列表 (Hash Table) 
算法: 一致性哈希 (Consistent Hashing)
分区算法
public class HashPartitioner<K, V> implements Partitioner<K, V> {
    public int getPartition(K key, V value, int numPartitions) {
        // 哈希算法:key.hashCode() & Integer.MAX_VALUE) % numPartitions
        return (key.hashCode() & Integer.MAX_VALUE) % numPartitions;
    }
}

✅ 二、Shuffle 阶段使用的数据结构和算法

1. 溢写文件管理 - 堆 (Heap)

数据结构: 最小堆 (Min-Heap)
算法: 堆排序 + 优先队列
文件合并算法
// 合并多个已排序的溢写文件
public class Merger {
    public static <K, V> void merge(List<File> spillFiles) {
        // 使用最小堆维护多个文件的最小元素
        PriorityQueue<SpillRecord> heap = new PriorityQueue<>();
        
        // 每个文件的最小元素入堆
        for (File file : spillFiles) {
            heap.offer(new SpillRecord(file));
        }
        
        // 堆顶元素输出,对应文件下一条记录入堆
        while (!heap.isEmpty()) {
            SpillRecord record = heap.poll();
            output.write(record);
            record.next();
            if (record.hasNext()) {
                heap.offer(record);
            }
        }
    }
}

2. 网络传输 - 流式处理

数据结构: 流 (Stream)
算法: 分块传输 + 校验和
传输算法
public class ShuffleClient {
    public void copyFromMap(TaskAttemptID mapId) {
        // 分块读取 Map 输出
        while (hasMoreData) {
            byte[] chunk = readChunk();
            // CRC32 校验和验证
            if (validateCRC(chunk)) {
                writeToFile(chunk);
            }
        }
    }
}

3. 内存管理 - LRU 缓存

数据结构: LinkedHashMap (LRU Cache)
算法: 最近最少使用算法
缓存管理
public class InMemoryMapOutput<K, V> {
    // LRU 缓存管理
    private LinkedHashMap<String, MapOutput> cache = 
        new LinkedHashMap<String, MapOutput>(16, 0.75f, true) {
        protected boolean removeEldestEntry(Map.Entry<String, MapOutput> eldest) {
            return size() > maxCacheSize;
        }
    };
}

✅ 三、Reduce 阶段使用的数据结构和算法

1. 分组 - 分组算法

数据结构: HashMap + ArrayList
算法: 分组排序 (GroupBy Sort)
分组实现
public class GroupingCollector<K, V> {
    public void collect() {
        // 按 key 分组
        Map<K, List<V>> groupedData = new HashMap<>();
        
        for (Map.Entry<K, V> entry : sortedInput) {
            K key = entry.getKey();
            V value = entry.getValue();
            
            groupedData.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
        }
    }
}

2. 迭代器模式

数据结构: 迭代器 (Iterator)
算法: 惰性求值 (Lazy Evaluation)
迭代器实现
public class ReduceIterator<K, V> implements Iterator<V> {
    private K currentKey;
    private Iterator<V> currentValueIterator;
    
    public boolean hasNext() {
        return currentValueIterator.hasNext();
    }
    
    public V next() {
        // 惰性求值:只有在需要时才获取下一个值
        return currentValueIterator.next();
    }
}

✅ 四、系统级数据结构和算法

1. 任务调度 - 优先队列

数据结构: 优先队列 (PriorityQueue)
算法: 任务调度算法
任务队列管理
public class TaskScheduler {
    // 按优先级调度任务
    private PriorityQueue<Task> taskQueue = 
        new PriorityQueue<>(Comparator.comparing(Task::getPriority));
}

2. 心跳机制 - 状态机

数据结构: 状态机 (State Machine)
算法: 心跳检测算法
状态管理
public enum TaskState {
    NEW, RUNNING, SUCCESS, FAILED, KILLED
}

public class TaskStatus {
    private TaskState state = TaskState.NEW;
    private long lastHeartbeat;
    
    public boolean isAlive() {
        return System.currentTimeMillis() - lastHeartbeat < HEARTBEAT_TIMEOUT;
    }
}

✅ 五、性能优化相关算法

1. 推测执行 - 统计算法

数据结构: 滑动窗口
算法: 统计分析 + 异常检测
推测执行判断
public class SpeculativeTaskDetector {
    private SlidingWindow<TaskProgress> progressWindow;
    
    public boolean shouldLaunchSpeculative(Task task) {
        double avgProgress = progressWindow.getAverage();
        double taskProgress = task.getProgress();
        
        // 如果任务进度远低于平均进度,启动推测任务
        return taskProgress < avgProgress * 0.5;
    }
}

2. 压缩算法

数据结构: 压缩字典
算法: LZO/Snappy/GZIP 压缩算法

✅ 六、算法复杂度分析

阶段算法时间复杂度空间复杂度说明
Map 排序快速排序O(n log n)O(log n)内存排序
溢写合并归并排序O(n log k)O(k)k个文件合并
网络传输流式处理O(n)O(1)分块传输
Reduce 分组哈希分组O(n)O(n)HashMap 操作

✅ 七、实际应用示例

WordCount 中的算法应用

// Map 阶段
public void map(LongWritable key, Text value, Context context) {
    // 使用 HashMap 统计词频(Combiner 优化)
    Map<String, Integer> wordCount = new HashMap<>();
    
    String[] words = value.toString().split("\\s+");
    for (String word : words) {
        wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
    }
    
    // 输出到缓冲区,触发排序和分区
    for (Map.Entry<String, Integer> entry : wordCount.entrySet()) {
        context.write(new Text(entry.getKey()), new IntWritable(entry.getValue()));
    }
}

📌 面试总结

MapReduce 核心数据结构:环形缓冲区、HashMap、优先队列、迭代器。关键算法:哈希分区、快速排序、归并排序、LRU 缓存、流式处理。优化策略:内存排序、溢写合并、网络压缩、推测执行。复杂度:Map 排序 O(n log n),Reduce 分组 O(n)。

核心要点内存管理 + 排序算法 + 哈希算法 + 流式处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

走过冬季

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值