基于HBase的冠字号查询系统1--理论部分
1. 软件版本和部署
maven:3.3.9,jdk:1.7 ,Struts2:2.3.24.1,hibernate:4.3.6,spring:4.2.5,MySQL:5.1.34,Junit:4,Myeclipse:2014;
Hadoop2.6.4,HBase1.1.2
源码下载:https://github.com/fansy1990/ssh_v3/releases
部署参考:http://blog.csdn.net/fansy1990/article/details/51356583
数据下载:http://download.csdn.net/detail/fansy1990/9540865 或 http://pan.baidu.com/s/1dEVeJz7
2. 背景&思路
本系统就是使用客观的方法来验证伪钞。本系统采用的方案是基于冠字号的,每张人民币的冠字号是唯一的,如果有一个大表可以把所有的人民币以及人民币对应的操作(在什么时间、什么地点存入或获取)记录下来,这样在进行存取时就可以根据冠字号先查询一下,看当前冠字号对应的纸币在大表中的保存的情况,这样就可以确定当前冠字号对应的纸币是否是伪钞了(这里假设在大表中的所有冠字号对应的钞票都是真钞)。
下面对应存储场景:
存/取 |
最近状态(表中有无) |
真钞/伪钞 |
|
场景1 |
存 |
有 |
伪钞 |
场景2 |
存 |
无 |
真钞 |
场景3 |
取 |
有(此时没有无状态) |
真钞 |
目前,基于传统数据库存储数据一般在千万级别(受限于查询等性能),但是如果要存储所有钞票的信息以及其被存储或获取的记录信息,那么传统数据库肯定是不能胜任的。所以本系统是基于HBase的。
3. 功能指标
Ø 存储万级用户信息;
Ø 存储百万级别钞票信息;
Ø 支持前端业务每秒500+实时查询请求;
Ø 数据存储和计算能够可扩展;
Ø 提供统一接口,支持前端相关查询业务;
4. 架构
Ø 数据层:包括基础数据MySQL、文档、Web数据等;
Ø 数据处理层:主要是数据的加载,包括MR加载方式、Java API加载模式、Sqoop加载模式等;
Ø 数据存储层:主要是HBase存储,包括钞票的所有信息以及用户信息等;
Ø 数据服务层:主要是对外提供查询、存储等接口服务;
Ø 数据应用层:存取钞系统,在存钞时设计到伪钞识别;其他应用系统;
5. 表设计
5.1原始数据:
5.2冠字号记录
create 'records',{NAME=>'info',VERSIONS=>1000},SPLITS =>['AAAM9999','AAAZ9999','AABM9999']
表结构描述如下:
主键/列簇 |
字段名称 |
字段含义 |
字段值举例 |
备注 |
rowkey |
- |
表主键(钞票冠字号) |
AAAA0000 |
|
timestamp |
- |
时间戳 |
1414939140000 |
long型(可以存储用户操作的时间) |
info |
- |
列簇 |
- |
who、when、where做了哪些操作 |
exist |
是否存在 |
1 |
如果用户是存储行为,那么在行为结束后,该值为1 |
|
uid |
用户ID |
4113281991XXXX9919 |
||
bank |
存取钞银行 |
SPDBCNSH |
银行编号 |
5.3用户信息
create 'user',{NAME=>'info'},SPLITS =>['4113281990XXXX0000','4113281991XXXX0000','4113281992XXXX0000']
表结构描述如下:
主键/列簇 |
字段名称 |
字段含义 |
字段值举例 |
备注 |
Rowkey |
- |
用户主键(身份证号) |
4113281991XXXX9919 |
|
Timestamp |
- |
时间戳 |
1414939140000 |
long型 |
info |
- |
列簇 |
- |
用户信息 |
name |
用户名 |
JACO |
||
gender |
用户性别 |
femail |
||
bank |
用户注册银行 |
SPDBCNSH |
银行编号 |
|
address |
用户住址 |
EXX-O94-1319151759 |
||
birthday |
用户出生年月 |
1981-10-20 09:12 |
6. 数据加载
系统在投入使用的时候,已经存在历史数据,需要把历史数据批量导入到系统中;在人民币首次发行时,也需要批量导入系统中。这里的导入直接使用MR导入。
6.1 主类:
package ssh.mr;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.util.Tool;import ssh.util.HadoopUtils;/*** Job Driver驱动类* * @author fansy* */
public class ImportToHBase extends Configured implements Tool {public static final String SPLITTER = "SPLITTER";public static final String COLSFAMILY = "COLSFAMILY";public static final String DATEFORMAT = "DATEFORMAT";@Overridepublic int run(String[] args) throws Exception {if (args.length != 5) {System.err.println("Usage:\n demo.job.ImportToHBase <input> <tableName> <splitter> <rk,ts,col1:q1,col2:q1,col2:q2> <date_format>");return -1;}if (args[3] == null || args[3].length() < 1) {System.err.println("column family can't be null!");return -1;}Configuration conf = getConf();conf.set(SPLITTER, args[2]);conf.set(COLSFAMILY, args[3]);conf.set(DATEFORMAT, args[4]);TableName tableName = TableName.valueOf(args[1]);Path inputDir = new Path(args[0]);String jobName = "Import to " + tableName.getNameAsString();Job job = Job.getInstance(conf, jobName);job.setJarByClass(ImportMapper.class);FileInputFormat.setInputPaths(job, inputDir);job.setInputFormatClass(TextInputFormat.class);job.setMapperClass(ImportMapper.class);TableMapReduceUtil.initTableReducerJob(tableName.getNameAsString(),null, job);job.setNumReduceTasks(0);HadoopUtils.setCurrJob(job);// 设置外部静态Jobreturn job.waitForCompletion(true) ? 0 : 1;}}
主类的run方法中使用的是传统的MR导入HBase的代码,只是设置了额外的参数,这里主类参数意思解释如下:
6.2 Mapper:
package ssh.mr;import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;/*** Mapper类,接收HDFS数据,写入到HBase表中* @author fansy**/
public class ImportMapper extends Mapper<LongWritable, Text, ImmutableBytesWritable, Put>{private static final String COMMA = ",";private static final String COLON=":";private String splitter = null;
// private String colsStr = null;private int rkIndex =0; // rowkey 下标private int tsIndex =1; // timestamp下标private boolean hasTs = false; // 原始数据是否有timestampprivate SimpleDateFormat sf = null;private ArrayList<byte[][]> colsFamily= null;private Put put =null;ImmutableBytesWritable rowkey = new ImmutableBytesWritable();@Overrideprotected void setup(Mapper<LongWritable, Text, ImmutableBytesWritable, Put>.Context context)throws IOException, InterruptedException {splitter = context.getConfiguration().get(ImportToHBase.SPLITTER,",");String colsStr = context.getConfiguration().get(ImportToHBase.COLSFAMILY,null);sf = context.getConfiguration().get(ImportToHBase.DATEFORMAT,null)==null? new SimpleDateFormat("yyyy-MM-dd HH:mm"):new SimpleDateFormat(context.getConfiguration().get(ImportToHBase.DATEFORMAT));String[] cols = colsStr.split(COMMA, -1);colsFamily =new ArrayList<>();for(int i=0;i< cols.length;i++){if("rk".equals(cols[i])){rkIndex= i;colsFamily.add(null);continue;}if("ts".equals(cols[i])){tsIndex = i;colsFamily.add(null);hasTs = true; // 原始数据包括tscontinue;}colsFamily.add(getCol(cols[i]));}}/*** 获取 family:qualifier byte数组* @param col* @return*/private byte[][] getCol(String col) {byte[][] fam_qua = new byte[2][];String[] fam_quaStr = col.split(COLON, -1);fam_qua[0]= Bytes.toBytes(fam_quaStr[0]);fam_qua[1]= Bytes.toBytes(fam_quaStr[1]);return fam_qua;}@Overrideprotected void map(LongWritable key, Text value,Mapper<LongWritable, Text, ImmutableBytesWritable, Put>.Context context)throws IOException, InterruptedException {String[] words = value.toString().split(splitter, -1);if(words.length!=colsFamily.size()){System.out.println("line:"+value.toString()+" does not compatible!");return ;}rowkey.set(getRowKey(words[rkIndex]));put = getValue(words,colsFamily,rowkey.copyBytes());context.write(rowkey, put);}/*** 获取Put值* @param words* @param colsFamily* @param bs* @return*/private Put getValue(String[] words, ArrayList<byte[][]> colsFamily, byte[] bs) {Put put = new Put(bs);for(int i=0;i<colsFamily.size();i++){if(colsFamily.get(i)==null){// rk 或tscontinue;// 下一个 列}if(words[i]==null || words[i].length()==0) {// 不添加,直接往下一个valuecontinue;}// 日期异常的记录同样添加if(hasTs){// 插入包含时间的数据put.addColumn(colsFamily.get(i)[0], colsFamily.get(i)[1],getLongFromDate(words[tsIndex]), Bytes.toBytes(words[i]));}else{// 不包含时间的数据put.addColumn(colsFamily.get(i)[0], colsFamily.get(i)[1],Bytes.toBytes(words[i]));}}return put;}private long getLongFromDate(String dateStr) {try{return sf.parse(dateStr).getTime();}catch(ParseException e){System.out.println(dateStr+" 转换失败!");return 0;}}/*** 获取rowkey byte数组* @param rowKey* @return*/private byte[] getRowKey(String rowKey) {return Bytes.toBytes(rowKey);}}
Mapper是整个流程的核心,主要负责进行数据解析、并从HDFS导入到HBase表中的工作,其各个部分功能如下:
Ø setup():获取输入数据字段分隔符,获取列簇、列名,获取rowkey列标,获取ts格式及列标(如果没有的话,就按照插入数据的时间设置);
Ø map():解析、过滤并提取数据(需要的字段数据),生成Put对象,写入HBase;
6.3 针对records,user MR导入:
7. 实时数据加载
使用Java API来操作HBase数据库,完成实时HBase数据库更新,包括冠字号查询、存取款等功能。
分享,成长,快乐
脚踏实地,专注
转载请注明blog地址:http://blog.csdn.net/fansy1990
基于HBase的冠字号查询系统1--理论部分相关推荐
- 基于HBase的冠字号查询系统2--实现部分
1. 软件版本和部署 maven:3.3.9,jdk:1.7 ,Struts2:2.3.24.1,hibernate:4.3.6,spring:4.2.5,MySQL:5.1.34,Junit:4,M ...
- 26个数据分析案例——第一站:基于Python的HBase冠字号查询系统
26个数据分析案例--第一站:基于Python的HBase冠字号查询系统 实验所需环境 • Python: Python 3.x: • Hadoop 2.7.7环境: • HBase 1.3.5: 数 ...
- 冠字号查询系统中HBase写入数据性能测试
机器说明:4台centos虚拟机,每台分别配置2G内存 测试步骤: 为了方便测试,利用hbase shell新建表如下: create 'identify01', {NAME => 'op_ww ...
- HBase冠字号查询系统(实训报告)
1. 实训目的 • 了解HBase的相关知识: • 熟悉HBase相关指令以及HBase过滤器的使用: • 掌握HBase数据导入与备份方法的使用以及性能优化的实现: • 具有实现冠字号查询的能力. ...
- 基于JAVA的城市公交查询系统毕业论文(含源文件)
获取项目源文件,学习交流联系Q:1225467431 摘要:公交查询系统是城市道路交通的重要组成部分,是城市发展的必然产物,是联系国民生活.社会生产和流通领域的关键环节.安阳城市公交查询系统的发展处于 ...
- 基于JAVA的城市公交查询系统毕业论文
欢迎添加微信互相交流学习哦! 项目源码:https://gitee.com/oklongmm/biye2 摘要:公交查询系统是城市道路交通的重要组成部分,是城市发展的必然产物,是联系国民生活.社会生产 ...
- 基于html5的城市公交查询系统,基于WEB的智能公交查询系统的研究与设计
摘要: 我国城市公交查询系统的发展处于一个较落后的水平,广大乘客可以获得信息的方式很少,为了解决这种问题,加快发展城市公交信息化,设计了这个城市公交出行线路查询系统.公交换乘查询系统是MAS技术和We ...
- 基于Android的app公交查询论文,基于Android平台的公交查询系统的设计与实现.doc
摘要:本系统是在Android开发平台上,基于百度地图API实现的.解决的问题是随着城市的不断扩增,所导致的盐城市公交信息不能有效分享的情况.现在人们出行时的选择越来越多,但是公交仍然是大部分市民的首 ...
- java 城市公交查询系统源码_基于Java的城市公交查询系统的毕业设计参考源码
资料介绍 一.实现多种查询功能,包括根据商厦名称.公交车号.日常站点.和任意两个站点查询乘车路线.其次,采用最短路径算法查找任意两个站点之间的最短乘车路线.最后,提供了用户留言的功能.用户管理功能和后 ...
最新文章
- Docker是世界上最牛逼的CaaS!
- $_FILES上传错误类型
- Epox 8RDA3G主板奇怪的问题
- Windows Mobile中实现统计图形的绘制(C#版,柱状图)
- 微信加入新功能,60秒语音不必从头听到尾,网友:还需要进度条
- 西数480G绿盘SSD搬板,SM2258xt开卡成功,附量产工具
- 将数字转为中文金额的大写方式(C++版)
- AI-ISP,是噱头还是真能解决问题
- ios 清理缓存功能实现
- 第一次滑雪小记——杭州临安大明山滑雪场
- 商场楼层地图怎么制作,高效、便捷的商场二三维地图绘制平台
- Octave是什么,以及Octave online的使用(相当于open source的matlab)
- computed,watch
- Newifi mini路由器刷华硕Padavan固件及无线中继笔记
- centos7.9中mysql5.6数据库安装和配置以及修改端口
- Xiaojie雷达之路---TI实战笔记---BPM MIMO
- nyoj166-小珂的数学题
- python实现监控URL的一个值小于规定的值--邮件报警
- 【转】国内大学图书馆网址
- 关于ISCC2013的思路整理
热门文章
- CF1311C. Perform the Combo题解
- POJ 1985 Cow Marathon
- [HDU6566]The Hanged Man
- Hibernate通常是三种:hql查询,QBC查询和QBE查询:
- Windows上搭建rtsp-simple-server流媒体服务器实现rtsp、rtmp等推流以及转流、前端html与Vue中播放hls(m3u8)视频流
- Tcl 字典转换为json格式 dict2json
- 2020年最新Python学习路线及学习目标规划 拿走不谢!
- A Practical Guide to Quantitative Finance Interviews
- mysql建表Rferencing column ‘‘ and referenced column ‘ in foreign key constraint ‘‘ are incompatible.
- 核心单词课--补充记录