现象:

+----------+-------+--------+-----+-----+-----+----+----+------+---------+-------+--------+--------+------------+
|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. js变量声明提升

    1.变量提升 根据javascript的运行机制和javascript没有块级作用域这个特点,可以得出,变量会声明提升移至作用域 scope (全局域或者当前函数作用域) 顶部的. 变量声明提升至全局 ...

  2. Js中去除数组中重复元素的6种方法

    方法一: Array.prototype.method1 = function(){ var arr=[]; //定义一个临时数组 for(var i = 0; i < this.length; ...

  3. 仍然有人在叫喊C语言已经过时了

    现在,仍然有人在叫喊C语言已经过时了.还有什么值得学习的?看看现在使用Python.PHP和其他语言有多简单.谁去学旧的C语言?是真的吗?作者下载了这两种语言的底层源代码.由于空间的限制,它没有分析框 ...

  4. Gephi简单导入数据

    使用工具 Gephi-0.9.2 事前要导入的数据 Node.csv 节点:名称可以所以定,格式.csv Edge.csv 边:名称可以所以定,格式.csv 导入操作 新建项目 导入节点 新建列要与表 ...

  5. ueditor 去掉自动跟随内容的<p><br /></p>

    //编辑器不能为空内容 if (domUtils.isEmptyNode(me.body)) { me.body.innerHTML = ''; ueditor.all.js  删除BR 如果还不行, ...

  6. JDBC及PreparedStatement防SQL注入

    概述 JDBC在我们学习J2EE的时候已经接触到了,但是仅是照搬步骤书写,其中的PreparedStatement防sql注入原理也是一知半解,然后就想回头查资料及敲测试代码探索一下.再有就是我们在项 ...

  7. spring JdbcTemplate如何返回多个结果集

    最近很少发博客,先是去了***公司呆了几年,完全不能上外网,后来又出来了,能上外网了,但项目太忙一直在打码,用的语言也从C#换成了JAVA. 好在两者比较相似,转起来还算方便,近日在操作sqlserv ...

  8. 如何在国内跑Kubernetes的minikube

    跑minikube start老是被卡住,得到如以下的结果 minikube start --registry-mirror=https://registry.docker-cn.com miniku ...

  9. css 模块化

    什么是css模块化思想?(what) 为了理解css模块化思想,我们首先了解下,什么是模块化,在百度百科上的解释是,在系统的结构中,模块是可组合.分解和更换的单元.模块化是一种处理复杂系统分解成为更好 ...

  10. thinkphp方法success和error跳转时间以及返回ajax

    Action类的success和error方法第三个参数为数字时候,表示指定页面跳转时间,例如: $,); $,); 如果是ajax跳转 必须用true: $this->success('操作成 ...