一、合并

  1. 由于每次对数据操作一次,都会生成一个hfile文件,hdfs端会在空闲时间,把多个hfile文件进行合并。

  2. 最后,如果合并之后,多个region中的数据分配的不合理,会自动的合并region。由于合并region销号很多资源,所以一般手动合并region。

1.1region的拆分

  1. 建表的时候预分region,根据rowkey合理设计
  1. create a ,’cf’,SPLITS=>[‘’,’’,’’]
  2. //java
  3. createTable(table,参数二二维字节数组)
  1. 自动进行大小拆分
  1. 1 没有预分region的表初始1region
  2. 2 随着数据的插入越来越多,region管理的数据行数越来越多
  3. 3 256M的时候会有1region拆分成2
  4. 4 再次拆分,2G的时候再拆分
  5. 5 再次拆分,6.75的时候再拆分
  6. 6 再次拆分,10G的时候再拆分
  7. 7 以后都是10G
  1. 拆分策略
  1. 1. 默认大小拆分
  2. 2. 根据rowkey前缀拆分
  3. 3. 切割符
  4. 4. 手动强制拆分

1.2 region的合并

hfile文件的合并

HBASE4 - 图1

  1. 由于每次对文件操作都会生成一个hfile文件,所以hdfs会在空闲时间依次合并这些小的hfile文件。
  2. 注意在memorystore中,如果有对数据有多个操作,如果有墓被标记,delete就不会读前面的数据,直接删除

region的合并

region合并,当大量的删除,大量的数据过期 , region管理的数据行数大大减少的时候就会合并

二、rowkey的设计

rowkey的作用

  1. 数据的排序维度

  2. 行的唯一标识

  3. 索引创建

  4. 布隆过滤器创建

  5. hbaseKV的数据库 rowkey

如何合理的设计rowkey

  1. 根据数据特点和业务特点设计
  2. 优先避免热点问题
  3. 优先考虑频次最高的作为查询维度
  4. rowkey的长度不能太长,因为有冗余

还可以多维度查询

HBASE4 - 图2

案例

在已经创建好movie为rowkey的情况下,查询某个UID对应的信息

思路:创建两个表。

HBASE4 - 图3

三、电影案例

  1. 创建tb_movie表,列族为info
  2. 写MR程序,加载json文件,编写MR程序,生成静态hfile并写入到tb_movie中
  1. package com._51doit.hbase.day04;
  2. import com.google.gson.Gson;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.apache.hadoop.conf.Configuration;
  5. import org.apache.hadoop.fs.Path;
  6. import org.apache.hadoop.hbase.HBaseConfiguration;
  7. import org.apache.hadoop.hbase.client.Put;
  8. import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
  9. import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
  10. import org.apache.hadoop.hbase.mapreduce.TableReducer;
  11. import org.apache.hadoop.hbase.util.Bytes;
  12. import org.apache.hadoop.io.LongWritable;
  13. import org.apache.hadoop.io.NullWritable;
  14. import org.apache.hadoop.io.Text;
  15. import org.apache.hadoop.mapreduce.Job;
  16. import org.apache.hadoop.mapreduce.Mapper;
  17. import org.apache.hadoop.mapreduce.Reducer;
  18. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  19. import java.io.IOException;
  20. /**
  21. * Author: Hang.Z
  22. * Date: 21/07/05
  23. * Description:把电影的json数据加载到HBASE的'tb_movie'表中
  24. map
  25. 生成rk
  26. write(rk,mb)
  27. reduce
  28. 定义put类
  29. 将mb的各个属性写入到表的单元格中
  30. */
  31. public class LoadData2Hbase {
  32. // mapper
  33. static class LoadData2HbaseMapper extends Mapper<LongWritable, Text,Text,MovieWritable> {
  34. Gson gson = new Gson();
  35. Text k = new Text() ;
  36. @Override
  37. protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
  38. try {
  39. String line = value.toString();
  40. //将每行内容转换成Java类
  41. MovieWritable mb = gson.fromJson(line, MovieWritable.class);
  42. String mid = mb.getMovie(); //47 --> 00047
  43. String timeStamp = mb.getTimeStamp();
  44. //设计好rowkey , rowkey作为Key输出
  45. String padMid = StringUtils.leftPad(mid, 5, '0');
  46. String padTime = StringUtils.leftPad(timeStamp, 10, '0');
  47. // 固定长度 唯一
  48. String rk = padMid+"_"+padTime;
  49. k.set(rk);
  50. context.write(k,mb);
  51. }catch (Exception e){
  52. }
  53. }
  54. }
  55. //reduce
  56. static class LoadData2HbaseReducer extends TableReducer<Text,MovieWritable,ImmutableBytesWritable>{
  57. @Override
  58. protected void reduce(Text key, Iterable<MovieWritable> values, Context context) throws IOException, InterruptedException {
  59. // key就是行键 唯一
  60. String rowkey = key.toString();
  61. //创建put添加单元格
  62. Put put = new Put(rowkey.getBytes());
  63. // 当前的电影记录
  64. MovieWritable movie = values.iterator().next(); // 四个属性 , 四个单元格
  65. // 添加单元格
  66. put.addColumn("info".getBytes() , "movie".getBytes() , Bytes.toBytes(movie.getMovie())) ;
  67. put.addColumn("info".getBytes() , "rate".getBytes() , Bytes.toBytes(movie.getRate())) ;
  68. put.addColumn("info".getBytes() , "timeStamp".getBytes() , Bytes.toBytes(movie.getTimeStamp())) ;
  69. put.addColumn("info".getBytes() , "uid".getBytes() , Bytes.toBytes(movie.getUid())) ;
  70. //输出数据
  71. context.write(null,put);
  72. }
  73. }
  74. public static void main(String[] args) throws Exception {
  75. Configuration conf = HBaseConfiguration.create();
  76. // zookeeper
  77. conf.set("hbase.zookeeper.quorum","linux01:2181,linux02:2181,linux03:2181");
  78. Job job = Job.getInstance(conf, "loadData");
  79. job.setMapperClass(LoadData2HbaseMapper.class) ;
  80. job.setMapOutputKeyClass(Text.class);
  81. job.setMapOutputValueClass(MovieWritable.class);
  82. // 数据的位置
  83. FileInputFormat.setInputPaths(job,new Path("D:\\mrdata\\movie\\input"));
  84. //表格reduce的设置
  85. TableMapReduceUtil.initTableReducerJob("tb_movie",LoadData2HbaseReducer.class ,job);
  86. job.waitForCompletion(true) ;
  87. }
  88. }

movebean类

  1. package com._51doit.hbase.day04;
  2. import org.apache.hadoop.io.Writable;
  3. import java.io.DataInput;
  4. import java.io.DataOutput;
  5. import java.io.IOException;
  6. import java.io.Serializable;
  7. /**
  8. * Author: Hang.Z
  9. * Date: 21/06/23
  10. * Description:
  11. * {"movie":"2288","rate":"4","timeStamp":"978160616","uid":"17"}
  12. * 这个类要放在Map端的VALUE的位置输出 序列化
  13. * 序列化本质
  14. * 内存对象--->二进制 写
  15. * 二进制--->内存对象 读
  16. */
  17. public class MovieWritable implements Writable {
  18. private String movie ;
  19. private double rate ;
  20. private String timeStamp ;
  21. private String uid ;
  22. public String getMovie() {
  23. return movie;
  24. }
  25. public void setMovie(String movie) {
  26. this.movie = movie;
  27. }
  28. public double getRate() {
  29. return rate;
  30. }
  31. public void setRate(double rate) {
  32. this.rate = rate;
  33. }
  34. public String getTimeStamp() {
  35. return timeStamp;
  36. }
  37. public void setTimeStamp(String timeStamp) {
  38. this.timeStamp = timeStamp;
  39. }
  40. public String getUid() {
  41. return uid;
  42. }
  43. public void setUid(String uid) {
  44. this.uid = uid;
  45. }
  46. @Override
  47. public String toString() {
  48. return "MovieWritable{" +
  49. "movie='" + movie + '\'' +
  50. ", rate=" + rate +
  51. ", timeStamp='" + timeStamp + '\'' +
  52. ", uid='" + uid + '\'' +
  53. '}';
  54. }
  55. // 序列化
  56. public void write(DataOutput dataOutput) throws IOException {
  57. dataOutput.writeUTF(movie);
  58. dataOutput.writeDouble(rate);
  59. dataOutput.writeUTF(timeStamp);
  60. dataOutput.writeUTF(uid);
  61. }
  62. // 反序列化
  63. public void readFields(DataInput dataInput) throws IOException {
  64. movie = dataInput.readUTF();
  65. rate = dataInput.readDouble() ;
  66. timeStamp = dataInput.readUTF() ;
  67. uid = dataInput.readUTF() ;
  68. }
  69. }

四、过滤器

  1. package com._51doit.hbase.day04.filter;
  2. import com._51doit.hbase.day02.HbaseUtils;
  3. import org.apache.hadoop.hbase.CompareOperator;
  4. import org.apache.hadoop.hbase.TableName;
  5. import org.apache.hadoop.hbase.client.*;
  6. import org.apache.hadoop.hbase.filter.RowFilter;
  7. import org.apache.hadoop.hbase.filter.SubstringComparator;
  8. /**
  9. * Author: Hang.Z
  10. * Date: 21/07/05
  11. * Description:
  12. * 获取数据的时候 可以使用过滤器过滤数据
  13. * Get
  14. * Scan
  15. */
  16. public class Filter01_Demo1 {
  17. public static void main(String[] args) throws Exception {
  18. Connection conn = HbaseUtils.getConnection();
  19. Table tb_movie = conn.getTable(TableName.valueOf("tb_movie"));
  20. Scan scan = new Scan();
  21. // 显示10行
  22. scan.setLimit(10) ;
  23. SubstringComparator substringComparator = new SubstringComparator("00002");
  24. // 行键
  25. /**
  26. * 参数一 判断的符合依据 比较运算符 = >= > < <= !=
  27. * 参数二 比较形式 substringComparator
  28. */
  29. RowFilter filter = new RowFilter(CompareOperator.EQUAL, substringComparator);
  30. // 设置数据过滤器 过滤级别为行过滤
  31. scan.setFilter(filter);
  32. ResultScanner results = tb_movie.getScanner(scan);
  33. for (Result result : results) {
  34. HbaseUtils.showData(result);
  35. }
  36. conn.close();
  37. }
  38. }

五、二级索引