关于HBase的sink的所有内容均在org.apache.flume.sink.hbase包下。

  每个sink包括自己定制的,都extends AbstractSink implements Configurable。

  一、首先是configure(Context context)方法。该方法是对HBaseSink的参数初始化。主要包括以下几个:

  tableName:要写入的HBase数据表名,不能为空;

  columnFamily:数据表对应的列簇名,这个sink目前只支持一个列簇,不能为空;

  batchSize:每次事务可以处理的最大Event数量,默认是100;

  eventSerializerType:用来将event写入HBase,即将event转化为put。默认是org.apache.flume.sink.hbase.SimpleHbaseEventSerializer,还有一个是RegexHbaseEventSerializer,即适合HBaseSink的Serializer只有这俩,否则自己定制;

  serializerContext:是eventSerializerType的配置信息,就是配置文件中包含“serializer.”的项;

  kerberosKeytab和kerberosPrincipal是用来做访问控制的,默认都为空,即不设置。

  并生成eventSerializerType对应的实例并加以配置,两个Serializer各有不同的用途主要是一个只能写一列,一个可以写多列: 

 Class<? extends HbaseEventSerializer> clazz =
(Class<? extends HbaseEventSerializer>)
Class.forName(eventSerializerType);
serializer = clazz.newInstance();
serializer.configure(serializerContext); //配置序列化组件,先配置。默认是SimpleHbaseEventSerializer

  1、SimpleHbaseEventSerializer.configure(Context context):此Serializer只能将数据写入一列

   public void configure(Context context) {
rowPrefix = context.getString("rowPrefix", "default");  //获取RowKey的前缀,固定的部分,默认前缀是default
incrementRow =
context.getString("incrementRow", "incRow").getBytes(Charsets.UTF_8);//获取计数器对应的行键
String suffix = context.getString("suffix", "uuid");  //rowkey的类型(可以指定的有四种uuid/random/timestamp/nano),默认是uuid String payloadColumn = context.getString("payloadColumn");  //要写入HBase的列名
String incColumn = context.getString("incrementColumn");  //计数器对应的列
if(payloadColumn != null && !payloadColumn.isEmpty()) {  //根据suffix决定rowkey类型
if(suffix.equals("timestamp")){
keyType = KeyType.TS;
} else if (suffix.equals("random")) {
keyType = KeyType.RANDOM;
} else if(suffix.equals("nano")){
keyType = KeyType.TSNANO;
} else {
keyType = KeyType.UUID;
}
plCol = payloadColumn.getBytes(Charsets.UTF_8);  //列名
}
if(incColumn != null && !incColumn.isEmpty()) {  //存在计数器列
incCol = incColumn.getBytes(Charsets.UTF_8);
}
}

  2、RegexHbaseEventSerializer.configure(Context context):此Serializer根据正则可以写入多列

  public void configure(Context context) {
String regex = context.getString(REGEX_CONFIG, REGEX_DEFAULT);  //获取配置文件中的正则表达式,默认是“(.*)”
regexIgnoreCase = context.getBoolean(IGNORE_CASE_CONFIG,
INGORE_CASE_DEFAULT);  //是否忽略大小写
inputPattern = Pattern.compile(regex, Pattern.DOTALL
+ (regexIgnoreCase ? Pattern.CASE_INSENSITIVE : 0));  //将给定的正则表达式编译到具有给定标志的模式中 String colNameStr = context.getString(COL_NAME_CONFIG, COLUMN_NAME_DEFAULT);  //获取配置文件中的列名s
String[] columnNames = colNameStr.split(",");  //分割列名获得列名数组
for (String s: columnNames) {
colNames.add(s.getBytes(Charsets.UTF_8));
}
}

  二、start()方法。该方法首先会构造一个HTable对象,并table.setAutoFlush(false)来激活缓冲区(默认大小时2MB),随后的是一些检查。

  三、然后是process()方法用来从channel中take数据,serializer之后写入HBase。

 public Status process() throws EventDeliveryException {
Status status = Status.READY;
Channel channel = getChannel();
Transaction txn = channel.getTransaction();
List<Row> actions = new LinkedList<Row>();
List<Increment> incs = new LinkedList<Increment>();
txn.begin();
for(long i = 0; i < batchSize; i++) {
Event event = channel.take();
if(event == null){
status = Status.BACKOFF;
counterGroup.incrementAndGet("channel.underflow");
break;
} else {
serializer.initialize(event, columnFamily);
actions.addAll(serializer.getActions());
incs.addAll(serializer.getIncrements());
}
}
putEventsAndCommit(actions, incs, txn);
return status;
}

  1、actions和incs是要写入HBase的数据,actions对应的是数据;incs对应的是计数器。

  2、serializer.initialize(event, columnFamily),两个Serializer的initialize目的一样:

 public void initialize(Event event, byte[] columnFamily) {
this.payload = event.getBody();  //获取要处理的数据
this.cf = columnFamily;    //获取要写入的列簇
}

  3、serializer.getActions()

  SimpleHbaseEventSerializer.getActions()方法会根据configure(Context context)中设置的RowKey类型先获取rowkey,可以是毫秒时间戳、随机数、纳秒时间戳以及UUID128位数四种类型。然后构造一个Put对象,将(列簇,列名,数据)添加进这个Put,返回List<Row> actions。

  RegexHbaseEventSerializer.getActions()方法,首先会做一些判断匹配成功否?匹配出的个数和指定的列数相同否?,然后是获取rowkey,这里的rowkey是[time in millis]-[random key]-[nonce]三部分组成的字符串。剩下的是依次匹配列组成Put,返回List<Row> actions。

  4、serializer.getIncrements()

  SimpleHbaseEventSerializer.getIncrements()如果配置文件中配置了incrementColumn,就添加相应的计数器,否则返回一个没有数据的List<Increment>。

  RegexHbaseEventSerializer.getIncrements()直接返回一个没有数据的List<Increment>,即不设置计数器。

  5、putEventsAndCommit(actions, incs, txn)方法。首先会table.batch(actions)提交List<Put>;然后是计数器table.increment(i);txn.commit()提交事务;如有异常txn.rollback()回滚;txn.close()事务关闭。

  四、stop()方法。table.close();table = null;

  有两个问题撒:

  1、我们在开发HBase程序的时候总是要指定“hbase.zookeeper.quorum”对应的zookeeper地址的,但是看完HBaseSink也没发现设置的地方,是不是在HBase集群中的任意节点都不需要设置,除非在集群外节点才设置?

  2、还有在使用时发现放在安装有zookeeper的节点上运行flume报错,删除zookeeper后运行正常,没安装zookeeper的节点上运行正常,这是为什么??

  希望知道的可以解答哈。。。HBaseSink也比较简单。。。后续还有更多源码解读!敬请期待!!

Flume-NG源码阅读之HBaseSink的更多相关文章

  1. ng2048源码阅读

    ng2048源码阅读 Tutorial: http://www.ng-newsletter.com/posts/building-2048-in-angularjs.html Github: http ...

  2. Pytorch版本yolov3源码阅读

    目录 Pytorch版本yolov3源码阅读 1. 阅读test.py 1.1 参数解读 1.2 data文件解析 1.3 cfg文件解析 1.4 根据cfg文件创建模块 1.5 YOLOLayer ...

  3. Flume-NG源码阅读之AvroSink

    org.apache.flume.sink.AvroSink是用来通过网络来传输数据的,可以将event发送到RPC服务器(比如AvroSource),使用AvroSink和AvroSource可以组 ...

  4. 编译spark源码及塔建源码阅读环境

    编译spark源码及塔建源码阅读环境 (一),编译spark源码 1,更换maven的下载镜像: <mirrors> <!-- 阿里云仓库 --> <mirror> ...

  5. spark源码阅读

    根据spark2.2的编译顺序来确定源码阅读顺序,只阅读核心的基本部分. 1.common目录 ①Tags②Sketch③Networking④Shuffle Streaming Service⑤Un ...

  6. Sping学习笔记(一)----Spring源码阅读环境的搭建

    idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...

  7. JDK源码阅读-------自学笔记(一)(java.lang.Object重写toString源码)

    一.前景提要 Object类中定义有public String toString()方法,其返回值是 String 类型. 二.默认返回组成 类名+@+16进制的hashcode,当使用打印方法打印的 ...

  8. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  9. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

随机推荐

  1. poj1840

    Eqs Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 15133   Accepted: 7426 Description ...

  2. 《从零开始学Swift》学习笔记(Day 22)——闭包那些事儿!

    原创文章,欢迎转载.转载请注明:关东升的博客    我给Swift 中的闭包一个定义:闭包是自包含的匿名函数代码块,可以作为表达式.函数参数和函数返回值,闭包表达式的运算结果是一种函数类型. Swif ...

  3. Spring 缓存注解@Cacheable 在缓存时候 ,出现了第一次进入调用 方法 ,第二次不调用的异常

    代码: @Override @Cacheable(value = CACHE_NAME, key = "'CartItemkey_'+#uId") public List<S ...

  4. 控制台程序的中文输出乱码问题(export LC_CTYPE=zh_CN.GBK,或者修改/etc/sysconfig/i18n为zh_CN.GBK。使用setlocale(LC_CTYPE, "");会使用默认办法。编译器会将源码做转换成Unicode格式,或者指定gcc的输入文件的编码参数-finput-charset=GBK。Linux下应该用wprintf(L"%ls/n",wstr))

    今天发现用securecrt登陆时,gcc编译出错时会出现乱码,但直接在主机的窗口界面下用Shell编译却没有乱码.查看了一下当时的错误描述,发现它的引号是中文引号,导致在SecureCRT中显示出错 ...

  5. 避免每次都用sudo使用docker

    默认安装完 docker 后,每次执行 docker 都需要运行 sudo 命令,非常浪费时间影响效率.如果不跟 sudo,直接执行 docker images 命令会有如下问题: FATA[0000 ...

  6. 常用模块一(random模块、time模块、sys模块)

    一.random模块 import random # 1 取随机小数 应用:数学计算 ret = random.random() # 大于0且小于1之间的小数 print(ret) # 0.53559 ...

  7. Ubuntu部署jmeter

    一:ubuntu部署jdk 1:先下载jdk-8u74-linux-x64.tar.gz,上传到服务器,这里上传文件用到了ubuntu 下的 lrzsz. ubuntu下直接执行 sudo apt-g ...

  8. MySQL数据库(5)_MySQL数据库视图、触发器

    一.视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用. SELECT * FROM ( S ...

  9. (转)IIS tomcat共用80端口解决一个IP多个域名:使用Nginx反向代理方式使两者兼容

    from :http://www.cnblogs.com/wuyou/p/3455619.html 环境: windows server 2003,IIS6服务器,Tomcat7服务器 域名有几个: ...

  10. 使用ajax进行汽车详情表的查询

    主界面代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w ...