关于hbase多线程写入问题

小小晋 发布于 2015/02/02 11:21
阅读 4K+
收藏 0

@cloud-coder 你好,想跟你请教个问题:

多线程写入hbase,官方已经摒弃了HtablePool方式写入,推荐使用HConnection#getTable方式。

问题:我不想put一次,就flushCommit。于是我在client端使用了setFlusthAo(false)以及缓存的大小XMB。

这种客户端只能达到table达到XMB的时候才能自动flushCommit。但是我们的业务只允许几秒延迟的,于是乎我使用了每隔三秒flushCommit一次(在getTable的时候,启动线程对这个table每隔3s flushCommit一次)。

发现Htable线程不是安全的,在我flushCommit的同时,会有其他线程对这个table进行写入。然后报异常

**ModificationException (具体名字忘记了)


请问对于这种问题,你有没有碰到过?然后是怎么处理的,谢谢!

加载中
0
cloud-coder
cloud-coder
// 初始化UserProvider
        UserProvider userProvider = UserProvider.instantiate(conf);

        // 初始化admin,ConnectionCache
        try {
            connectionCache = new ConnectionCache(conf, userProvider, cleanInterval, maxIdleTime);
            admin = new HBaseAdmin(conf);
        }
        catch (Exception e) {
            LOG.error("创建HBaseAdmin失败:" + e.getMessage());
        }

        // 初始化HTableFactory
        tableFactory = new HTableFactory() {
            @Override
            public HTableInterface createHTableInterface(Configuration config, byte[] tableName) {
                try {
                    return connectionCache.getTable(Bytes.toString(tableName));
                }
                catch (IOException ioe) {
                    throw new RuntimeException(ioe);
                }
            }
        };

        // 初始化Cache
        htablePools =
                CacheBuilder.newBuilder().expireAfterAccess(maxIdleTime, TimeUnit.MILLISECONDS).softValues()
                    .concurrencyLevel(4).build();
        htablePoolCreater = new Callable<HTablePool>() {
            public HTablePool call() {
                return new HTablePool(conf, maxPoolSize, tableFactory);
            }
        };


/**
     * 获取HTableInterface实例
     * 
     * @param tableName
     * @return
     */
    private static HTableInterface getTable(String tableName) {
        String currentUser = connectionCache.getEffectiveUser();
        try {
            HTablePool htablePool = htablePools.get(currentUser, htablePoolCreater);
            return htablePool.getTable(tableName);
        }
        catch (ExecutionException ee) {
            throw new RuntimeException(ee);
        }
    }



0
cloud-coder
cloud-coder

可以使用HtablePool,但创建时指定HTableInterfaceFactory,  在此工厂中指定从connect中直接获取连接,可以参考上面的代码

可以在方法中通过调用table.flushcommits进行提交,一般情况下一个事务提交一次

可以是一行或多行数据

小小晋
小小晋
我在评论中回复了,请帮忙看下。谢谢:)
0
小小晋
小小晋

引用来自“cloud-coder”的评论

可以使用HtablePool,但创建时指定HTableInterfaceFactory,  在此工厂中指定从connect中直接获取连接,可以参考上面的代码

可以在方法中通过调用table.flushcommits进行提交,一般情况下一个事务提交一次

可以是一行或多行数据

首先感谢你的回答。问题我不在于获取连接方式和flushcommit调用。
问题在于:我3s定时调用一次flushcommit table,同时这个table还在接收数据。。这时候会报错。我跟踪了代码,在执行writeAsyncBuffer删除的同时,改变的writeAsyncBuffer的大小,会报错。。


主要是在于我如何实现每隔3s定时刷新所有table。。如果不定时刷新,等缓存满,在数据量很小的时候,可能无法及时刷进server。。。
0
cloud-coder
cloud-coder

可以在方法中通过调用table.flushcommits进行提交,一般情况下一个事务提交一次

可以是一行或多行数据

0
cloud-coder
cloud-coder
你的问题我没有遇到过,
0
小小晋
小小晋

@cloud-coder  感谢您的答复。

我这边还有几个问题:

1、压缩完后(数据量达到1.6T),读的速度立马上升,但是写入速度速度下降,运行一段时间,会出现rpc连接一直断开现象。目前无法下手怎么优化,请问下你们对这方面怎么优化方法?

(我们有5台regionserver,压缩完后每台有70个region,每region 就1~2 个Store, 最大StoreFile是10G,只有一个簇)。


0
小小晋
小小晋

@cloud-coder   

目前我们的配置这样:

1、JVM大小 6G 。老生代在70%回收,目前从监控上来看还是够的。但是GC收集耗时都在200ms左右,偶尔会冲高到1s都有,这个是正常的么?

2、memstore 设置128  。region分裂是storeFile达到10G的时候开始

3、关闭自动压缩,凌晨开始压缩。

4、客户端关闭flushAuto 和wal,使用缓存方式发送数据。



0
cloud-coder
cloud-coder

hbase region的heap设置大点,如12G

使用的是什么版本的hbase,CDH5?

0
小小晋
小小晋

@cloud-coder     

hbase(Version 0.98.6-cdh5.2.0)

6G我发现已经够用了

小小晋
小小晋
当然是以我自身的业务来说
0
cloud-coder
cloud-coder

使用的是什么版本的hbase,CDH5? 

另外,压缩方式使用的是什么?

返回顶部
顶部