hbase scan数据缓慢,server端出现LeaseException。hbase写入缓慢。
直接原因是:
?
而根本原因在于单个查询请求在server端处理时间过长,经过检查,发现是因为该scan带有一个会把绝大多数数据过滤掉的filter,导致hbase扫描了几百万条数据也没能拿到指定数量(scan的caching)的数据。
?
这和全表扫描还不一样。由于有查询缓存,即使是全表扫描,server端在拿到满足缓存需求的数据之后就会返回结果,实际上单个请求并不会扫描整张表。
?
?
网上有些朋友给出的意见是增大hbase.regionserver.lease.period以减少LeaseException,这我是同意的。
?
还有的意见是减小hbase.rpc.timeout,这样client端就能很快得到反馈。这样用户体验确实好了一点,但并没有实际解决问题。。。server端的查询实际上还在跑啊!handler还是没有释放啊!况且一直抛timeout exception给client也不是办法,这个请求永远没有办法处理。
?
我们给出的解决方案是,用RandomRowFilter。
?
FilterList filterList = new FilterList(Operator.MUST_PASS_ONE); // RandomRowFilter must on the first of the FilterList filterList.addFilter(new RandomRowFilter(0.01F)); filterList.addFilter(...);//add other filters Scan scan = new Scan(); scan.setFilter(filterList);
?
它的原理很简单,hbase每扫描过一条记录,就会生成一个随机数,如果这个随机数小于某个阈值,就终止这次查询并返回已经查询到的结果。那么这个阈值如何定义呢?
?
Random random = new Random(); boolean filterOutRow = !(random.nextFloat() < chance);
?
这个chance就是阈值,也就是上面例子中的构造参数0.01F。因此你可以根据需要设定chance的大小,来控制扫描的最大记录数。
?
因此假设我们设chance=0.01F,在Scan的时候即使使用了一个很糟糕的filter,server端在扫描了100条记录(数字非确定,以下会说明)后就会终止,并返回当前扫描到的记录,如果需要继续进行查询,使用当前记录的rowkey作为startkey再发起一次查询请求即可。
?
?
但有几点需要注意:
?
?
原文:http://kane-xie.iteye.com/blog/2223428