|
文章目录
- 分布式NoSQL列存储数据库Hbase_列族的设计(五)
- 知识点01:课程回顾
- 知识点02:课程目标
- 知识点03:Hbase设计:列族的设计
- 知识点04:聊天系统案例:需求分析
- 知识点05:聊天系统案例:Hbase表设计
- 知识点06:聊天系统案例:环境准备
- 知识点07:聊天系统案例:模拟生成数据
- 知识点08:聊天系统案例:构建Rowkey
- 知识点09:聊天系统案例:测试写入代码
- 知识点10:聊天系统案例:查询需求分析
- 知识点11:聊天系统案例:测试查询代码
- 知识点12:聊天系统案例:查询问题
- 知识点13:二级索引
- 附录一:Maven 依赖
分布式NoSQL列存储数据库Hbase_列族的设计(五)
知识点01:课程回顾
- Hbase存储原理
- 存储架构
- Hbase:对外提供分布式内存
- Master:集群管理
- RegionServer:数据管理
- HDFS:提供分布式磁盘
- Zookeeper:实现辅助选举、实现元数据存储
- 存储结构
- Table:分布式表,一张表划分了多个Region
- RegionServer:分布式集群节点,管理所有表的region
- Region:每张表的每个分区,对表的数据进行划分
- region的划分规则:按照范围划分,从-oo 到+oo进行有序划分
- 数据的划分规则:按照Rowkey或者Rowkey前缀,Rowkey属于哪个范围,写入对应的region
- Store:对分区内部的数据再次划分,按照列族进行划分Store
- MemStore:内存区域,用于存储刚写入的数据,使用的RegionServer的JVM内存
- StoreFile:逻辑上属于Store,物理上存储在HDFS【HFILE】
- HDFS存储关系
- Hbase目录:/hbase
- Hbase数据:/hbase/data
- 热点问题
- 现象:大量的读写请求全部集中在某个Region或者某个RegionServer上
- 原因:数据分配的不均衡
- 情况一:表只有一个分区
- 情况二:表有多个分区,但是Rowkey是连续的,或者与分区的划分不匹配
- Rowkey是连续,写入同一个Region
- 分区都是按照数字划分的,但是Rowkey是字母开头
- 解决
- 实现预分区
- 方式一:创建表时候:SPLITS => [10,30……]
- 方式二:指定分区的个数,根据数字和字母的Hash组合
- 方式三:Java API
- 合理的设计Rowkey,根据Rowkey的前缀或者完整的Rowkey来划分分区
- Rowkey的设计规则
- 业务原则:尽量用最常用的查询条件作为Rowkey的前缀
- 唯一原则:每条Rowkey是不能重复
- 组合原则:将最常用的几个查询条件组合构建Rowkey
- 散列原则:Rowkey整体或者前缀不能是连续的,需要构建随机的散列
- 长度原则:在满足业务需求情况下,越短越好
- 目的:提高性能
- Rowkey本身每列都会存储:存储占用的空间越大
- Rowkey会构建索引:内存的占用越大,比较就越慢
知识点02:课程目标
- 聊天系统案例
- 目标
- 掌握基于业务需求场景的Hbase表的设计
- 熟练Hbase JavaAPI
- 实现
- 二级索引【重点】
- 问题:如果查询数据的条件,不是rowkey的前缀,怎么解决查询效率的问题?
- 本质:基于Rowkey索引之上,自己构建一层索引
知识点03:Hbase设计:列族的设计
- 设计目的
- 底层实现
- Store:每个Region中根据列族将不同列族的列存储在不同的Store
- 设计规则
- 个数原则:Hbase列族的个数有一定的要求,大部分情况下建议给2个
- 如果列的个数比较多:30列以上
- 如果列的个数比较少,数据量不大
- 长度原则 :能满足业务需求的情况下,越短越好
- 名称没有其他功能,只要有标示性即可
- Hbase底层数据结构:KV结构,按列存储
- K:rowkey+列族+列名+Timestamp
- V:value
知识点04:聊天系统案例:需求分析
- 目标
- 掌握Hbase表的设计:Rowkey设计、列族设计
- 熟练应用Hbase Java API
- 需求
- 基于Hbase来设计聊天系统的数据存储
- 需求1:当用户聊天时,将用户的聊天的信息写入Hbase
- A发送消息给B
发送人ID接受者ID时间内容……
- 写入Hbase
- 需求2:允许用户查询聊天记录:指定时间查询两个用户的聊天信息
- 查询某个时间当前用户与其他用户的聊天记录
- 时间戳
- 发送人ID
- 接收人ID
- 数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m51LYFsL-1616666919956)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322092911806.png)]
消息时间发件人昵称发件人账号发件人性别发件人IP发件人系统发件人手机型号发件人网络制式发件人GPS收件人昵称收件人IP收件人账号收件人系统收件人手机型号收件人网络制式收件人GPS收件人性别消息类型双方距离消息msg_timesender_nickynamesender_accountsender_sexsender_ipsender_ossender_phone_typesender_networksender_gpsreceiver_nickynamereceiver_ipreceiver_accountreceiver_osreceiver_phone_typereceiver_networkreceiver_gpsreceiver_sexmsg_typedistancemessage2020/05/08 15:11:33古博易14747877194男48.147.134.255Android 8.0小米 Redmi K304G94.704577,36.247553莱优97.61.25.5217832829395IOS 10.0Apple iPhone 104G84.034145,41.423804女TEXT77.82KM天涯海角惆怅渡,牛郎织女隔天河。佛祖座前长顿首,只求共度一百年。
知识点05:聊天系统案例:Hbase表设计
- NameSpace的设计
create_namespace 'MOMO_CHAT'
- 表的设计
- Rowkey设计:每一条聊天记录都是一个Rowkey的数据,Rowkey怎么设计?
- 业务原则
- 唯一原则
- 散列原则
- 组合原则
- 长度原则
- 需求:根据时间戳、发件人ID、收件人ID查询数据
[/list] Rowkey:MD5【发件人_收件人_时间戳】取8位_发件人_收件人_时间戳 发件人_收件人_时间戳
- 列族设计
- 个数原则
- 长度原则
- 需求:存储聊天记录所有列,列的个数不多,给定1个列族
C1
- 列的设计
- 预分区
- 规则:划分多个分区,根据Rowkey的设计划分
- Hbase中提供了数字与字母组合的指定分区个数的方式:HexStringSplit
- 建表语句
create 'MOMO_CHAT:MSG', {NAME => "C1", COMPRESSION => "GZ"}, { NUMREGIONS => 6, SPLITALGO => 'HexStringSplit'}
- COMPRESSION:压缩
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fa0jBwS0-1616666919959)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322094757899.png)]
知识点06:聊天系统案例:环境准备
- 参考附录一导入Maven依赖
- 构建以下包,并依次添加代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AdmYCQsN-1616666919960)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210321214639429.png)]
- entity:实体类,JavaBean
- Msg:用于将每一条消息封装为一个对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kRiU1ypz-1616666919961)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322101623133.png)]
- service:应用层
- tool:工具类
- ExcelReader:用于读取Excel表中的数据,从每一列中随机选择一个值,模拟生成用户之间的聊天数据
//返回值:Map集合
K:String:列名称
V:List:这一列对应的所有数据
public static Map<String, List> readXlsx(String path, String sheetName)
```
- randomColumn:随机的从某一列总取某一个值
//参数一:Excel中的所有数据
//参数二:指定获取的列名
//返回值:从指定列名中随机返回一个值
public static String randomColumn(Map<String, List<String>> resultMap, String columnName)
```
- getOneMsg:用于从整张Excel表中让每一列都随机产生一个值,构建一条消息数据
```java
//参数:Excel中的所有数据
//返回值:模拟的数据对应的Msg对象
public static Msg getOneMsg(Map<String, List<String>> resultMap)
```
- 运行测试,得到一条数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3aHK6cHg-1616666919962)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322103055968.png)]
知识点07:聊天系统案例:模拟生成数据
- 目标
- 模拟产生用户聊天数据,将每条聊天数据写入Hbase表中
- 路径
- step1:读取Excel文件,读取指定表格
- step2:从表格的每一列中随机生成一条数据,构建一条模拟数据
- step3:将模拟数据封装在一个Msg对象中
- 实现
- 读取Excel文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XPxKWFGg-1616666919964)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322105117623.png)]
- 随机取某一列的一个值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9a9g0u0B-1616666919964)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322105145249.png)]
- 随机生成一条数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hm39BwML-1616666919965)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322105206464.png)]
- 总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GvWhnY47-1616666919965)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322103055968.png)]
知识点08:聊天系统案例:构建Rowkey
- 目标
- 基于表的设计构建Rowkey
- HbaseJava API
- step1:构建连接
- step2:构建Table对象
- step3:写入数据
table.put(Put)
- 路径
- step1:根据每条模拟数据,获取时间、发送人ID、接收人ID
- step2:基于时间戳、发送人ID、接收人ID构建MD5编码
- step3:使用MD5前8位+发送人ID+接收人ID+时间戳,构建Rowkey返回
- 实现
//构建rowkey,根据每条数据的内容来生成rowkey:ROWKEY = MD5Hash8位_发件人账号_收件人账号_时间戳
private static String getRowKey(Msg msg) throws Exception {
//构建一个动态字符串,用于拼接Rowkey
StringBuilder stringBuilder = new StringBuilder(msg.getSender_account());
stringBuilder.append("_");
stringBuilder.append(msg.getReceiver_account());
stringBuilder.append("_");
//转换时间戳
stringBuilder.append(input.parse(msg.getMsg_time()).getTime());
//构建MD5前缀
byte[] orginkey = Bytes.toBytes(stringBuilder.toString());
String md5AsHex = MD5Hash.getMD5AsHex(orginkey).substring(0, 8);
//返回最终rowkey
return md5AsHex + "_"+stringBuilder.toString();
}
- 总结
- Rowkey必须根据需求提前设计
- 在构建Put等DML操作时,提前基于数据构建Rowkey即可
知识点09:聊天系统案例:测试写入代码
- 目标
- 路径
- step1:基于Rowkey构建Put对象
- step2:获取模拟数据中每一列,添加到Put对象中
- step3:对表执行Put操作,将每条模拟数据,构建一个Put,写入hbase表中中,观察结果
- 实现
//写入Hbase表
private static void writeToHbase(Table table) throws Exception {
for(int i = 0;i<100 ;i++){
//step1:先获取要写入的数据
Map<String, List<String>> maps = ExcelReader.readXlsx("datas/momo/测试数据集.xlsx", "陌陌数据");
Msg msg = ExcelReader.getOneMsg(maps);
//测试
// System.out.println(msg);
//step2:构建rowkey
String rowkey = getRowKey(msg);
// System.out.println(rowkey);
//step3:写入Hbase,构建Put对象
Put put = new Put(Bytes.toBytes(rowkey));
//添加每一列到put对象中
// put.addColumn(列族、列、值)
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_msg_time), Bytes.toBytes(msg.getMsg_time()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_sender_nickyname), Bytes.toBytes(msg.getSender_nickyname()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_sender_account), Bytes.toBytes(msg.getSender_account()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_sender_sex), Bytes.toBytes(msg.getSender_sex()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_sender_ip), Bytes.toBytes(msg.getSender_ip()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_sender_os), Bytes.toBytes(msg.getSender_os()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_sender_phone_type), Bytes.toBytes(msg.getSender_phone_type()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_sender_network), Bytes.toBytes(msg.getSender_network()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_sender_gps), Bytes.toBytes(msg.getSender_gps()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_receiver_nickyname), Bytes.toBytes(msg.getReceiver_nickyname()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_receiver_ip), Bytes.toBytes(msg.getReceiver_ip()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_receiver_account), Bytes.toBytes(msg.getReceiver_account()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_receiver_os), Bytes.toBytes(msg.getReceiver_os()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_receiver_phone_type), Bytes.toBytes(msg.getReceiver_phone_type()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_receiver_network), Bytes.toBytes(msg.getReceiver_network()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_receiver_gps), Bytes.toBytes(msg.getReceiver_gps()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_receiver_sex), Bytes.toBytes(msg.getReceiver_sex()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_msg_type), Bytes.toBytes(msg.getMsg_type()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_distance), Bytes.toBytes(msg.getDistance()));
put.addColumn(Bytes.toBytes(cf_name), Bytes.toBytes(col_message), Bytes.toBytes(msg.getMessage()));
//让表执行Put操作
table.put(put);
}
}
- 总结
- 写入hbase只要设计好rowkey,构建Put,添加列,执行即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaacGobF-1616666919966)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322110352464.png)]
知识点10:聊天系统案例:查询需求分析
- 目标
- 根据时间【日期】、发送人ID、接收人ID查询用户在指定时间的聊天记录
- Hbase JavaAPI
- step1:构建连接
- step2:构建Table
- step3:读分为两种
- Get:给定rowkey,只返回一条数据
- Scan:基于各种条件的复杂查询,返回多条数据
- 路径
- 实现
//构建返回值
List<Msg> msgs = new ArrayList<>();
//step1:先构建连接
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum","node1:2181,node2:2181,node3:2181");
conn = ConnectionFactory.createConnection(conf);
//step2:构建表的对象
Table table = conn.getTable(tbName);
//step3:构建Scan + Filter
Scan scan = new Scan();
String startTime = date+" 00:00:00";
String endTime = date+" 23:59:59";
SingleColumnValueFilter valueFilter1 = new SingleColumnValueFilter(
Bytes.toBytes(cf_name),
Bytes.toBytes("msg_time"),
CompareOperator.GREATER_OR_EQUAL,
Bytes.toBytes(startTime));
SingleColumnValueFilter valueFilter2 = new SingleColumnValueFilter(
Bytes.toBytes(cf_name),
Bytes.toBytes("msg_time"),
CompareOperator.LESS_OR_EQUAL,
Bytes.toBytes(endTime));
SingleColumnValueFilter valueFilter3 = new SingleColumnValueFilter(
Bytes.toBytes(cf_name),
Bytes.toBytes("sender_account"),
CompareOperator.EQUAL,
Bytes.toBytes(sender));
SingleColumnValueFilter valueFilter4 = new SingleColumnValueFilter(
Bytes.toBytes(cf_name),
Bytes.toBytes("receiver_account"),
CompareOperator.EQUAL,
Bytes.toBytes(receiver));
FilterList list = new FilterList();
list.addFilter(valueFilter1);
list.addFilter(valueFilter2);
list.addFilter(valueFilter3);
list.addFilter(valueFilter4);
scan.setFilter(list);
- 总结
- step1:分析需求,使用哪种过滤器
- step2:构建Scan和过滤器即可
知识点11:聊天系统案例:测试查询代码
- 目标
- 路径
- step1:将返回的每条Rowkey的数据中的每一列取出
- step2:将每一列赋值为Msg对象的对应属性
- step3:输出每一条Msg数据
- 实现
ResultScanner scanner = table.getScanner(scan);
//step5:将每个rowkey的数据取出转换为Msg对象,放入集合中
for (Result result : scanner) {
//每个rowkey构建一个Msg对象
Msg msg = new Msg();
//读取Rowkey中每一列的数据赋值给msg的属性
// result.getValue(列族,列)
msg.setSender_nickyname(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_sender_nickyname))));
msg.setSender_account(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_sender_account))));
msg.setSender_sex(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_sender_sex))));
msg.setSender_ip(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_sender_ip))));
msg.setSender_os(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_sender_os))));
msg.setSender_phone_type(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_sender_phone_type))));
msg.setSender_network(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_sender_network))));
msg.setSender_gps(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_sender_gps))));
msg.setReceiver_nickyname(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_receiver_nickyname))));
msg.setReceiver_account(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_receiver_account))));
msg.setReceiver_sex(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_receiver_sex))));
msg.setReceiver_ip(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_receiver_ip))));
msg.setReceiver_os(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_receiver_os))));
msg.setReceiver_phone_type(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_receiver_phone_type))));
msg.setReceiver_network(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_receiver_network))));
msg.setReceiver_gps(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_receiver_gps))));
msg.setDistance(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_distance))));
msg.setMsg_type(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_msg_type))));
msg.setMessage(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_message))));
msg.setMsg_time(Bytes.toString(result.getValue(Bytes.toBytes(cf_name),Bytes.toBytes(col_msg_time))));
//将msg放入集合
msgs.add(msg);
}
return msgs;
- 总结
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OteMzxhZ-1616666919966)(20210322_分布式NoSQL列存储数据库Hbase(五).assets/image-20210322112127417.png)]
- step1:执行Scan,得到所有符合条件的数据
- step2:迭代每条数据进行处理即可
知识点12:聊天系统案例:查询问题
- 问题
- 根据当前Rowkey的设计以及当前的需求,无法实现基于索引查询,性能较差,如何解决?
- 原因
- 解决
知识点13:二级索引
- 目标
- 基于一级索引之上,构建一层索引,通过走两次索引来代替全表扫描
- Hbase中的唯一索引是Rowkey
- 目标:得到所有符合条件的数据
- 思考:能不能先得到所有符合条件的rowkey,再通过rowkey得到所有符合条件的数据
- 路径
- step1:先构建原始数据表
- step2:根据查询需求,构建索引表
- step3:先查询索引表,再查询原始数据表
- 实现
- 总结
- Hive的问题
- Hive中能否执行create index
- 可以
- 要求:0.7 ~ 3.x
- 原因:Hive中索引表不会自动同步原始数据表,必须手动通过MapReduce同步索引表
- Hbase问题:索引表如何与原表保持一致的问题
- 方案一:当客户端往Hbase原表写入时,在客户端中也往索引表写一份
- 不会用的
- 优点:最简单
- 缺点:Hbase无法保证不同表不同的rowkey的事务性,不能实现同时成功或者同时失败,性能很差
- 方案二:协处理器,类似于Hive中的UDF
- 自定义开发代码,让Hbase实现监听原表,如果原表的数据发生变化,索引自动发生变化
- 优点:Hbase原生发生,可以满足原子性包括性能
- 缺点:开发比较麻烦
- 方案三:第三方工具
- Phoenix:专门为Hbase所设计的工具,底层通过大量协处理器来实现,提供SQL接口
create index
- ES:ElasticSearch / Solr
附录一:Maven 依赖
<repositories>
<repository>
<id>aliyun</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<properties>
<hbase.version>2.1.2</hbase.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.hbase/hbase-client -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>${hbase.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>${hbase.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- Xml操作相关 -->
<dependency>
<groupId>com.github.cloudecho</groupId>
<artifactId>xmlbean</artifactId>
<version>1.5.5</version>
</dependency>
<!-- 操作Office库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<!-- 操作Office库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<!-- 操作Office库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.0.1</version>
</dependency>
<!-- 操作JSON -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!-- phoenix core -->
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>5.0.0-HBase-2.0</version>
</dependency>
<!-- phoenix 客户端 -->
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-queryserver-client</artifactId>
<version>5.0.0-HBase-2.0</version>
</dependency>
</dependencies>
<!-- 操作Office库 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.0.1</version>
</dependency>
<!-- 操作JSON -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<!-- phoenix core -->
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>5.0.0-HBase-2.0</version>
</dependency>
<!-- phoenix 客户端 -->
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-queryserver-client</artifactId>
<version>5.0.0-HBase-2.0</version>
</dependency>
</dependencies>
|
免责声明:
1. 本站所有资源来自网络搜集或用户上传,仅作为参考不担保其准确性!
2. 本站内容仅供学习和交流使用,版权归原作者所有!© 查看更多
3. 如有内容侵害到您,请联系我们尽快删除,邮箱:kf@codeae.com
|