ruoyi+Hadoop+hbase实现大数据存储查询
前言
有个现实的需求,数据量可能在100亿条左右。现有的数据库是SQL Server,随着采集的数据不断的填充,查询的效率越来越慢(现有的SQL Server查询已经需要数十秒钟的时间),看看有没有优化的方案。
考虑过SQL Server加索引、分区表、分库分表等方案,但数据量增长太快,还是很快就会遇到瓶颈,因此需要更优化的技术。在众多的NOSQL和大数据技术之下,针对此场景,主要考虑了两种方案:
-
MongoDB:json文档型数据库,可以通过集群拓展。但更适合列比较复杂的场景快速查询。
-
Hadoop:大数据领域的瑞士军刀,周边有很多相配套的工具可以使用,后期拓展性较强。
因为此需求只是简单的根据编码找到对应的卷号,因此最终选择Hadoop实现。
部署Hadoop
直接去官方下载,https://hadoop.apache.org/。
要注意版本的问题,版本不匹配会带来很多麻烦。我这里选择的是hadoop 3.3.4的版本。
步骤:
- 找到hadoop对应版本的winutils.exe、hadoop.dll文件
复制hadoop 3.3.4版本对应的winutils.exe和hadoop.dll文件到hadoop的bin文件夹下面。同步复制这两个文件,到C:\Windows\System32下面。
这两个文件可以去github上面搜索,一定要注意跟你的hadoop版本一致,否则不通过。
- 文件配置(下面的配置文件都在 hadoop 3.3.4/etc/hadoop 文件夹内)
a). hadoop-env.cmd文件配置
set JAVA_HOME=C:\Users\Administrator\.jdks\corretto-11.0.21
注意:这里的JAVA_HOME是指向的openjdk(开源)的版本,oracle的jdk用不起来。必须要安装openjdk。
b). core-site.xml
<configuration><property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property>
</configuration>
c). hdfs-site.xml
<configuration><property> <name>dfs.replication</name> <value>1</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>/hadoop-3.3.4/data/namenode</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/hadoop-3.3.4/data/datanode</value> </property>
</configuration>
d). yarn-site.xml
<configuration><property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.nodemanager.auservices.mapreduce.shuffle.class</name> <value>org.apache.hadoop.mapred.ShuffleHandler</value> </property>
</configuration>
- 配置环境变量

再添加到Path,%HADOOP_HOME%\bin
可以在控制台输入:hadoop version,验证是否安装配置正确

最后在控制台输入:start-all.cmd ,启动Hadoop。没有错误信息,表示Hadoop启动成功。

部署Hbase
安装Hbase可以到官网下载:https://hbase.apache.org/。
同样要非常关注版本的问题,因为我上面选择的Hadoop是3.3.4,与之配套的Hbase的版本是2.5.5。
步骤:
-
将之前下载的winutils.exe和hadoop.dll文件拷贝到 hbase的bin目录下,比如我的:E:\hbase-2.5.5\bin。
-
文件配置
在hbase的conf目录下,打开hbase-site.xml文件,添加如下内容:
<configuration><property><name>hbase.rootdir</name><value>file:///E:/hbase-2.5.5/root</value></property><property><name>hbase.cluster.distributed</name><value>false</value></property><property><name>hbase.zookeeper.quorum</name><value>127.0.0.1</value></property><property><name>hbase.tmp.dir</name><value>./tmp</value></property><property><name>hbase.unsafe.stream.capability.enforce</name><value>false</value></property>
</configuration>
按照上述的配置说明,在hbase目录下,添加root和tmp文件夹。
3.配置环境变量(此处省略,参考上面的hadoop的截图)
找到hbase的bin目录下的start-hbase.cmd文件,双击启动。
hbase启动完成后的界面:

基于若依进行二次开发
直接引用ruoyi的项目,在里面添加功能,当然首先需要导入相应的jar包(这些jar包在hadoop和hbase里面都有,直接引用即可)。

当然下面还有引用的jar包,这里就不截图了,供参考。

该项目基于SpringBoot框架,实现了基于HDFS、hbase的基础功能。
控制器代码如下:
package com.ruoyi.web.controller.roll;import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.roll.RollEntity;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.client.coprocessor.AggregationClient;
import org.apache.hadoop.hbase.client.coprocessor.LongColumnInterpreter;
import org.apache.hadoop.hbase.filter.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.*;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FsUrlStreamHandlerFactory;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.CompareOperator;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.mapreduce.Job;@Controller
@RequestMapping("/roll")
public class RollController extends BaseController {private String prefix = "/roll";/*** 新增角色*/@GetMapping("/add")public String add() {
// long count = rowCountByCoprocessor("mytb");
// System.out.println("总记录数->>>"+count + "");return prefix + "/add";}@PostMapping("/list")@ResponseBodypublic TableDataInfo list(String inputEPC) {
// startPage();
// List<SysRole> list = roleService.selectRoleList(role);//String epc = "E280117020000333BF040B34";//String epc = "E280119120006618A51D032D"; //查询的EPCString epc = inputEPC;String tableName = "mytb";String columnFamily = "mycf";// create(tableName, columnFamily);
// insert(tableName,columnFamily);long startTime = System.currentTimeMillis();//E280119120006BEEA4E5032String reVal = query(tableName, columnFamily, epc);long endTime = System.currentTimeMillis();System.out.println("卷号查询时间为:" + (endTime - startTime) + "ms");RollEntity model = new RollEntity();model.epc = epc;model.rollName = reVal;model.searchTime = (endTime - startTime) + "ms";List<RollEntity> list = new ArrayList<>();list.add(model);return getDataTable(list);}// 创建表public static void create(String tableName, String columnFamily) {Configuration conf = HBaseConfiguration.create();conf.set("hbase.rootdir", "hdfs://localhost:9000/hbase");conf.set("hbase.zookeeper.quorum", "localhost");try {Connection conn = ConnectionFactory.createConnection(conf);if (conn.getAdmin().tableExists(TableName.valueOf(tableName))) {System.err.println("Table exists!");} else {HTableDescriptor tableDesc = new HTableDescriptor(TableName.valueOf(tableName));try {tableDesc.addFamily(new HColumnDescriptor(columnFamily));conn.getAdmin().createTable(tableDesc);System.err.println("Create Table SUCCESS!");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}// 插入数据public static void insert(String tableName, String columnFamily) {Configuration conf = HBaseConfiguration.create();conf.set("hbase.rootdir", "hdfs://localhost:9000/hbase");conf.set("hbase.zookeeper.quorum", "localhost");try {Connection conn = ConnectionFactory.createConnection(conf);TableName tn = TableName.valueOf(tableName);Table table = conn.getTable(tn);try {// for (int i = 17742000; i <= 100000000; i++) {
// Put put = new Put(Bytes.toBytes("row" + i));
// put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes("code"),
// Bytes.toBytes("E280119120006BEEA4E5032" + i));
// table.put(put);
// }// Put put = new Put(Bytes.toBytes("E280119120006618A51D032D"));
// put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes("code"),
// Bytes.toBytes("CQ-230308009"));
// table.put(put);Put put = new Put(Bytes.toBytes("E280117020000333BF040B34"));put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes("code"),Bytes.toBytes("CQ-230309002"));table.put(put);table.close();// 释放资源System.err.println("record insert SUCCESS!");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}// 查询public static String query(String tableName, String columnFamily, String rowName) {String reVal = "";Configuration conf = HBaseConfiguration.create();conf.set("hbase.rootdir", "hdfs://localhost:9000/hbase");conf.set("hbase.zookeeper.quorum", "localhost");try {Connection conn = ConnectionFactory.createConnection(conf);TableName tn = TableName.valueOf(tableName);Table table = conn.getTable(tn);try {Get get = new Get(rowName.getBytes());Result r = table.get(get);for (Cell cell : r.rawCells()) {String family = new String(CellUtil.cloneFamily(cell));String qualifier = new String(CellUtil.cloneQualifier(cell));String value = new String(CellUtil.cloneValue(cell));System.out.println("列:" + family + ":" + qualifier + " 值:" + value);reVal = value;break;}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {conn.close();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return reVal;}//过滤查询public static void queryFilter(String tableName, String columnFamily, String rowName, String value) {Configuration conf = HBaseConfiguration.create();conf.set("hbase.rootdir", "hdfs://localhost:9000/hbase");conf.set("hbase.zookeeper.quorum", "localhost");try {Connection conn = ConnectionFactory.createConnection(conf);TableName tn = TableName.valueOf(tableName);Table table = conn.getTable(tn);try {Scan scan = new Scan();Filter filter = new ValueFilter(CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes(value)));scan.setFilter(filter);ResultScanner rs = table.getScanner(scan);for (Result res : rs) {System.out.println(res);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}//读取HDFS文件private static void readHDFSFileContents() {InputStream is = null;OutputStream os = null;BufferedInputStream bufferInput = null;BufferedOutputStream bufferOutput = null;try {is = new URL("hdfs://127.0.0.1:9000/myHadoop/1.txt").openStream();bufferInput = new BufferedInputStream(is);// IOUtils.copyBytes(is, os, 4096,false);byte[] contents = new byte[1024];int bytesRead = 0;String strFileContents = "";while ((bytesRead = is.read(contents)) != -1) {strFileContents += new String(contents, 0, bytesRead);}System.out.println(strFileContents);} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {// IOUtils.closeStream(is);}}//创建HDFS目录private static void createHDFSDirectory() {// TODO Auto-generated method stubtry {Configuration conf = new Configuration();conf.set("fs.defaultFS", "hdfs://127.0.0.1:9000");FileSystem fs = FileSystem.get(conf);boolean result = fs.mkdirs(new Path("/myHadoop"));System.out.println(result);} catch (Exception e) {e.printStackTrace();}}//查询Hbase有多少条记录public long rowCountByCoprocessor(String tablename){long count = 0;try {Configuration conf = HBaseConfiguration.create();conf.set("hbase.rootdir", "hdfs://localhost:9000/hbase");conf.set("hbase.zookeeper.quorum", "localhost");Connection connection = ConnectionFactory.createConnection(conf);//提前创建connection和confAdmin admin = connection.getAdmin();//admin.enableTable(TableName.valueOf("mytb"));TableName name=TableName.valueOf(tablename);//先disable表,添加协处理器后再enable表//admin.disableTable(name);HTableDescriptor descriptor = new HTableDescriptor(name); //admin.getTableDescriptor(name);//descriptor.setReadOnly(false);String coprocessorClass = "org.apache.hadoop.hbase.coprocessor.AggregateImplementation";if (! descriptor.hasCoprocessor(coprocessorClass)) {descriptor.addCoprocessor(coprocessorClass);}//admin.modifyTable(name, descriptor);//admin.enableTable(name);//计时StopWatch stopWatch = new StopWatch();stopWatch.start();Scan scan = new Scan();AggregationClient aggregationClient = new AggregationClient(conf);//System.out.println("RowCount: " + aggregationClient.rowCount(name, new LongColumnInterpreter(), scan));count = aggregationClient.rowCount(name, new LongColumnInterpreter(), scan);stopWatch.stop();System.out.println("统计耗时:" +stopWatch.getTotalTimeMillis());connection.close();} catch (Throwable e) {e.printStackTrace();}return count;}
}
最终效果

相关文章:
ruoyi+Hadoop+hbase实现大数据存储查询
前言 有个现实的需求,数据量可能在100亿条左右。现有的数据库是SQL Server,随着采集的数据不断的填充,查询的效率越来越慢(现有的SQL Server查询已经需要数十秒钟的时间),看看有没有优化的方案。 考虑过S…...
Word 在页眉或页脚中设置背景颜色
目录预览 一、问题描述二、解决方案三、参考链接 一、问题描述 如何在word的页眉页脚中设置背景色? 二、解决方案 打开 Word 文档并进入页眉或页脚视图。在 Word 2016 及更高版本中,你可以通过在“插入”选项卡中单击“页眉”或“页脚”按钮来进入或者…...
python获取js data.now同款时间戳
import requestsimport time from datetime import datetimecu_t datetime.now() se cu_t.timestamp()*1000 se int(se) print(se)#cur_time time.time()*1000 #seconds int(cur_time) #print(seconds)...
线上超市小程序可以做什么活动_提升用户参与度与购物体验
标题:线上超市小程序:精心策划活动,提升用户参与度与购物体验 一、引言 随着移动互联网的普及,线上购物已经成为人们日常生活的一部分。线上超市作为线上购物的重要组成部分,以其便捷、快速、丰富的商品种类和个性化…...
旺店通:API无代码开发的集成解决方案,连接电商平台、CRM和客服系统
集成电商生态:旺店通的核心优势 在数字化转型的浪潮中,旺店通旗舰版奇门以其无代码开发的集成解决方案,正成为电商领域的关键变革者。商家们通过旺店通可以轻松实现与电商平台、CRM系统和客服系统的连接,无需深入了解复杂的API开…...
命令查询pg 数据库版本,并且分析结果行各代表什么意思
目录 1 问题2 实现 1 问题 命令查询pg 数据库版本,并且分析结果行各代表什么意思 2 实现 SELECT version(); PostgreSQL 11.7 (Debian 11.7-2.pgdg1001) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit这是一条关于 PostgreSQL 数据库…...
Elaticsearch 学习笔记
文章目录 Elaticsearch 学习笔记一、什么是 Elaticsearch ?二、Elaticsearch 安装1 es 安装2 问题解决3 数据格式 三、索引操作1 PUT 请求:在postman中,向 ES 服务器发 PUT 请求(PUT请求相当于创建的意思)2 GET 请求&a…...
计算机网络体系的形成
目录 1、开放系统互连参考模型OSI/RM 2、两种国际标准 3、协议与划分层次 4、网络协议的三要素 5、划分层次 (1)文件发送模块使两个主机交换文件 (2)通信服务模块 (3)接入网络模块 6、分层带来的好…...
PyTorch 基础篇(1):Pytorch 基础
Pytorch 学习开始 入门的材料来自两个地方: 第一个是官网教程:WELCOME TO PYTORCH TUTORIALS,特别是官网的六十分钟入门教程 DEEP LEARNING WITH PYTORCH: A 60 MINUTE BLITZ。 第二个是韩国大神 Yunjey Choi 的 Repo:pytorch-t…...
掌握Selenium4:详解各种定位方式
Selenium4中有多种元素定位方式,主要包括以下几种: 通过ID属性定位:根据元素的id属性进行定位。通过name属性定位:当元素没有id属性而有name属性时,可以使用name属性进行元素定位。通过class name定位:可以…...
go-fastfds部署心得
我是windows系统安装 Docker Desktop部署 docker run --name go-fastdfs(任意的一个名称) --privilegedtrue -t -p 3666:8080 -v /data/fasttdfs_data:/data -e GO_FASTDFS_DIR/data sjqzhang/go-fastdfs:lastest docker run:该命令用于运…...
Python第三次练习
Python 一、如何判断一个字符串是否是另一个字符串的子串二、如何验证一个字符串中的每一个字符均在另一个字符串中出现三、如何判定一个字符串中既有数字又有字母四、做一个注册登录系统 一、如何判断一个字符串是否是另一个字符串的子串 实现代码: string1 inp…...
从Java8升级到Java17,特色优化点
从Java8升级到Java17,特色优化点 一、局部变量类型推断二、switch表达式三、文本块四、Records五、模式匹配instanceof六、密封类七、NullPointerException 从Java 8 到 Java 20,Java 已经走过了漫长的道路,自 Java 8 以来,Java 生…...
js实现富文本
当涉及到使用 JavaScript 实现富文本时,一种常见的方法是使用一些现成的富文本编辑器库,比如: Quill:一个功能强大、易于集成的富文本编辑器,支持自定义样式和格式,提供丰富的插件和API。 TinyMCE…...
每日OJ题_算法_双指针②_力扣1089. 复写零
目录 力扣1089. 复写零 解析代码 力扣1089. 复写零 1089. 复写零 - 力扣(LeetCode) 难度 简单 给你一个长度固定的整数数组 arr ,请你将该数组中出现的每个零都复写一遍,并将其余的元素向右平移。 注意:请不要在…...
C++——红黑树
作者:几冬雪来 时间:2023年12月7日 内容:C——红黑树讲解 目录 前言: 红黑树的概念: 红黑树的性质: 红黑树的路径计算: 最长路径和最短路径: AVL树与红黑树的区别ÿ…...
【神化世界】asp网页500内部服务器错误的解决方法
问题解决方案记录 一、问题 在asp网页调试的时候,不小心改错了,好好的页面突然出现如下错误信息了: 二、解决方法 终于找到了问题所在,是sql语句出错造成的,特别记录一下。 正确的写法 sql"select * from mem…...
java面试题6
1.什么是Java中的泛型(Generic)? 答案:泛型是一种参数化类型的机制,在编译时提供类型安全性检查和重用代码的能力。使用泛型可以在编译时检测类型错误,并减少类型转换的需要。 2.Java中的反射(…...
(03)vite 处理 css
文章目录 系列全集vite 处理css流程vite如何解决协同开发,样式重复覆盖的问题?使用less通过配置,更改vite的css默认行为vite 利用postcss样式兼容低版本浏览器 系列全集 (01)vite 从启动服务器开始 (02&am…...
阿里云上传文件出现的问题解决(跨域设置)
跨域设置引起的问题 起因:开通对象存储服务后,上传文件限制在5M 大小,无法上传大文件。 1.查看报错信息 2.分析阿里云服务端响应内容 <?xml version"1.0" encoding"UTF-8"?> <Error><Code>Invali…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...
CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?
在现代前端开发中,Utility-First (功能优先) CSS 框架已经成为主流。其中,Tailwind CSS 无疑是市场的领导者和标杆。然而,一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...
Qt Quick Controls模块功能及架构
Qt Quick Controls是Qt Quick的一个附加模块,提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中,这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构,与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...
Docker环境下安装 Elasticsearch + IK 分词器 + Pinyin插件 + Kibana(适配7.10.1)
做RAG自己打算使用esmilvus自己开发一个,安装时好像网上没有比较新的安装方法,然后找了个旧的方法对应试试: 🚀 本文将手把手教你在 Docker 环境中部署 Elasticsearch 7.10.1 IK分词器 拼音插件 Kibana,适配中文搜索…...
