flume-ng源码阅读memory-channel(原创)
org.apache.flume.channel.MemoryChannel类是Flume-NG的memory-channel。
private LinkedBlockingDeque<Event> queue;//mem-channel存放数据的地方
private Semaphore queueRemaining;//queue存量信号量
private Semaphore queueStored;//queue存量的信号量,保证channel里面有数据
private Semaphore bytesRemaining;//剩余字节信号量,以100字节为一个单位,也是动态调整的
Flume-NG的组件(source、sink、channel)总是先通过configure(Context context)方法,获取配置文件中的配置信息,在这配置了mem的最大容量capacity、事务的event最大容量transCapacity、缓存百分比byteCapacityBufferPercentage、最大内存所有事件允许总字节数 byteCapacity。还有信号量的初始化:
synchronized(queueLock) {//初始化mem
queue = new LinkedBlockingDeque<Event>(capacity);
queueRemaining = new Semaphore(capacity);
queueStored = new Semaphore(0);
}
以及:bytesRemaining = new Semaphore(byteCapacity);
queueStored这个比较特殊,初始为0表示开始时,queue没有数据,只要queue的大小有所调整时就需要调整这个信号量,增加就release,减少就tryAcquire。
当然在configure方法中可以看到如果配置文件修改后是如何动态修改的(flume默认每30s扫描加载一次配置文件)。
然后start()方法进行一些初始化操作。
resizeQueue(capacity)方法用来动态加载配置文件,调整mem容量的。
createTransaction()方法,返回MemoryTransaction实例。
estimateEventSize(Event event)方法,返回event.body的字节长度。
该类有一个内部类MemoryTransaction是mem-channel从source取(put)数据、给(take)sink的操作类。其初始化时会创建两个LinkedBlockingDeque,一个是takeList用于sink的take;一个是putList用于source的put,两个队列的容量都是事务的event最大容量transCapacity。两个队列是用于事务回滚rollback和提交commit的。
Source交给channel处理的一般是调用ChannelProcessor类的processEventBatch(List<Event> events)方法或者processEvent(Event event)方法;在sink端可以直接使用channel.take()方法获取其中的一条event数据。这俩方法在将event提交至channel时,都需要:
一、获取channel列表。List<Channel> requiredChannels = selector.getRequiredChannels(event);
二、通过channel获取Transaction。Transaction tx = reqChannel.getTransaction();
三、tx.begin();
四、reqChannel.put(event)(在sink中这是take(event)方法);
五、tx.commit();
六、tx.rollback();
七、tx.close()。
上面的三~七中的方法,最终调用的是MemoryTransaction的doBegin(未重写,默认空方法)、doPut、doCommit、doRollback、doClose(未重写,默认空方法)方法。
其中doPut方法,先计算event的大小可以占用bytesRemaining的多大空间,然后在有限的时间内等待获取写入空间,获取之后写入putList暂存。
doTake方法,先检查takeList的剩余容量;再检查是否有许可进行取操作(queueStored使得可以不用阻塞其它线程获取许可信息);然后同步的从queue中取一个event,再放入takeList,并返回此event。
doCommit方法,不管在sink还是source端都会调用。首先检查queue队列中是否有足够空间放得下从source过来的数据,依据就是queueRemaining是否有remainingChange = takeList.size-putList.size个许可。然后是将putList中的所有数据提交到内存队列queue之中,并将putList和takeList清空。清空表明:运行到这步说明takeList中的数据无需再保留,putList中的数据可以放入queue中。由于在doTake中从queue取数据,所以queueStored在减,但在doCommit中会把putList中的数据放入queue所以需要增加queueStored:queueStored.release(puts);bytesRemaining在doPut中获得了一些许可会减少,在doCommit中由于takeList会清空所有会增加bytesRemaining:bytesRemaining.release(takeByteCounter);而queueRemaining在doPut和doTake中并未进行操作,而且doCommit方法在sink和source中都会调用,故而在此方法中修改takeList和putList的差值即可:queueRemaining.release(remainingChange)(在此有个细节,在doCommit的开始remainingChange如果小于0,说明剩余空间不足以放入整个putList,要么超时报错退出;要么获得足够的许可,如果是后者的话就不需要再调整queueRemaining因为是在现在的基础之上减,如果remainingChange大于0,说明去除takeList大小后不仅足以放入整个putList,而且还有剩余,queueRemaining需要释放remainingChange)。其他就是修改计数器。
doRollback方法是在上面三、四、五出现异常的时候调用的,用于事务回滚。不管是在sink还是source中,都会调用。将takeList中的所有数据重新放回queue中:
while(!takeList.isEmpty()) {
queue.addFirst(takeList.removeLast());//回滚时,重新放回queue中。可能会重复(commit阶段出错,已经take的数据需要回滚,批量的情况)
}
然后清空putList:
putList.clear(); //这个方法可能发生在put中,也可能发生在take中,所以需要同步清空。可能会丢数据(还在put的阶段,没到commit阶段,出错会导致回滚,导致已经put还未放入queue中的数据会丢失)
由于putList清空了,所以bytesRemaining.release(putByteCounter);
由于takeList又返回给了queue所以queue的量增加了:queueStored.release(takes)。
在分层的分布式flume中,一旦汇总节点中断,而采集节点使用mem,则采集会大量的丢失数据,因为channel会因为put而快速的填满,填满之后再调用put会迸发异常,致使出现异常引起事务回滚,回滚会直接清空putList,使数据丢失,只留下channel中的数据(这些数据是一开始放入进去的后来的会丢失)。putList.offer会因为填满数据返回false,add方法如果队列满了则会爆异常。
讲解并不一定完全正确,希望大伙踊跃交流。
flume-ng源码阅读memory-channel(原创)的更多相关文章
- Flume-NG源码阅读之SpoolDirectorySource(原创)
org.apache.flume.source.SpoolDirectorySource是flume的一个常用的source,这个源支持从磁盘中某文件夹获取文件数据.不同于其他异步源,这个源能够避免重 ...
- Flume-NG源码阅读之Interceptor(原创)
有的时候希望通过Flume将读取的文件再细分存储,比如讲source的数据按照业务类型分开存储,具体一点比如类似:将source中web.wap.media等的内容分开存储:比如丢弃或修改一些数据.这 ...
- Flume-NG源码阅读之SourceRunner,及选择器selector和拦截器interceptor的执行
在AbstractConfigurationProvider类中loadSources方法会将所有的source进行封装成SourceRunner放到了Map<String, SourceRun ...
- Netty源码阅读之如何将TCP的读写操作和指定线程绑定
原文链接:http://xueliang.org/article/detail/20200712234015993 前言 在Netty的线程模型中,对于一个TCP连接的读写操作,都是由一个单线程完成的 ...
- JDK1.8源码阅读系列之四:HashMap (原创)
本篇随笔主要描述的是我阅读 HashMap 源码期间的对于 HashMap 的一些实现上的个人理解,用于个人备忘,有不对的地方,请指出- 接下来会从以下几个方面介绍 HashMap 源码相关知识: 1 ...
- [原创]chromium源码阅读-进程间通信IPC.消息的接收与应答
chromium源码阅读-进程间通信IPC.消息的接收与应答 chromium源码阅读-进程间通信IPC.消息的接收与应答 介绍 chromium进程间通信在win32下是通过命名管道的方式实现的 ...
- Spark源码阅读之存储体系--存储体系概述与shuffle服务
一.概述 根据<深入理解Spark:核心思想与源码分析>一书,结合最新的spark源代码master分支进行源码阅读,对新版本的代码加上自己的一些理解,如有错误,希望指出. 1.块管理器B ...
- TiDB 源码阅读系列文章(一)序
原创: 申砾 PingCAP 2018-02-28 在 TiDB DevCon2018 上,我们对外宣布了 TiDB 源码阅读分享活动,承诺对外发布一系列文章以及视频帮助大家理解 TiDB 源码.大 ...
- 【Dubbo源码阅读系列】服务暴露之远程暴露
引言 什么叫 远程暴露 ?试着想象着这么一种场景:假设我们新增了一台服务器 A,专门用于发送短信提示给指定用户.那么问题来了,我们的 Message 服务上线之后,应该如何告知调用方服务器,服务器 A ...
- Flume-NG源码阅读之AvroSink
org.apache.flume.sink.AvroSink是用来通过网络来传输数据的,可以将event发送到RPC服务器(比如AvroSource),使用AvroSink和AvroSource可以组 ...
随机推荐
- python中的URL编码和解码
python中的URL编码和解码:test.py # 引入urllib的request模块 import urllib.request url = 'https://www.douban.com/j/ ...
- Nginx/LVS/HAProxy 负载均衡软件的优缺点对比
Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,一般对负载均衡的使用是随着网站规模的提升根据不同的阶段来使用不同的技术,具体的应用需求还得具体分析. 如果是中小型的Web应用,比 ...
- Python2 显示 unicode
用户想要看的是 u'中文' 而不是 u'\u4e2d\u6587',但是在 Python2 中有时并不能实现. 转译 转义字符是这样一个字符,标志着在一个字符序列中出现在它之后的后续几个字符采取一种替 ...
- 请写出用于校验HTML文本框中输入的内容全部为数字的javascript代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html ...
- 错误0x80070522:客户端没有所需的特权
win10或win7 C盘复制文件等遇到"错误0x80070522:客户端没有所需的特权" 在运行中输入 icacls c:\ /setintegritylevel M
- 再谈Redis应用场景(转)
原文:在谈Redis应用场景 一.MySql+Memcached架构的问题 实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样 ...
- 细数Python中的数据类型以及他们的方法
一.数据类型的种类及主要功能 1.数字类型 数字类型主要是用来计算,它分为整数类型int和浮点类型float 2.布尔类型 布尔类型主要是用于判断,它分为真True和False两种 3.字符串类型 字 ...
- mysql以下c连接mysql数据库
1.安装sudo yum install mysql-devel 安装组件和库 2. #include <stdio.h> #include <stdlib.h> #incl ...
- Webbench进行网站压力测试
今天突然发现一个新大陆,Webbench,是linux下,用这很方便,开源,不限制并发访问次数和时间....大爱啊! 下载Webbench 使用wget 或者windows下载好导入linux也行, ...
- python3条件表达式和字符串
1.布尔表达式 布尔表达式的值只有两个:真和假.在python中,真值为1,假值为0 2.逻辑操作符 三种逻辑操作:and.or.not 3.条件语句 if. if...else.if...elif. ...