Flume

概述

分布式的海量日志采集,聚合和传输的系统。

优点:可以高速采集数据,采集的数据能够以想要的文件格式及压缩方式存储在HDFS上。事务功能保证了数据在采集的过程中数据不丢失,部分Source保证了Flume挂了以后重启依旧能够继续在上一次采集点采集数据,正真做到数据零丢失。

体系结构

体系结构图:

核心组件:

  • Client->生产数据,运行在一个独立的线程
  • Event->一个数据单元,消息头和信息体组成(Event可以是日志记录、avro对象等)
  • Flow->Event从源点到达目的点的迁移的抽象
  • Agent->一个独立的Flume进程,包含组件Source、Channel、Sink

Source:数据收集组件。(source从Client收集数据,传递给Channel) Channel:中转Event的一个临时存储,保存由Source组件转递过滤的Event。(Channel连接source和sink有点像消息队列) Sink:从Channel中读取并移除Event,将Event传递到FlowPipeline中的下一个Agent(Sink从Channel收集数据,运行在下一个独立线程)

事务机制

Flume处理流程中,有两个事务机制:推送事务机制和拉取事务机制

推送事务机制

doput:把批数据写入到临时缓冲区putList中,便于回滚,提高数据可靠性

doCommit:检查Channel容量是否足够,如果容量足够则把putList里的数据发送到Channel

doRollBack:如果Channel容量不够,则把数据回滚到putList

拉取事务机制

doTake:把数据读取到临时缓冲区takeList

doCommit:检查数据是否发送成功,成功则把event从takeList中移除

doRollBack:如果发送失败,则把takeList的数据回滚到Channel

事务机制的可靠性与恢复性
  • 可靠性:只有当sink接收到,数据落地完成的信息之后,才会将数据从管道中删除。事件在每个代理上的一个通道中上游。然后将事件传递到流中的下一个代理或终端存储库 (如HDFS)。仅将事件存储在下一个代理程序的通道或终端存储库中之后,才将其从通道中 删除。这就是Flume中单条消息传递语义如何提供流的端到端可靠性的方式。数据传输的方式不是byte,而是一个个的event,Flume使用事务性方法来确保事件的可靠传 递。源和接收器分别在事务中封装存储在通道中或由通道提供的事务中提供的事件的存储/检索。这确保了事件集在流中从点到点可靠地传递。在多条流的情况下,来自上一条的接收器 和来自下一条的源均运行其事务,以确保将数据安全地存储在下一条的通道中。
  • 可恢复性:当数据丢失了,只有从存储在磁盘的方式,才能将数据找回,事件在通道中恢复,该通道管理从故障中恢复。Flume支持持久的文件通道,该通道由本地文件系统支持。还有一个内存通道可以将事件简单地存储在内存队列中,这虽然速度更快,但是当代理进行死亡时,仍保留在内存通道中的任何事件都无法恢复。

拦截器

拦截器结构:header:key-value,body:数据

使用场景

场景一:时间戳拦截器

  • 解决的问题:零点漂移
  • 问题的产生:

2023-11-17 23:59:59:59此时产生的数据应该属于17号。由于机器运行的时间是根据系统时间来的,有可能此时的数据保存到了18号 生产数据的时间:2023-11-17 23:59:59:59 保存时的时间:2023-11-18 00:00:01:00。

  • 需求分析:使用拦截器根据生产时间来解决问题,通过Hive分析每日的销售数据--保存在hive分区表year=2023 month=11 day=17

场景二:拦截器与channel配合实现数据分流

两个特性:复制与多路复用

复制:利用Channel Selector将相同的数据发送到不同Channel中,不同Channel中的数据分发到不同的Sink,不同的Sink再将数据发送到指定位置。

多路复用:利用拦截器和Channel Selector将不同的数据发送到不同的Channel中,不同Channel中的数据分发到不同的Sink,不同的Sink再将数据发送到指定位置。

拦截器分类
自定义拦截器

java编写拦截器

typescript 复制代码
package com.flume;


import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class Hello01CustomInterceptor implements Interceptor {

    //声明一个全局变量
    private int count=0;

    //声明用户自定义参数
    private static Map<String, String> customParams;

    @Override
    public void initialize() {
        System.out.println("Hello01CustomInterceptor.initialize["+System.currentTimeMillis()+"]");
    }

    /**
     * 可以获取本批次【Batch】传递的所有事件
     * @param events
     * @return
     */
    @Override
    public List<Event> intercept(List<Event> events) {
        //声明一个List装载处理完毕后的Event
        List<Event> eventsNew = new ArrayList<>();
        //遍历传入的Event
        for (Event event :events) {
            Event eventNew = this.intercept(event);
            if(eventNew!=null){
                eventsNew.add(eventNew);
            }
        }
        return eventsNew;
    }

    /**
     * 将本批次内的数据依次进行处理
     * @param event
     * @return
     */
    @Override
    public Event intercept(Event event) {
        //获取Event的Header
        Map<String, String> headers = event.getHeaders();
        //获取Event的Body
        String body = new String(event.getBody());

        //设置Event的Header
        headers.put("master","cy_yyds");
        //设置Event的Body
        event.setBody(body.concat("_yjxxt_"+customParams.get("yjxxt")+"_"+ ++count).getBytes());

        //判断是否返回--只有能被3整除才能返回
        if (count%3==0){
            return event;
        }
        return null;
    }

    @Override
    public void close() {
        System.out.println("Hello01CustomInterceptor.close["+System.currentTimeMillis()+"]");
    }

    public static class Builder implements Interceptor.Builder{

        @Override
        public Interceptor build() {
            System.out.println("Builder.build["+System.currentTimeMillis()+"]");
            return new Hello01CustomInterceptor();
        }

        @Override
        public void configure(Context context) {
            Map<String, String> parameters = context.getParameters();
            customParams=parameters;
            parameters.entrySet().stream().forEach(System.out::println);
        }
    }
}

然后打成jar包放入liunx下的flume的lib中

option下的配置文件:

案例

简单案例与文件读取
Flume的高阶特性
  • Flume自连接:达到解耦
  • 故障转移:实现高可用
  • 负载均衡:增加吞吐量
相关推荐
geneculture24 分钟前
融智学形式本体论:一种基于子全域与超子域的统一认知架构
大数据·人工智能·哲学与科学统一性·信息融智学·融智时代(杂志)
xiaobaishuoAI1 小时前
分布式事务实战(Seata 版):解决分布式系统数据一致性问题(含代码教学)
大数据·人工智能·分布式·深度学习·wpf·geo
edisao3 小时前
一。星舰到底改变了什么?
大数据·开发语言·人工智能·科技·php
昨夜见军贴06163 小时前
AI审核的自我进化之路:IACheck AI审核如何通过自主学习持续提升检测报告审核能力
大数据·人工智能
冬至喵喵3 小时前
二进制编码、base64
大数据
coding-fun4 小时前
电子发票批量提取导出合并助手
大数据·数据库
墨香幽梦客4 小时前
家具ERP口碑榜单,物料配套专用工具推荐
大数据·人工智能
悟纤5 小时前
Suno 爵士歌曲创作提示整理 | Suno高级篇 | 第22篇
大数据·人工智能·suno·suno ai·suno api·ai music
yl45305 小时前
污泥清淤机器人实践复盘分享
大数据·人工智能·机器人
B站计算机毕业设计超人6 小时前
计算机毕业设计Python+百度千问大模型微博舆情分析预测 微博情感分析可视化 大数据毕业设计(源码+LW文档+PPT+讲解)
大数据·hive·hadoop·python·毕业设计·知识图谱·课程设计