6

我们正在处理一个需要在插入之前检查记录是否存在的场景。如果记录已经存在,我们不会再次插入它。我们正在分批进行。首先我们创建一批Get来查看我们要插入的记录是否存在。当表大小较小并且非常断断续续时,不会出现此问题。Get 的推荐批量大小是多少在插入之前检查记录是否存在的最佳方法是什么?感谢您的回复..

这是堆栈跟踪..

java.util.concurrent.ExecutionException: java.net.SocketTimeoutException: Call to b16-pf-dv-093.abc.com/10.106.8.103:60020 failed on socket timeout exception: java.net.SocketTimeoutException: 60000 millis timeout while waiting for channel to be ready for read. ch : java.nio.channels.SocketChannel[connected local=/10.106.8.133:41903 remote=b16-pf-dv-093.abc.com/10.106.8.103:60020] 
        at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222) 
        at java.util.concurrent.FutureTask.get(FutureTask.java:83) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatchCallback(HConnectionManager.java:1604) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatch(HConnectionManager.java:1456) 
        at org.apache.hadoop.hbase.client.HTable.batch(HTable.java:757) 
        at org.apache.hadoop.hbase.client.HTable.get(HTable.java:726) 
        at org.apache.hadoop.hbase.client.HTablePool$PooledHTable.get(HTablePool.java:367) 
        at com.abc.psp.core.metering.util.HBaseClient.get(HBaseClient.java:263) 
        at com.abc.psp.core.metering.dao.MeteringHBaseDAOImpl.addMeteredRecords(MeteringHBaseDAOImpl.java:374) 
        at com.abc.psp.core.metering.dao.MeteringHBaseDAOImpl.addMeteredRecords(MeteringHBaseDAOImpl.java:342) 
        at HBaseTest.main(HBaseTest.java:32) 
Caused by: java.net.SocketTimeoutException: Call to b16-pf-dv-093.abc.com/10.106.8.103:60020 failed on socket timeout exception: java.net.SocketTimeoutException: 60000 millis timeout while waiting for channel to be ready for read. ch : java.nio.channels.SocketChannel[connected local=/10.106.8.133:41903 remote=b16-pf-dv-093.abc.com/10.106.8.103:60020] 
        at org.apache.hadoop.hbase.ipc.HBaseClient.wrapException(HBaseClient.java:1026) 
        at org.apache.hadoop.hbase.ipc.HBaseClient.call(HBaseClient.java:999) 
        at org.apache.hadoop.hbase.ipc.WritableRpcEngine$Invoker.invoke(WritableRpcEngine.java:86) 
        at $Proxy6.multi(Unknown Source) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation$3$1.call(HConnectionManager.java:1433) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation$3$1.call(HConnectionManager.java:1431) 
        at org.apache.hadoop.hbase.client.ServerCallable.withoutRetries(ServerCallable.java:215) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation$3.call(HConnectionManager.java:1440) 
        at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation$3.call(HConnectionManager.java:1428) 
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
        at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
        at java.lang.Thread.run(Thread.java:662) 
Caused by: java.net.SocketTimeoutException: 60000 millis timeout while waiting for channel to be ready for read. ch : java.nio.channels.SocketChannel[connected local=/10.106.8.133:41903 remote=b16-pf-dv-093.abc.com/10.106.8.103:60020] 
        at org.apache.hadoop.net.SocketIOWithTimeout.doIO(SocketIOWithTimeout.java:164) 
        at org.apache.hadoop.net.SocketInputStream.read(SocketInputStream.java:155) 
        at org.apache.hadoop.net.SocketInputStream.read(SocketInputStream.java:128) 
        at java.io.FilterInputStream.read(FilterInputStream.java:116) 
        at org.apache.hadoop.hbase.ipc.HBaseClient$Connection$PingInputStream.read(HBaseClient.java:373) 
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) 
        at java.io.BufferedInputStream.read(BufferedInputStream.java:237) 
        at java.io.DataInputStream.readInt(DataInputStream.java:370) 
        at org.apache.hadoop.hbase.ipc.HBaseClient$Connection.receiveResponse(HBaseClient.java:646) 
        at org.apache.hadoop.hbase.ipc.HBaseClient$Connection.run(HBaseClient.java:580)
4

2 回答 2

10

此处提供的解决方案并非 100% 正确。我在高负载下读写时都遇到了 socketTimeOut。直到或除非在 hbase 服务器上的扫描或写入非常大,否则增加 hbase.rpc.timeout 不是解决方案。

这是我的问题:

我试图扫描 hbase 在几毫秒内返回的行。一切都很正常,直到我将并发扫描线程从 10 个增加到 50 个。通过这样做,我开始遇到 socketTimeoutException(与此线程中的异常相同),这是从一个进程扩展 hbase 读取或写入的障碍。

要找到确切的解决方案,您首先需要先了解原因。

socketTimeout 的原因

一个。从hbase服务器读取或写入返回很慢

湾。客户端无法连接到服务器并超时。线程拥塞?

如果您遇到“a”,那么增加 hbase.rpc.timeout 可能是您的解决方案,但您仍然很可能最终也会遇到“b”。

我注意到默认情况下,hbase 客户端每个 regionServer 只创建一个连接。要验证,请从对 hbase 进行读取的客户端运行此命令。确保负载在运行。

netstat -an | grep 60020 | grep EST

令我惊讶的是,对于每个 regionServer,该进程只建立了一个连接。这解释了超时。只有一个连接/套接字?似乎这是默认的 hbase 客户端行为。还不知道为什么?

解决方案

在客户端的hbase conf中添加这两个属性并重启客户端

<property>
   <name>hbase.client.ipc.pool.type</name>
   <value>RoundRobinPool</value>
</property>
<property>
   <name>hbase.client.ipc.pool.size</name>
   <value>10</value>
</property>

这从每个客户端在每个 regionServer 上创建了 10 个套接字。通过此更改,您应该会在客户端看到重大改进。自此更改以来,我没有遇到过 socketTimeOutException。

于 2016-02-10T19:23:53.720 回答
3

您收到此错误是因为您获取的时间超过了 HBase 客户端应用程序远程调用超时所花费的默认允许时间,即60 seconds。当您的表很大时(这意味着您有更多数据要获取),获取将需要时间。您可以通过在hbase-site.xml文件中将hbase.rpc.timeout的值设置为更高的值来增加此值。

Get 的推荐批量大小是多少?

取决于您的设计、配置、规格、数据和访问模式。

在插入之前检查记录是否存在的最佳方法是什么?

当你想检查某事时,检查是唯一的选择。如果您能详细说明您的用例,那将会很有帮助。这将帮助我提出一些适当的建议。

于 2013-07-29T22:27:10.640 回答