1. 背景描述

目前在做音乐推荐项目,前期做排序模型优化,任务是使用模型对用户的历史音乐进行排序,有6800多万个用户,约40G的用户数据,使用HBase作为数据仓库。

利用HBase可以存储多个版本数据的特性,数据运算完后入库时,将用户id作为rowkeysongInfo:songid的值为歌曲id,使用自定义时间戳,将排序模型输出的歌曲得分(分值越高)作为时间戳。因为HBase数据存储默按照时间戳降序存储,这样只要取出用户的songInfo:songid的所有版本的值就能获取该用户的历史音乐经过模型排序后的顺序。

2. 问题描述

每次数据入库时,使用oozie进行任务调度,先使用truncate命令将原表数据清空,然后根据用户日志进行计算后入库。也就是不管用户的历史音乐数据是否有发生改变,都将HBase中的用户数据删除,根据数据统计,每天的活动用户约为20w占总用户的1/340,换句话说,对339/340的用户进行了没有必要的重复计算,因为他们的历史数据没有发生改变。如果能使用增量入库的方式,只获取活跃用户的日志数据进行计算并入库,可以大大节约资源。

3. 解决方案

3.1 直接删除行数据

最直接的想法是,直接在入库前增加删除语句就行,拿到日志有变化的用户后,删除用户数据,然后入库。所以直接新增了以下语句

Delete delete = new Delete(Bytes.toBytes(StringUtils.trimWhite(userid)));

table.delete(delete);

查看最后的入库结果,入库失败,只入了几百条数据,而且根本不是想要的效果。

3.2 删除自定义时间戳的行数据

Delete对象在删除前没限制删除的列簇和时间戳,就是删除了该rowkey所对应的所有列簇的所有字段,所以删除数据的操作没问题,可是入库的代码没有改动,之前入库没有问题。继续了解HBase删除机制后找到了原因。

其实问题出在了自定义时间戳上。在入库的时间戳是根据模型计算出来的,远小于当前的时间的时间戳,而删除的时候没有指定时间戳,HBase会默认使用服务器生成的当前时间的时间戳。而HBase的删除操作并不是真正的删除,可以看成是含有Delete标记的特殊put,只是先给数据打上标记,时间戳小于这个删除时间的数据在下一次major compaction的时候才被真正的删除。由于删除后入库的数据使用的是自定义时间戳且远小于当前时间的时间戳,所以导致了入库的数据被HBase删除了。

自定义时间戳远小于删除时自动生成的时间戳,按理来说最后入库结果应该一条数据都没有(因为小于删除时间戳的数据都被删除了),但为什么最后还是入了几百条的数据呢? 推测原因是因为在最后数据的put过程中发生了major compaction,HBase进行了真正的删除,删除数据后Delete标记也失效了,所以后面的put操作才会真正生效。

既然问题定位到了时间戳,那就在删除的时候指定时间戳,还是使用自定的时间戳,但是不直接使用模型生成的分值,而是把歌曲按分值升序排序后从1开始编号,将 删除时的时间戳+歌曲编号 作为入库时的时间戳。在删除的时候直接指定删除时间戳为当前的时间戳,这样之前的用户数据就会被删除,而新入库的数据时间戳大于被删除的时间戳,就会被保留。关键代码如下:


long offset = new Date().getTime();
//判断该用户是否存在
Get get = new Get(Bytes.toBytes(StringUtils.trimWhite(userid)));
get.addColumn(Bytes.toBytes(columnFamily),Bytes.toBytes("songID"));
get.setMaxVersions(1);
Result result = table.get(get);
//System.out.println("这是result.rawCells()前的result对象"+result.toString());
if (!result.isEmpty()) {
//KeyValue[] kV = result.raw();
//offset = kV[0].getTimestamp();
//System.out.println("获取的最新时间戳为: "+offset);
//offset = result.rawCells()[0].getTimestamp(); //报错找不到该方法,可能是hbase版本太低
//删除之前的数据
Delete delete = new Delete(Bytes.toBytes(StringUtils.trimWhite(userid)));
delete.deleteFamily(Bytes.toBytes(columnFamily),offset);
table.delete(delete);
}

参考文章:

[1] hbase时间戳修改带来的问题总结

[2] HBase中数据的多版本特性潜在的意外

实现HBase增量入库(HBase删除自定义时间戳行数据)的更多相关文章

  1. c# js 删除table原行数据

    function addtreetotable(obj){ var table1 =  document.getElementById("Table1"); var hang =  ...

  2. 一个将当前目录下HEX文件的第一行数据删除的程序

    为什么要写这样一个函数 在使用SoftConsole开发M3程序时,生成的hex文件,必须要把第一行数据删除,才能在Libero中使用,所以写了这个小工具,这是2.0版本了,第一版是直接删除第一行数据 ...

  3. Mac 下用IDEA时maven,ant打包 (mr 入库hbase)

    现在非常喜欢IDEA,之前在mac 上用的eclipse 经常出现无缘无故的错误.所以转为IDEA.  不过新工具需要学习成本,手头上的项目就遇到了很多问题,现列举如下: 背景描述 在hadoop 开 ...

  4. Hbase框架原理及相关的知识点理解、Hbase访问MapReduce、Hbase访问Java API、Hbase shell及Hbase性能优化总结

    转自:http://blog.csdn.net/zhongwen7710/article/details/39577431 本blog的内容包含: 第一部分:Hbase框架原理理解 第二部分:Hbas ...

  5. HBase之六:HBase的RowKey设计

    数据模型 我们可以将一个表想象成一个大的映射关系,通过行健.行健+时间戳或行键+列(列族:列修饰符),就可以定位特定数据,Hbase是稀疏存储数据的,因此某些列可以是空白的, Row Key Time ...

  6. HBase 1、HBase介绍和工作原理

    HBase是一个分布式的.面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”.就像Bigtable利用了Google文件 ...

  7. HBase学习——3.HBase表设计

    1.建表高级属性 建表过程中常用的shell命令 1.1 BLOOMFILTER 默认是 NONE 是否使用布隆过虑及使用何种方式,布隆过滤可以每列族单独启用 使用HColumnDescriptor. ...

  8. 大数据技术之_11_HBase学习_01_HBase 简介+HBase 安装+HBase Shell 操作+HBase 数据结构+HBase 原理

    第1章 HBase 简介1.1 什么是 HBase1.2 HBase 特点1.3 HBase 架构1.3 HBase 中的角色1.3.1 HMaster1.3.2 RegionServer1.3.3 ...

  9. Hbase之三:Hbase Shell使用入门

    HBase 为用户提供了一个非常方便的使用方式, 我们称之为“HBase Shell”.HBase Shell 提供了大多数的 HBase 命令, 通过 HBase Shell 用户可以方便地创建.删 ...

随机推荐

  1. 客户端链接Blog

    Word 2013链接Blog 1.设置共享->发布至博客->发布至博客 2.新建博客账户 3.添加新建账户信息 注意:URL内为Blog名,而非用户名 a) 在"Type of ...

  2. Linux下各文件夹的含义和用途

    Linux根目录”/“下各个系统文件夹的含义和用途 1./boot 该目录默认下存放的是Linux的启动文件和内核. 2./initrd 它的英文含义是boot loader initialized ...

  3. Django 之 富文本编辑器-tinymce

    这里的富文本编辑器以 tinymce 为例. 环境:ubuntu 16.04 + django 1.10 + python 2.7 ubuntu安装tinymce: python 2.7 $ sudo ...

  4. springboot整合mybatis增删改查(四):完善增删改查及整合swgger2

    接下来就是完成增删改查的功能了,首先在config包下配置Druid数据连接池,在配置之前先把相关配置在application.preperties中完善 application.preperties ...

  5. 离散数学:用C语言来判断集合存在的二元关系

    用C语言来判断是否满足自反,反自反,非自反,对称,反对称,非对称和传递性 也不知道写的对不对.没有大量验证,但是随便找的一些关系测试的没毛病,如果错了,欢迎各位大佬留言 #include<bit ...

  6. test20181024 qu

    题意 分析 极似UVa11995 I Can Guess the Data Structure! 模拟即可,时间复杂度(--)\(O(n \log n)\) 旁边的L君:这题有两个坑点,我被卡了一次. ...

  7. python 之 collections

    Python作为一个“内置电池”的编程语言,标准库里面拥有非常多好用的模块.比如今天想给大家 介绍的 collections 就是一个非常好的例子. 基本介绍 我们都知道,Python拥有一些内置的数 ...

  8. OPENQUERY用法以及使用需要注意的地方

    对给定的链接服务器执行指定的传递查询.该服务器是 OLE DB 数据源.OPENQUERY 可以在查询的 FROM 子句中引用,就好象它是一个表名.OPENQUERY 也可以作为 INSERT.UPD ...

  9. Windows 2008 关闭远程桌面的单用户多会话模式

    Windows 2008 关闭远程桌面的单用户多会话模式 在腾讯云上购买了一台云服务器. 因为设置了自动登录,在远程桌面连接后会启动一个新的会话,然后软件被运行了两次,端口被占用,无法起动. 还有可能 ...

  10. 【记录】MVC4中使用SignalR

    前言 周末在偶尔翻阅微软官网的时候看到Getting Started with SignalR and MVC 4此篇文章,知道了signalr这个东西,貌似这个出来很长时间了,奈何自己一直没有发现, ...