一、Hbase表的设计
1.1、 Hbase 表设计原理(ps:这里不知道可不可以这样说):
https://blog.csdn.net/yydu_666/article/details/80620980
1.2、列簇设计
官方建议不超过2到3个列簇,columnFamily flush临近的column family也会可能被触发关联flush
产生大量IO。因此尽量将关联很强的信息都放在同一个列簇下面,比如:用户的信息
https://www.cnblogs.com/frankdeng/p/9310356.html
二、RowKey设计
2.1、 rowkey 设计原则
2.2.1、长度原则
最好在16位,
1)持久化HFile按照keyValue形式存储, 如果rowkey是100个字节,
则几万的数据将占据近百数M的存储空间,影响HFile的存储效率
2)MemStore 将缓存数据存在内存中,rowkey太长,系统无法存
储更多数据,影响检索效率
3)系统64位的
2.2.2、散列性
若rowkey以时间递增,则高位为随机的散列字段,低位为时间字段,
避免集中访问产生热点问题;
2.2.3、唯一性
rowkey要唯一;
例子1:设计一个存储用户消费记录的rowkey:
根据设计原则比如 rowkey 由 随机数 + 时间戳 + 字符串 组成,
那么这个 rowkey 就由 用户id(随机三位) + 时间戳 + 消费类型 组成
那么对应的预分区可以分为十个,分别为0,1,2,3..到9的开头的数字的分区
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.client.*; import com.jm.common.HBaseClient; import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.util.Bytes; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @Description: $description$ * @Author: Jomin * @Date: $time$ $date$ */ public class CreateBySplitKey { private static HBaseClient instance = null; private Connection connection; public static void main(String[] args) throws IOException { Configuration configuration = HBaseConfiguration.create(); configuration.set("hbase.zookeeper.quorum", "192.168.164.128"); //hbase 服务地址 configuration.set("hbase.zookeeper.property.clientPort", "2181"); //端口号 Admin admin = ConnectionFactory.createConnection(configuration).getAdmin(); //表名 String name = "test_table_split_region"; TableName tableName = TableName.valueOf(name); // 创建表名字 HTableDescriptor tableDescriptor = new HTableDescriptor(name); // 列簇 HColumnDescriptor columnDescriptor = new HColumnDescriptor("info"); tableDescriptor.addFamily(columnDescriptor); //分区 byte[][] splitKeys = genSplitKeys(10); admin.createTable(tableDescriptor, splitKeys); System.out.println("create table sucsssss"); } static private byte[][] genSplitKeys(int regionCount) { int splitkeyCount = regionCount - 1; byte[][] bs = new byte[splitkeyCount][]; List<byte[]> bsList = new ArrayList<byte[]>(); for (int i = 1; i < splitkeyCount; i++) { String splitkey = String.valueOf(i); System.out.println(splitkey); bsList.add(Bytes.toBytes(splitkey)); } Collections.sort(bsList, new Bytes.ByteArrayComparator()); bsList.toArray(bs); return bs; } }
创建后,显示
补充例子:https://www.jianshu.com/p/59d198e501c8
http://bigdata-star.com/archives/1256
2.2.4、避免数据热点问题
1、rowkey 加盐;
2、rowkey 哈希, 将rowkey 哈希之后,用确定的哈希,重构 rowkey 来读取数据(我用这个);
3、rowkey 反转;
( ps : 哈希一致性参考链接
的方法二: https://blog.csdn.net/qq_31289187/article/details/80869906 )
三、预建分区
每个region 维护一个startRowKey和EndRowKey
四、冷热数据处理
https://www.cnblogs.com/small-k/p/8847926.html
https://developer.aliyun.com/article/738128?spm=a2c6h.12873581.0.0.7229187aX9Y9iZ
五、降IO