现象:

+----------+-------+--------+-----+-----+-----+----+----+------+---------+-------+--------+--------+------------+
|totalCount|January|February|March|April| May|June|July|August|September|October|November|December|totalMileage|
+----------+-------+--------+-----+-----+-----+----+----+------+---------+-------+--------+--------+------------+
| 33808| 0| 0| 0| 0|33798| 0| 0| 0| 0| 0| 0| 0| 79995.0|
+----------+-------+--------+-----+-----+-----+----+----+------+---------+-------+--------+--------+------------+

当前表预分区10个

按照当月数据看,当前测试表中总数量是:33798

hbase的总数量也是:33798

神奇的地方:使用sparkSQL对接hbase查询的数量是:33808

当时的sql语句是:select count(1) from orderData

很神奇,因为通过sql查询后,总数据多了10条

============================================================

原因:

这里设置了hbase SCAN_BATCHSIZE这个值,会设置scan的batchsize。这个设置的文档是这样说的:

Set the maximum number of values to return for each call to next()

之前一直以为这里是设置一次读取多少行,其实values貌似是读取多少列,并且开启了这个值会导致hbase scan时返回一行的部分结果;

于是将这个设置注释掉,程序即可正常运行

进一步的,我们从hbase端代码看看这个设置。hbase的scan会两个成员变量:

  • private boolean allowPartialResults = false;
  • private int batch = -1;

allowPartialResult这个很明显就是会返回部分结果的设置,那么这个batch呢?setBatch()时并不会设置allowPartialResult。但是在Scan的getResultsToAddToCache()函数中,如果batch值大于0,会设置isBatch=true。之后会有这段代码:

// If the caller has indicated in their scan that they are okay with seeing partial results,
// then simply add all results to the list. Note that since scan batching also returns results
// for a row in pieces we treat batch being set as equivalent to allowing partials. The
// implication of treating batching as equivalent to partial results is that it is possible
// the caller will receive a result back where the number of cells in the result is less than
// the batch size even though it may not be the last group of cells for that row.
if (allowPartials || isBatchSet) {
addResultsToList(resultsToAddToCache, resultsFromServer, ,
(null == resultsFromServer ? : resultsFromServer.length));
return resultsToAddToCache;
}

之前错误代码:

TableInputFormat.SCAN_BATCHSIZE
lazy val buildScan = {

    val hbaseConf = HBaseConfiguration.create()
hbaseConf.set("hbase.zookeeper.quorum", GlobalConfigUtils.hbaseQuorem)
hbaseConf.set(TableInputFormat.INPUT_TABLE, hbaseTableName)
hbaseConf.set(TableInputFormat.SCAN_COLUMNS, queryColumns)
hbaseConf.set(TableInputFormat.SCAN_ROW_START, startRowKey)
hbaseConf.set(TableInputFormat.SCAN_ROW_STOP, endRowKey)
hbaseConf.set(TableInputFormat.SCAN_BATCHSIZE , "")//TODO 此处导致查询数据不一致
hbaseConf.set(TableInputFormat.SCAN_CACHEDROWS , "")
hbaseConf.set(TableInputFormat.SHUFFLE_MAPS , "") val hbaseRdd = sqlContext.sparkContext.newAPIHadoopRDD(
hbaseConf,
classOf[org.apache.hadoop.hbase.mapreduce.TableInputFormat],
classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
classOf[org.apache.hadoop.hbase.client.Result]
) val rs: RDD[Row] = hbaseRdd.map(tuple => tuple._2).map(result => { var values = new ArrayBuffer[Any]()
hbaseTableFields.foreach { field =>
values += Resolver.resolve(field, result)
}
Row.fromSeq(values.toSeq)
})
rs
}

解决:

去掉TableInputFormat.SCAN_BATCHSIZE的设置即可

去掉后的查询结果:

+----------+-------+--------+-----+-----+-----+----+----+------+---------+-------+--------+--------+------------+
|totalCount|January|February|March|April| May|June|July|August|September|October|November|December|totalMileage|
+----------+-------+--------+-----+-----+-----+----+----+------+---------+-------+--------+--------+------------+
| 33798| 0| 0| 0| 0|33798| 0| 0| 0| 0| 0| 0| 0| 79995.0|
+----------+-------+--------+-----+-----+-----+----+----+------+---------+-------+--------+--------+------------+

问题解决~

记一次newApiHadoopRdd查询数据不一致问题的更多相关文章

  1. 记一次ES查询数据突然变为空的问题

    基本环境 elasticsearch版本:6.3.1 客户端环境:kibana 6.3.4.Java8应用程序模块. 其中kibana主要用于数据查询诊断和查阅日志,Java8为主要的客户端,数据插入 ...

  2. MySQL主从复制数据不一致问题【自增主键】

    前言: 今天遇到主从表不一致的情况,很奇怪为什么会出现不一致的情况,因为复制状态一直都是正常的.最后检查出现不一致的数据都是主键,原来是当时初始化数据的时候导致的.现在分析记录下这个问题,避免以后再遇 ...

  3. 使用 JdbcTemplate 查询数据时报错:列名无效(已解决)

    又犯了一个错误. 争取没有下次了. 就算再犯,也要知道去哪找答案. 所以,记录一下,以示警戒. 报错 使用 JdbcTemplate 查询数据时,出现异常: PreparedStatementCall ...

  4. pt-table-checksum检验主从数据不一致

    测试环境:主从架构,操作系统liunx 运行pt-table-checksum需要先安装以下依赖包: yum install perl-IO-Socket-SSL perl-DBD-MySQL per ...

  5. 揭秘MySQL主从数据不一致

    前言: 目前MySQL数据库最常用的是主从架构,大多数高可用架构也是通过主从架构演变而来.但是主从架构运行时间长久后容易出现数据不一致的情况,比如因从库可写造成的误操作或者复制bug等,本篇文章将会详 ...

  6. Redis面试题记录--缓存双写情况下导致数据不一致问题

    转载自:https://blog.csdn.net/lzhcoder/article/details/79469123 https://blog.csdn.net/u013374645/article ...

  7. 由数据迁移至MongoDB导致的数据不一致问题及解决方案

    故事背景 企业现状 2019年年初,我接到了一个神秘电话,电话那头竟然准确的说出了我的昵称:上海小胖. 我想这事情不简单,就回了句:您好,我是小胖,请问您是? "我就是刚刚加了你微信的 xx ...

  8. 三年之久的 etcd3 数据不一致 bug 分析

    问题背景 诡异的 K8S 滚动更新异常 笔者某天收到同事反馈,测试环境中 K8S 集群进行滚动更新发布时未生效.通过 kube-apiserver 查看发现,对应的 Deployment 版本已经是最 ...

  9. 解决Redis中数据不一致问题

    redis系列之数据库与缓存数据一致性解决方案 数据库与缓存读写模式策略写完数据库后是否需要马上更新缓存还是直接删除缓存? (1).如果写数据库的值与更新到缓存值是一样的,不需要经过任何的计算,可以马 ...

随机推荐

  1. sql使用临时表循环

    code CREATE PROCEDURE sp_Update_Blogger_Blog_ArticleCount AS BEGIN declare @account varchar(); --博主账 ...

  2. JS基础_逻辑运算符

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. O025、OpenStack 通用设计思路

    参考https://www.cnblogs.com/CloudMan6/p/5427981.html   API 前端服务   每个OpenStack组件可能包含若干子服务,其中必定有一个API服务负 ...

  4. JQuery --- 第六期 (Ajax)

    欢迎访问我的个人博客,获取更多有用的东西 链接一 链接二 也可以关注我的微信订阅号:CN丶Moti 点击查看Ajax

  5. PHP之50个开源项目

    GitHub上50个最受欢迎的PHP开源项目[2019] 1.Laravel Laravel是一个为Web开发者打造的PHP开发框架. GitHub Stars: 43.5k+ 网址: https:/ ...

  6. var正在声明变量

    var正在声明变量也可以直接分配一个变量,而不在JS中声明它,但是这种变量在默认情况下是全局的.<!-/->是HTML中的注释,在JS中不起作用.它只是用来忽略无法识别脚本的浏览器的脚本内 ...

  7. vue-element-admin 多层路由问题

    在二级页面上添加<router-view> 关于页面打包后三级路由无法访问问题 需要将 存放router-view 的页面单独存放一个文件夹 router.js 写法

  8. layDate面板出现红色花纹图案

    要使用layDate,有两种方法: 1. 要么在引用layui.js和layui.css,然后通过layui.use('laydate', callback) 加载模块后,调用方法使用. 2. 去la ...

  9. 文件浏览:ls&file

    文件浏览主要完成的功能是列出当前目录或指定目录下文件的文件名称以及一些基本的资料. Linux的命令是区分大小写的. 1.  ls:列出当前目录(默认)或指定目录下所有文件,并按字典序排序 语法:ls ...

  10. selenium设置Chrome浏览器不出现通知,设置代理IP

    from selenium import webdriver PROXY = "" chrome_options = webdriver.ChromeOptions() prefs ...