HBase过滤器与MapReduce数据输出量深度解析
-
- 引言
- 一、HBase过滤器详解
-
- 1.1 过滤器的作用
- 1.2 过滤器的主要用途
- 1.3 过滤器代码示例
- 1.4 过滤器性能对比
- 二、MapReduce输出量分析
-
- 2.1 输出量影响因素
- 2.2 过滤型MR程序
-
- 场景1:错误日志提取
- 场景2:订单状态过滤
- 2.3 解析型MR程序
-
- 场景:共同好友分析
- 2.4 聚合型MR程序
-
- 场景:Pi值计算
- 三、不同类型MR程序的输出量对比
- 四、优化策略
-
- 4.1 过滤型作业优化
- 4.2 解析型作业优化
- 4.3 聚合型作业优化
- 五、实际应用案例分析
-
- 5.1 场景:Sca阶段增强日志处理
- 5.2 场景:共同好友分析
- 六、总结
|
🌺The Begin🌺点点关注,收藏不迷路🌺 |
引言
在大数据生态系统中,过滤器是优化数据查询的关键技术,而MapReduce作业的输出量则直接影响集群的I/O负载和作业效率。本文将深入探讨HBase过滤器的用途,并结合具体场景分析MapReduce作业的输出量变化规律。
一、HBase过滤器详解
1.1 过滤器的作用
HBase过滤器主要用于增强查询功能和减少网络传输:
#mermaid-svg-chuMOrOWj5OKHhjq{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-chuMOrOWj5OKHhjq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-chuMOrOWj5OKHhjq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-chuMOrOWj5OKHhjq .error-icon{fill:#552222;}#mermaid-svg-chuMOrOWj5OKHhjq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-chuMOrOWj5OKHhjq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-chuMOrOWj5OKHhjq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-chuMOrOWj5OKHhjq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-chuMOrOWj5OKHhjq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-chuMOrOWj5OKHhjq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-chuMOrOWj5OKHhjq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-chuMOrOWj5OKHhjq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-chuMOrOWj5OKHhjq .marker.cross{stroke:#333333;}#mermaid-svg-chuMOrOWj5OKHhjq svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-chuMOrOWj5OKHhjq p{margin:0;}#mermaid-svg-chuMOrOWj5OKHhjq .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-chuMOrOWj5OKHhjq .cluster-label text{fill:#333;}#mermaid-svg-chuMOrOWj5OKHhjq .cluster-label span{color:#333;}#mermaid-svg-chuMOrOWj5OKHhjq .cluster-label span p{background-color:transparent;}#mermaid-svg-chuMOrOWj5OKHhjq .label text,#mermaid-svg-chuMOrOWj5OKHhjq span{fill:#333;color:#333;}#mermaid-svg-chuMOrOWj5OKHhjq .node rect,#mermaid-svg-chuMOrOWj5OKHhjq .node circle,#mermaid-svg-chuMOrOWj5OKHhjq .node ellipse,#mermaid-svg-chuMOrOWj5OKHhjq .node polygon,#mermaid-svg-chuMOrOWj5OKHhjq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-chuMOrOWj5OKHhjq .rough-node .label text,#mermaid-svg-chuMOrOWj5OKHhjq .node .label text,#mermaid-svg-chuMOrOWj5OKHhjq .image-shape .label,#mermaid-svg-chuMOrOWj5OKHhjq .icon-shape .label{text-anchor:middle;}#mermaid-svg-chuMOrOWj5OKHhjq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-chuMOrOWj5OKHhjq .rough-node .label,#mermaid-svg-chuMOrOWj5OKHhjq .node .label,#mermaid-svg-chuMOrOWj5OKHhjq .image-shape .label,#mermaid-svg-chuMOrOWj5OKHhjq .icon-shape .label{text-align:center;}#mermaid-svg-chuMOrOWj5OKHhjq .node.clickable{cursor:pointer;}#mermaid-svg-chuMOrOWj5OKHhjq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-chuMOrOWj5OKHhjq .arrowheadPath{fill:#333333;}#mermaid-svg-chuMOrOWj5OKHhjq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-chuMOrOWj5OKHhjq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-chuMOrOWj5OKHhjq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-chuMOrOWj5OKHhjq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-chuMOrOWj5OKHhjq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-chuMOrOWj5OKHhjq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-chuMOrOWj5OKHhjq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-chuMOrOWj5OKHhjq .cluster text{fill:#333;}#mermaid-svg-chuMOrOWj5OKHhjq .cluster span{color:#333;}#mermaid-svg-chuMOrOWj5OKHhjq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-chuMOrOWj5OKHhjq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-chuMOrOWj5OKHhjq rect.text{fill:none;stroke-width:0;}#mermaid-svg-chuMOrOWj5OKHhjq .icon-shape,#mermaid-svg-chuMOrOWj5OKHhjq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-chuMOrOWj5OKHhjq .icon-shape p,#mermaid-svg-chuMOrOWj5OKHhjq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-chuMOrOWj5OKHhjq .icon-shape rect,#mermaid-svg-chuMOrOWj5OKHhjq .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-chuMOrOWj5OKHhjq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-chuMOrOWj5OKHhjq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-chuMOrOWj5OKHhjq :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
有过滤器
带过滤条件的查询
服务器端过滤只返回1GB
客户端
RegionServer
无过滤器
查询所有数据
返回10GB数据
客户端
RegionServer
客户端过滤只取1GB
1.2 过滤器的主要用途
| 数据过滤 | 在服务端过滤数据,减少传输 | SingleColumnValueFilter |
| 行键过滤 | 根据行键模式匹配 | RowFilter |
| 列过滤 | 只返回指定列族/列 | FamilyFilter, QualifierFilter |
| 分页查询 | 实现数据分页 | PageFilter |
| 前缀过滤 | 匹配行键前缀 | PrefixFilter |
1.3 过滤器代码示例
// 创建HBase过滤器:只返回age大于30且城市为北京的数据
Scan scan = new Scan();
// 过滤器1:age > 30
SingleColumnValueFilter ageFilter = new SingleColumnValueFilter(
Bytes.toBytes("info"),
Bytes.toBytes("age"),
CompareOperator.GREATER,
Bytes.toBytes(30)
);
// 过滤器2:city = "北京"
SingleColumnValueFilter cityFilter = new SingleColumnValueFilter(
Bytes.toBytes("info"),
Bytes.toBytes("city"),
CompareOperator.EQUAL,
Bytes.toBytes("北京")
);
// 组合过滤器:AND条件
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
filterList.addFilter(ageFilter);
filterList.addFilter(cityFilter);
scan.setFilter(filterList);
// 执行查询
ResultScanner scanner = table.getScanner(scan);
1.4 过滤器性能对比
| 数据扫描量 | 100GB | 100GB | – |
| 网络传输量 | 100GB | 1GB | 99% |
| 客户端内存 | 高 | 低 | 显著 |
| 响应时间 | 慢 | 快 | 10-100倍 |
二、MapReduce输出量分析
2.1 输出量影响因素
MapReduce作业的输出量主要取决于作业类型和业务逻辑:
#mermaid-svg-VC5mvaHdsBCA2PpJ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VC5mvaHdsBCA2PpJ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VC5mvaHdsBCA2PpJ .error-icon{fill:#552222;}#mermaid-svg-VC5mvaHdsBCA2PpJ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VC5mvaHdsBCA2PpJ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VC5mvaHdsBCA2PpJ .marker.cross{stroke:#333333;}#mermaid-svg-VC5mvaHdsBCA2PpJ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VC5mvaHdsBCA2PpJ p{margin:0;}#mermaid-svg-VC5mvaHdsBCA2PpJ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-VC5mvaHdsBCA2PpJ .cluster-label text{fill:#333;}#mermaid-svg-VC5mvaHdsBCA2PpJ .cluster-label span{color:#333;}#mermaid-svg-VC5mvaHdsBCA2PpJ .cluster-label span p{background-color:transparent;}#mermaid-svg-VC5mvaHdsBCA2PpJ .label text,#mermaid-svg-VC5mvaHdsBCA2PpJ span{fill:#333;color:#333;}#mermaid-svg-VC5mvaHdsBCA2PpJ .node rect,#mermaid-svg-VC5mvaHdsBCA2PpJ .node circle,#mermaid-svg-VC5mvaHdsBCA2PpJ .node ellipse,#mermaid-svg-VC5mvaHdsBCA2PpJ .node polygon,#mermaid-svg-VC5mvaHdsBCA2PpJ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VC5mvaHdsBCA2PpJ .rough-node .label text,#mermaid-svg-VC5mvaHdsBCA2PpJ .node .label text,#mermaid-svg-VC5mvaHdsBCA2PpJ .image-shape .label,#mermaid-svg-VC5mvaHdsBCA2PpJ .icon-shape .label{text-anchor:middle;}#mermaid-svg-VC5mvaHdsBCA2PpJ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VC5mvaHdsBCA2PpJ .rough-node .label,#mermaid-svg-VC5mvaHdsBCA2PpJ .node .label,#mermaid-svg-VC5mvaHdsBCA2PpJ .image-shape .label,#mermaid-svg-VC5mvaHdsBCA2PpJ .icon-shape .label{text-align:center;}#mermaid-svg-VC5mvaHdsBCA2PpJ .node.clickable{cursor:pointer;}#mermaid-svg-VC5mvaHdsBCA2PpJ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VC5mvaHdsBCA2PpJ .arrowheadPath{fill:#333333;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VC5mvaHdsBCA2PpJ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VC5mvaHdsBCA2PpJ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VC5mvaHdsBCA2PpJ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VC5mvaHdsBCA2PpJ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VC5mvaHdsBCA2PpJ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VC5mvaHdsBCA2PpJ .cluster text{fill:#333;}#mermaid-svg-VC5mvaHdsBCA2PpJ .cluster span{color:#333;}#mermaid-svg-VC5mvaHdsBCA2PpJ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VC5mvaHdsBCA2PpJ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VC5mvaHdsBCA2PpJ rect.text{fill:none;stroke-width:0;}#mermaid-svg-VC5mvaHdsBCA2PpJ .icon-shape,#mermaid-svg-VC5mvaHdsBCA2PpJ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VC5mvaHdsBCA2PpJ .icon-shape p,#mermaid-svg-VC5mvaHdsBCA2PpJ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VC5mvaHdsBCA2PpJ .icon-shape rect,#mermaid-svg-VC5mvaHdsBCA2PpJ .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VC5mvaHdsBCA2PpJ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VC5mvaHdsBCA2PpJ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VC5mvaHdsBCA2PpJ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
作业类型
过滤型Filter
输出 < 输入
解析型Parse
输出 > 输入
聚合型Aggregate
输出 << 输入
2.2 过滤型MR程序
特点:输出量远小于输入量,只保留满足条件的数据。
场景1:错误日志提取
// 场景:从1.5T-2T的日志中提取ERROR级别日志
public class ErrorLogFilter extends Mapper<LongWritable, Text, Text, Text> {
public void map(LongWritable key, Text value, Context context) {
String line = value.toString();
if (line.contains("ERROR") || line.contains("Exception")) {
context.write(new Text(line), new Text(""));
}
}
}
// 输入:1.5T – 2T 全量日志
// 输出:假设错误日志占1%,约15GB – 20GB
// 输出/输入 ≈ 1%
场景2:订单状态过滤
// 过滤出已完成订单
public class CompletedOrderFilter extends Mapper<LongWritable, Text, Text, Text> {
public void map(LongWritable key, Text value, Context context) {
String[] fields = value.toString().split(",");
String status = fields[3]; // 订单状态字段
if ("COMPLETED".equals(status)) {
context.write(new Text(fields[0]), value);
}
}
}
// 输入:1亿条订单记录
// 输出:已完成订单约占30%,3000万条
// 输出/输入 ≈ 30%
2.3 解析型MR程序
特点:输出量大于输入量,一条输入产生多条输出。
场景:共同好友分析
// 场景:输入是用户好友列表,输出是用户对的共同好友
// 输入格式:用户A\\t好友1,好友2,好友3
public class CommonFriendsMapper extends Mapper<LongWritable, Text, Text, Text> {
public void map(LongWritable key, Text value, Context context) {
String[] parts = value.toString().split("\\t");
String user = parts[0];
String[] friends = parts[1].split(",");
// 为每个好友对生成一条记录
for (int i = 0; i < friends.length; i++) {
for (int j = i + 1; j < friends.length; j++) {
// 输出:好友对 -> 共同拥有者
String friendPair = friends[i] + "-" + friends[j];
context.write(new Text(friendPair), new Text(user));
}
}
}
}
// 输入:100万用户,平均每人100个好友
// 输入记录数:100万条
// 输出记录数:100万 * C(100,2) ≈ 100万 * 4950 ≈ 49.5亿条
// 输出/输入 ≈ 4950倍!
2.4 聚合型MR程序
特点:输出量远小于输入量,进行汇总计算。
场景:Pi值计算
// 场景:通过蒙特卡洛方法计算圆周率
// 输入:大量随机点
public class PiEstimator {
public static class PiMapper extends Mapper<Object, Text, Text, IntWritable> {
public void map(Object key, Text value, Context context) {
// 每个map任务处理一批随机点
int inside = 0;
int total = Integer.parseInt(value.toString());
for (int i = 0; i < total; i++) {
double x = Math.random();
double y = Math.random();
if (x*x + y*y <= 1) inside++;
}
// 只输出两个数字:圆内点数和总点数
context.write(new Text("inside"), new IntWritable(inside));
context.write(new Text("total"), new IntWritable(total));
}
}
public static class PiReducer extends Reducer<Text, IntWritable, Text, DoubleWritable> {
public void reduce(Text key, Iterable<IntWritable> values, Context context) {
// 聚合所有map的结果
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
if (key.toString().equals("inside")) {
insideSum = sum;
} else {
totalSum = sum;
}
}
public void cleanup(Context context) {
// 计算Pi值
double pi = 4.0 * insideSum / totalSum;
context.write(new Text("Estimated Pi"), new DoubleWritable(pi));
}
}
}
// 输入:10亿个随机点(10GB数据)
// 输出:只有1个数值(Pi的估计值)≈ 8字节
// 输出/输入 ≈ 1 : 1,250,000,000
三、不同类型MR程序的输出量对比
| 过滤型 | 错误日志提取 | 2TB | 20GB | 1% | 输入 > 输出 |
| 过滤型 | 订单状态过滤 | 1亿条 | 3000万条 | 30% | 输入 > 输出 |
| 解析型 | 共同好友分析 | 100万条 | 49.5亿条 | 4950倍 | 输入 < 输出 |
| 解析型 | 日志解析成结构化 | 1GB | 1.2GB | 120% | 输入 < 输出 |
| 聚合型 | Pi值计算 | 10GB | 8字节 | 极小 | 输入 >>> 输出 |
| 聚合型 | 单词计数 | 100GB | 1MB | 0.001% | 输入 >>> 输出 |
四、优化策略
4.1 过滤型作业优化
// 使用Combiner提前过滤
public class OptimizedFilter extends Mapper<...> {
public void map(...) {
// 尽早过滤
if (!shouldKeep(line)) return;
// 使用压缩输出
context.getConfiguration().setBoolean("mapreduce.output.compress", true);
context.getConfiguration().set("mapreduce.output.compression.codec",
"org.apache.hadoop.io.compress.SnappyCodec");
}
}
4.2 解析型作业优化
// 控制爆炸式增长的输出
public class ControlledParseMapper extends Mapper<...> {
public void map(...) {
// 限制输出量
if (context.getCounter("Parse", "OutputCount").getValue() > MAX_OUTPUT) {
return; // 超过阈值,停止输出
}
// 批量输出
List<Text> batchOutput = new ArrayList<>();
// 填充batchOutput
for (Text output : batchOutput) {
context.write(output, ...);
}
}
}
4.3 聚合型作业优化
// 使用Combiner减少数据传输
public class PiCombiner extends Reducer<Text, IntWritable, Text, IntWritable> {
public void reduce(Text key, Iterable<IntWritable> values, Context context) {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
context.write(key, new IntWritable(sum)); // 预聚合
}
}
五、实际应用案例分析
5.1 场景:Sca阶段增强日志处理
// 处理1.5T-2T的增强日志
public class ScaLogProcessor {
public static void main(String[] args) {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "Sca Log Processor");
job.setJarByClass(ScaLogProcessor.class);
// Mapper配置
job.setMapperClass(LogFilterMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(LogWritable.class);
// Reducer配置
job.setReducerClass(LogAggregatorReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
// 输入:2TB
FileInputFormat.addInputPath(job, new Path("/data/sca/logs"));
// 输出:约20GB (1% 过滤率)
FileOutputFormat.setOutputPath(job, new Path("/output/sca/filtered"));
// 启用压缩
FileOutputFormat.setCompressOutput(job, true);
FileOutputFormat.setOutputCompressorClass(job, SnappyCodec.class);
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
static class LogFilterMapper extends Mapper<...> {
public void map(...) {
String line = value.toString();
// 只保留ERROR级别日志
if (line.contains("ERROR") || line.contains("WARN")) {
context.write(...);
}
}
}
}
5.2 场景:共同好友分析
// 完整共同好友分析作业
public class CommonFriends {
public static void main(String[] args) throws Exception {
// 输入:用户好友列表
// 输出:共同好友统计
// 预期输出量估算:
// 100万用户,平均100好友
// 中间输出 ≈ 100万 * 4950 = 49.5亿条
// 最终输出 ≈ 1000万条好友对
// 需要大量资源
job.setNumReduceTasks(200); // 增加Reducer数量
}
}
六、总结
| 过滤型 | 输入 > 输出 | 日志过滤、状态筛选 | 尽早过滤、压缩输出 |
| 解析型 | 输入 < 输出 | 共同好友、数据展开 | 控制爆炸增长、内存管理 |
| 聚合型 | 输入 >> 输出 | 统计计算、Pi值 | Combiner使用、预聚合 |
| HBase过滤器 | 减少网络传输 | 数据查询优化 | 服务端过滤、合理设计 |
核心要点:
理解不同作业类型的数据量特征,有助于合理规划资源、优化作业性能,避免出现OOM或数据倾斜问题。

|
🌺The End🌺点点关注,收藏不迷路🌺 |



