当前位置: 首页 > news >正文

详解 HBase 的常用 API

一、环境准备

  • 创建一个 Maven 工程并引入依赖

    <dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-server</artifactId><version>1.3.1</version>
    </dependency>
    <dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>1.3.1</version>
    </dependency>
    
  • 创建 API 测试类并获取 HBase 客户端连接

    public class TestAPI {private static Connection conn = null;private static Admin admin = null;  // DDL 操作客户端static {try { // 1.获取配置信息对象// 过时API// HBaseConfiguration conf1 = new HBaseConfiguration();// conf1.set("hbase.zookeeper.quorum","hadoop102,hadoop103,hadoop104");// 新APIConfiguration conf = HBaseConfiguration.create();conf.set("hbase.zookeeper.quorum","hadoop102,hadoop103,hadoop104");// 2.创建连接对象(新API)conn = ConnectionFactory.createConnection(conf);// 3.创建hbase管理员对象// 过时API// HBaseAdmin admin1 = new HBaseAdmin(conf1);// 新APIadmin = conn.getAdmin();} catch(Exception e) {e.printStackTrace();    }}// 关闭资源public static void close() {try {if(admin != null) {admin.close();}if(conn != null) {conn.close();}} catch(Exception e) {e.printStackTrace();}}
    }
    

二、HBase API 实操

1. 判断表是否存在

public static boolean isTableExist(String tableName) {// 过时API// boolean exist = admin1.tableExists(tableName);// 新APIboolean exist = admin.tableExists(TableName.valueOf(tableName));return exist;
}

2. 创建表

public static void createTable(String tableName, String... cfs) {// 1.判断传入列族信息if(cfs.length()<=0) {System.out.println("必须设置一个列族信息");return;}// 2.判断表是否存在if(isTableExist(tableName)) {System.out.println(tableName + "表已经存在");return;}// 3.创建表描述器HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));// 4.循环添加列族for(String cfs : cfs) {// 5.创建列族描述器HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(cfs);// 6.添加单个列族hTableDescriptor.addFamily(hColumnDescriptor);}// 7.创建表admin.createTable(hTableDescriptor);System.out.println(tableName + "表创建成功!");
}

3. 删除表

public static void deleteTable(String tableName) {// 1.判断表是否存在if(!isTableExist(tableName)) {System.out.println(tableName + "表已经不存在!");return;}// 2.使表下线admin.disableTable(TableName.valueOf(tableName));// 3.删除表admin.deleteTable(TableName.valueOf(tableName));System.out.println(tableName + "表删除成功!");
}

4. 创建命名空间

public static void createNamespace(String ns) {// 1.创建命名空间描述器NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(ns).build();try {// 2.创建命名空间admin.createNamespace(namespaceDescriptor); System.out.println(ns + "命名空间创建成功!");} catch(NamespaceExistException e) { // 生产上判断 ns 是否存在System.out.println(ns + "命名空间已经存在!");} catch(Exception e) {e.printStackTrace();}}

5. 插入数据

public static void putData(String tableName, String rowKey, String cf, String cn, String value) {// 1.创建hbase表操作对象Table table = conn.getTable(TableName.valueOf(tableName));// 2.创建 put 对象// HBase 底层存储的数据格式都是 byte[],可以通过 hbase.util 包下的 Bytes 类进行数据类型转换Put put = new Put(Bytes.toBytes(rowKey));// 3.给put对象赋值put.addColumn(Bytes.toBytes(cf), Bytes.toBytes(cn), Bytes.toBytes(value));// 4.插入数据table.put(put);// 5.关闭资源table.close();}

6. 获取数据

6.1 get
public static void getData(String tableName, String rowKey, String cf, String cn) {// 1.创建hbase表操作对象Table table = conn.getTable(TableName.valueOf(tableName));// 2.创建get对象Get get = new Get(Bytes.toBytes(rowKey));// 2.1.指定获取的列族// get.addFamily(Bytes.toBytes(cf));// 2.2.指定获取的列族和列// get.addColumn(Bytes.toBytes(cf), Bytes.toBytes(cn));// 2.3.指定获取数据的版本数// get.setMaxVersions();  // 相当于 scan 'tb',{RAW=>TRUE,VERSIONS=>10}// 3.获取一行的数据Result result = table.get(get);// 4.获取一行的所有 cellfor(Cell cell : result.rawCells()) {// 5.打印数据信息System.out.println("family:" + Bytes.toString(CellUtil.cloneFamily(cell)) +",qualifier:" + Bytes.toString(CellUtil.cloneQualifier(cell)) + ",value:" + Bytes.toString(CellUtil.cloneValue(cell)));}// 6.关闭资源table.close();
}
6.2 scan
public static void scanTable(String tableName) {// 1.创建hbase表操作对象Table table = conn.getTable(TableName.valueOf(tableName));// 2.构建scan对象Scan scan = new Scan(); // 全表// Scan scan = new Scan(Bytes.toBytes("1001"),Bytes.toBytes("1003")); // 限定 rowKey 范围,左闭右开// 3.扫描表ResultScanner resultScanner = table.getScanner(scan);// 4.解析resultScannerfor(Result result : resultScanner) { // 按 rowKey 从小到大遍历获取// 5.解析resultfor(Cell cell : result.rawCells()) {// 6.打印数据信息System.out.println("rk:" + Bytes.toString(CellUtil.cloneRow(cell)) +",family:" + Bytes.toString(CellUtil.cloneFamily(cell)) +",qualifier:" + Bytes.toString(CellUtil.cloneQualifier(cell)) + ",value:" + Bytes.toString(CellUtil.cloneValue(cell)));}}// 7.关闭资源table.close();
}

7. 删除数据

delete 操作最终还是 put 操作

public static void deleteData(String tableName, String rowKey, String cf, String cn) {// 1.创建hbase表操作对象Table table = conn.getTable(TableName.valueOf(tableName));// 2.构建delete对象Delete delete = new Delete(Bytes.toBytes(rowKey)); // 相当于 deleteall 命令// 2.1.设置删除列// delete.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cn)); // 删除指定版本的列,不指定则为最大版本,小于该版本的列信息可以查询出来(慎用)// delete.addColumns(Bytes.toBytes(cf),Bytes.toBytes(cn)); // 删除列的所有版本// 2.2.设置删除的列族// delete.addFamily(Bytes.toBytes(cf));// 3.删除数据table.delete(delete);// 4.关闭资源table.close();
}
  • 只指定 rowKey 删除:删除指定 rowKey 的所有列族所有版本数据,标记为 deleteFamily
  • 指定 rowKey + 列族 [+ 版本]:删除指定 rowKey 的指定列族所有版本 (小于等于该版本) 数据,标记为 deleteFamily
  • 指定 rowKey + 列族 + 列 [+ 版本]:
    • addColumns():删除指定 rowKey 的指定列族的指定列的所有版本 (小于等于该版本) 数据,标记为 deleteColumn
    • addColumn():删除指定 rowKey 的指定列族的指定列的最新版本 (该指定版本) 数据,标记为 delete,生产上慎用

三、与 MapReduce 交互

1. 环境搭建

  • 查看 MR 操作 HBase 所需的 jar 包:

    cd /opt/module/hbase
    bin/hbase mapredcp
    
  • 在 Hadoop 中导入环境变量

    • 临时生效:

      # 在命令行执行
      export HBASE_HOME=/opt/module/hbase
      export HADOOP_HOME=/opt/module/hadoop-2.7.2
      export HADOOP_CLASSPATH=`${HBASE_HOME}/bin/hbase mapredcp`
      
    • 永久生效:

      # 在 /etc/profile.d/my_env.sh 配置
      export HBASE_HOME=/opt/module/hbase
      export HADOOP_HOME=/opt/module/hadoop-2.7.2# 在 hadoop-env.sh 中配置,在有关 HADOOP_CLASSPATH 的 for 循环之后添加
      export HADOOP_CLASSPATH=$HADOOP_CLASSPATH:/opt/module/hbase/lib/*
      
  • 分发配置到其他节点

  • 启动 Hadoop 集群和 HBase 集群

2. 案例实操

2.1 官方案例
  • 统计 stu 表中有多少行数据

    /opt/module/hadoop-2.7.2/bin/yarn jar \
    /opt/module/hbase/lib/hbase-server-1.3.1.jar \ 
    rowcounter student
    
  • 使用 MapReduce 将本地数据导入到 HBase

    # 在本地创建一个 tsv 格式的文件:fruit.tsv
    vim fruit.tsv
    1001  Apple  Red
    1002  Pear  Yellow
    1003  Pineapple Yellow# 在 HDFS 中创建 input_fruit 文件夹并上传 fruit.tsv 文件
    /opt/module/hadoop-2.7.2/bin/hdfs dfs -mkdir /input_fruit/
    /opt/module/hadoop-2.7.2/bin/hdfs dfs -put fruit.tsv /input_fruit/# 创建 Hbase 表
    Hbase(main):001:0> create 'fruit','info'# 执行 MapReduce 到 HBase 的 fruit 表中(若表不存在则报错)
    /opt/module/hadoop-2.7.2/bin/yarn jar \
    /opt/module/hbase/lib/hbase-server-1.3.1.jar \
    importtsv -Dimporttsv.columns=HBASE_ROW_KEY,info:name,info:color fruit \
    hdfs://hadoop102:9000/input_fruit/fruit.tsv# 使用 scan 命令查看导入后的结果
    Hbase(main):001:0> scan 'fruit'
    
2.2 自定义案例
  • 案例 1:实现将 HDFS 中的数据写入到 Hbase 表中

    • 编码:

      // 构建 FruitMapper 用于读取 HDFS 中的文件数据
      public class FruitMapper extends Mapper<LongWritable, Text, LongWritable, Text> {@overrideprotected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {context.write(key, value);}
      }// 构建 FruitReducer 用于将 HDFS 中的文件数据写入 Hbase
      // TableReducer 默认的输出value类型是 Mutation,其子类有 put/delete 等
      public class FruitReducer extends TableReducer<LongWritable, Text, NullWritable> {@overrideprotected void reduce(LongWritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException {// 1.遍历获取每行数据for(Text value : values) {// 2.切割一行数据String[] fields = value.toString().split("\t");// 3.构建put对象Put put = new Put(Bytes.toBytes(fields[0]));// 4.为put对象赋值put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("name"),Bytes.toBytes(fields[1]));put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("color"),Bytes.toBytes(fields[2]));// 5.数据写入hbasecontext.write(NullWritable.get(),put);}}
      }// 构建 FruitDriver
      public class FruitDriver implements Tool {private Configuration conf = null;@overridepublic int run(String[] args) throws Exception {// 1.获取jobJob job = Job.getInstance(conf);// 2.设置驱动类路径job.setJarByClass(FruitDriver.class);// 3.设置Mapper及输出KV类型job.setMapperClass(FruitMapper.class);job.setMapOutputKeyClass(LongWritable.class);job.setMapOutputValueClass(Text.class);// 4.设置Reducer(不能使用普通的 Reducer 设置)TableMapReduceUtil.initTableReducerJob(args[1], FruitReducer.class, job);// 5.设置输入路径FileInputFormat.setInputPaths(job, new Path(args[0]));// 6.提交jobboolean result = job.waitForCompletion(true);return result ? 0 : 1;}@overridepublic void setConf(Configuration conf) {this.conf = conf;}@overridepublic Configuration getConf() {return conf;}public static void main(String[] args) {try {Configuration conf = new Configuration();int status = ToolRunner.run(conf, new FruitDriver(), args);System.exit(status);    } catch(Exception e) {e.printStackTrace();}}
      }
      
    • 将代码打包后上传到 hbase 集群服务器并执行

      # 首先创建 hbase fruit 表
      # 执行:
      /opt/module/hadoop-2.7.2/bin/yarn jar \
      /opt/module/hbase/Hbase-0.0.1-SNAPSHOT.jar com.xxx.FruitDriver \ /input_fruit/fruit.tsv fruit
      
  • 案例 2:将 fruit 表中的一部分数据,通过 MR 迁入到 fruit2 表中

    • 编码

      // 构建 Fruit2Mapper 用于读取 Hbase 中的 Fruit 表数据
      // TableMapper 默认的KV输入类型为 ImmutableBytesWritable, Result
      public class Fruit2Mapper extends TableMapper<ImmutableBytesWritable, Put> {@overrideprotected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {// 1.构建PUT对象Put put = new Put(key.get()); // key 是 rowKey 值// 2.解析Resultfor(Cell cell : value.rawCells()) {// 3.获取列为 name 的 cellif("name".equals(Bytes.toString(CellUtil.cloneQualifier(cell)))) {// 4.为put对象赋值put.add(cell);}}// 5.写出context.write(key, put);}
      }// 构建 Fruit2Reducer 用于将数据写入 Hbase
      // TableReducer 默认的输出value类型是 Mutation,其子类有 put/delete 等
      public class Fruit2Reducer extends TableReducer<ImmutableBytesWritable, Put, NullWritable> {@overrideprotected void reduce(ImmutableBytesWritable key, Iterable<Put> values, Context context) throws IOException, InterruptedException {// 遍历写出for(Put put : values) {context.write(NullWritable.get(), put);}}
      }// 构建 Fruit2Driver
      public class Fruit2Driver implements Tool {private Configuration conf = null;@overridepublic int run(String[] args) throws Exception {// 1.获取jobJob job = Job.getInstance(conf);// 2.设置驱动类路径job.setJarByClass(Fruit2Driver.class);// 3.设置Mapper及输出KV类型(不能使用普通的 Mapper 设置)TableMapReduceUtil.initTableMapperJob(args[0], new Scan(), Fruit2Mapper.class, ImmutableBytesWritable.class, Put.class, job);// 4.设置Reducer(不能使用普通的 Reducer 设置)TableMapReduceUtil.initTableReducerJob(args[1], Fruit2Reducer.class, job);// 5.提交jobboolean result = job.waitForCompletion(true);return result ? 0 : 1;}@overridepublic void setConf(Configuration conf) {this.conf = conf;}@overridepublic Configuration getConf() {return conf;}public static void main(String[] args) {try {// Configuration conf = new Configuration();Configuration conf = HbaseConfiguration.create();int status = ToolRunner.run(conf, new Fruit2Driver(), args);System.exit(status);    } catch(Exception e) {e.printStackTrace();}}
      }
      
    • 集群测试:将代码打包后上传到 hbase 集群服务器并执行

      # 首先创建 hbase fruit2 表
      # 执行:
      /opt/module/hadoop-2.7.2/bin/yarn jar \
      /opt/module/hbase/Hbase-0.0.1-SNAPSHOT.jar com.xxx.Fruit2Driver \
      fruit fruit2
      
    • 本地测试:

      • 在 Maven 工程的 resources 目录下创建 hbase-site.xml 文件
      • hbase/conf/hbase-site.xml 的内容拷贝到上面创建的文件中
      • 执行 Fruit2Driver 程序 main 方法

四、集成 Hive

1. 与 Hive 对比

  • Hive
    • 数据仓库:Hive 的本质其实就相当于将 HDFS 中已经存储的文件在 Mysql 中做了一个双射关系,以方便使用 HQL 去管理查询
    • 用于数据分析、清洗:Hive 适用于离线的数据分析和清洗,延迟较高
    • 基于 HDFS、MapReduce:Hive 存储的数据依旧在 DataNode 上,编写的 HQL 语句终将是转换为 MapReduce 代码执行
  • HBase
    • 数据库:是一种面向列族存储的非关系型数据库
    • 用于存储结构化和非结构化的数据:适用于单表非关系型数据的存储,不适合做关联查询,类似 JOIN 等操作
    • 基于 HDFS:数据持久化存储的体现形式是 HFile,存放于 DataNode 中,被 ResionServer 以 region 的形式进行管理
    • 延迟较低,接入在线业务使用:面对大量的企业数据, HBase 可以直线单表大量数据的存储,同时提供了高效的数据访问速度

2. 集成使用

2.1 环境搭建
  • /etc/profile.d/my_env.sh 中配置 Hive 和 HBase 环境变量

    vim /etc/profile.d/my_env.shexport HBASE_HOME=/opt/module/hbase
    export HIVE_HOME=/opt/module/hive
    
  • 使用软链接将操作 HBase 的 Jar 包关联到 Hive

    ln -s $HBASE_HOME/lib/hbase-common-1.3.1.jar $HIVE_HOME/lib/hbase-common-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-server-1.3.1.jar $HIVE_HOME/lib/hbaseserver-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-client-1.3.1.jar $HIVE_HOME/lib/hbase-client-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-protocol-1.3.1.jar $HIVE_HOME/lib/hbase-protocol-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-it-1.3.1.jar $HIVE_HOME/lib/hbase-it-1.3.1.jar
    ln -s $HBASE_HOME/lib/htrace-core-3.1.0-incubating.jar $HIVE_HOME/lib/htrace-core-3.1.0-incubating.jar
    ln -s $HBASE_HOME/lib/hbase-hadoop2-compat-1.3.1.jar $HIVE_HOME/lib/hbase-hadoop2-compat-1.3.1.jar
    ln -s $HBASE_HOME/lib/hbase-hadoop-compat-1.3.1.jar $HIVE_HOME/lib/hbase-hadoop-compat-1.3.1.jar
    
  • hive-site.xml 中添加 Zookeeper 连接信息

    <property><name>hive.zookeeper.quorum</name><value>hadoop102,hadoop103,hadoop104</value><description>The  list  of  ZooKeeper  servers  to  talk  to.  This  is only needed for read/write locks.</description>
    </property>
    <property><name>hive.zookeeper.client.port</name><value>2181</value><description>The  port  of  ZooKeeper  servers  to  talk  to.  This  is only needed for read/write locks.</description>
    </property>
    
  • 下载 Hive 对应版本的源码包,使用 Eclipse 工具创建一个普通 Java 工程 import 这个 hbase-handler 文件夹到工程,在工程下创建一个 lib 文件并导入 hive/lib 下所有的 .jar 文件(add build path),使用 export 重新编译 hive-hbase-handler-1.2.2.jar (取消勾选 lib 目录),将新编译的 jar 包替换掉 hive/lib 下的 jar 包

2.2 案例实操
  • 案例 1:建立 Hive 表,关联 HBase 表,插入数据到 Hive 表的同时能够影响 HBase 表

    # 在 Hive 中创建表同时关联 HBase,然后分别进入 Hive 和 HBase 查看
    CREATE TABLE hive_hbase_emp_table
    (empno int,ename string,job string,mgr int,hiredate string,sal double,comm double,deptno int
    )
    STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
    WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno")
    TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");# 在 Hive 中创建临时中间表,用于 load 文件中的数据
    # 提示:不能将数据直接 load 进 Hive 所关联 HBase 的那张表中
    CREATE TABLE emp
    (empno int,ename string,job string,mgr int, hiredate string,sal double,comm double,deptno int
    )
    row format delimited fields terminated by '\t';# 向 Hive 中间表中 load 数据
    load data local inpath '/home/admin/softwares/data/emp.txt' into table emp;# 通过 insert 命令将中间表中的数据导入到 Hive 关联 Hbase 的那张表中
    insert into table hive_hbase_emp_table select * from emp;# 查看 Hive 以及关联的 HBase 表中是否已经成功的同步插入了数据
    select * from hive_hbase_emp_table;scan 'hbase_emp_table'
    
  • 案例 2:针对已经存在的 HBase 表 hbase_emp_table,在 Hive 中创建一个外部表来关联这张表,并使用 HQL 操作

    # 在 Hive 中创建外部表关联 HBase 表(必须创建外部表)
    CREATE EXTERNAL TABLE relevance_hbase_emp
    (empno int,ename string,job string,mgr int,hiredate string,sal double,comm double,deptno int
    )
    STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
    WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:comm,info:deptno") 
    TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");# 使用 HQL 操作
    select * from relevance_hbase_emp;
    

相关文章:

详解 HBase 的常用 API

一、环境准备 创建一个 Maven 工程并引入依赖 <dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-server</artifactId><version>1.3.1</version> </dependency> <dependency><groupId>org.apach…...

JSR303校验

校验的需求 前端请求后端接口传输参数&#xff0c;需要校验参数。 在controller中需要校验参数的合法性&#xff0c;包括&#xff1a;必填项校验、数据格式校验等在service中需要校验业务规则&#xff0c;比如&#xff1a;课程已经审核过了&#xff0c;所以提交失败。 servi…...

04 远程访问及控制

1、SSH远程管理 SSH是一种安全通道协议&#xff0c;主要用来实现字符界面的远程登录、远程复制等功能。 SSH协议对通信双方的数据传输进行了加密处理&#xff08;包括用户登陆时输入得用户口令&#xff09;。 终端&#xff1a;接收用户的指令 TTY终端不能远程&#xff0c;它…...

[晕事]今天做了件晕事38 shell里的source 点号

今天碰到一个问题脚本里使用点号引入某个文件形式如下&#xff1a; . /tmp/abc但是脚本运行出现错误&#xff0c;一开始还以为是/tmp没有可执行权限&#xff08;https://mzhan017.blog.csdn.net/article/details/112178736#t16&#xff09;&#xff0c;导致abc运行不了。 后来…...

java如何分割字符串

java要实现对字符串的分割&#xff0c;需要用到split语句 语法格式是 str.split(分隔符) 其中 str是字符串 示例代码如下 public class Stringsplit {public static void main(String[] args) {String a"蒸羊羔&#xff0c;蒸熊掌&#xff0c;蒸鹿尾&#xff0c;烧花…...

胡说八道(24.6.12)——数字电子技术以及Modelsim

上回书说到数电中的最常用的表达式——逻辑表达式(由布尔代数组成)以及常用的两种图表——真值表(真值表表示的是所有的输入可能的线性组合以及输出)和卡诺图(卡诺图则是一种化简工具&#xff0c;排除冗余项&#xff0c;合并可合并项)。 今天&#xff0c;先来看看昨天说的基本逻…...

【Android面试八股文】AsyncTask中的任务是串行的还是并行的

文章目录 串行执行并行执行示例代码串行执行(默认)并行执行总结AsyncTask 的任务执行方式可以是串行的,也可以是并行的,这取决于使用的执行器 ( Executor)。 串行执行 默认情况下,AsyncTask 使用的是 SERIAL_EXECUTOR,即任务按顺序一个接一个地执行。这意味着下一个任务…...

无人机RTMP推流EasyDSS直播平台推流成功,不显示直播按钮是什么原因?

互联网视频云平台/视频点播直播/视频推拉流EasyDSS支持HTTP、HLS、RTMP等播出协议&#xff0c;并且兼容多终端&#xff0c;如Windows、Android、iOS、Mac等。为了便于用户集成与二次开发&#xff0c;我们也提供了API接口供用户调用和集成。在无人机场景上&#xff0c;可以通过E…...

经验分享,xps格式转成pdf格式

XPS 是一种电子文档格式、后台打印文件格式和页面描述语言。有时候微软默认打印机保存的是xps格式&#xff0c;我们如何转换为pdf格式呢&#xff0c;这里分享一个免费好用的网站&#xff0c;可以实现。 网站&#xff1a;https://xpstopdf.com/zh/ 截图&#xff1a;...

基于51单片机的音乐彩灯设计

基于51单片机的音乐彩灯设计 &#xff08;程序&#xff0b;原理图&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 由STC单片机ADC0809模块LM386功放模块喇叭音频接口发光二极管电源构成 1.通过音频线输入可以播放电脑、手机、MP3里面的音乐。 2.AD对音频…...

API接口设计的艺术:如何提升用户体验和系统性能

在数字时代&#xff0c;API接口的设计对于用户体验和系统性能有着至关重要的影响。良好的设计可以显著提升应用程序的响应速度、可靠性和易用性。以下是几个关键点&#xff0c;帮助改善API接口的设计&#xff1a; 1. 理解并定义清晰的要求 用户研究&#xff1a;与最终用户进行…...

韩兴国/姜勇团队在《Trends in Plant Science》发表植物根系氮素再分配的观点文章!

氮素是陆地生态系统中的关键限制性营养元素&#xff0c;通过生物固氮和土壤氮供应通常远低高等植物的氮需求。当土壤氮素供应无法充分满足植物茎叶生长需求时&#xff0c;植物会通过自身营养器官&#xff08;如根或根茎&#xff09;再分配来实现氮的内部循环和再利用。尽管植物…...

52.Python-web框架-Django - 多语言编译-fuzzy错误

目录 1.起因 2.原因 3.解决方法 3.1手动移除fuzzy标记 3.2重新生成po文件&#xff0c;并检查是否还存在fuzzy标记 3.3重新编译生成mo文件 1.起因 在Django的国际化和本地化过程中&#xff0c;当你发现某些字段仅显示msgid&#xff0c;而不显示msgstr时&#xff0c;可能是…...

Linux自旋锁

面对没有获取锁的现场&#xff0c;通常有两种处理方式。 互斥锁&#xff1a;堵塞自己&#xff0c;等待重新调度请求自旋锁&#xff1a;循环等待该锁是否已经释放 本文主要讲述自旋锁 自旋锁其实是一种很乐观的锁&#xff0c;他认为只要再等一下下锁便能释放&#xff0c;避免…...

服务器----阿里云服务器重启或关机,远程连接进不去,个人博客无法打开

问题描述 在使用阿里云免费的新加坡服务器时&#xff0c;发现重启或者是关机在开服务器后&#xff0c;就会出现远程连接不上、个人博客访问不了等问题 解决方法 进入救援模式连接主机&#xff0c;用户名是root&#xff0c;密码是自己设置的 点击访问博客查看更多内容...

go 定时任务

在 Go 语言中&#xff0c;可以使用内置的 time 包来实现定时任务。以下是一个简单的示例&#xff1a; go package main import ( "fmt" "time" ) func main() { timer : time.NewTimer(2 * time.Second) <-timer.C fmt.Println(…...

Java Character 类

Java Character 类 Character 类用于对单个字符进行操作。 Character 类在对象中包装一个基本类型 char 的值 char ch a;// Unicode 字符表示形式char uniChar \u039A; // 字符数组char[] charArray { a, b, c, d, e };然而&#xff0c;在实际开发过程中&#xff0c;我们经…...

MQTT协议应用场景

MQTT协议的应用场景非常丰富&#xff0c;特别是在物联网领域。以下是对MQTT协议应用场景的清晰归纳&#xff1a; 1.物联网设备控制和监控&#xff1a;MQTT被广泛应用于物联网设备之间的通信&#xff0c;如智能家居、智能城市和工业自动化等领域。设备可以发布自身状态到特定主题…...

3.4.马氏链-随机游走的常返性

随机游走的常返态 1. 随机游走常返性定义1.1. 随机游走常返值和可能集1.2. 随机游走常返性2. 简单随机游走: 维数与常返性的关系2.1. 简单随机游走2.2. 二维及以下简单随机游走常返, 三维及以上简单随机游走非常返3. 随机游走 ( d ≤ 2 ) (d\leq 2) (d≤2): 常返的充分条件4. 随…...

HOT100与剑指Offer

文章目录 前言一、41. 缺失的第一个正数&#xff08;HOT100&#xff09;二、6. 从尾到头打印链表&#xff08;剑指Offer&#xff09;总结 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招&#xff0c;计划刷完hot100和剑指Offer的刷题计划&#xff0c;加油&#xff01; 根…...

【AI开发】CRAG、Self-RAG、Adaptive-RAG

先放一张基础RAG的流程图 https://blog.langchain.dev/agentic-rag-with-langgraph/ 再放一个CRAG和self-RAG的LangChain官方博客 Corrective RAG(CRAG) 首先需要知道的是CRAG的特色发生在retrieval阶段的最后开始&#xff0c;即当我们获得到了近似的document&#xff08;或者…...

FFmpeg中内存分配和释放相关的源码:av_malloc函数、av_mallocz函数、av_free函数和av_freep函数分析

一、av_malloc函数分析 &#xff08;一&#xff09;av_malloc函数的声明 av_malloc函数的声明放在在FFmpeg源码&#xff08;本文演示用的FFmpeg源码版本为5.0.3&#xff0c;该ffmpeg在CentOS 7.5上通过10.2.1版本的gcc编译&#xff09;的头文件libavutil/mem.h中&#xff1a;…...

七天进阶elasticsearch[Four]

依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>...

数据库-数据定义和操纵-DDL语言的使用

创建一个数据库&#xff1a; create database 数据库名; 选择数据库&#xff1a; use 数据库名; 创建表 create table 表名( ); 添加字段&#xff1b; ALTER TABLE 表名 ADD 新字段名 数据类型 [约束条件] [FIRST|AFTER 已存在字段名] ; 删除字段&#xff1a; ALTER TABLE 表…...

黄金价格与美元的关系变了?

在一些传统的定价框架中&#xff0c;现货黄金的价格走势取&#xff0c;决于美元的实际利率水平——实际利率越高&#xff0c;黄金价格越低&#xff0c;反之亦然。在大多数的时候&#xff0c;美元的实际利率决定了美元指数的高低所以人们通常认为&#xff0c;现货金价与美元呈反…...

VB.net与C# 调用InitializeComponent的区别

VB.NET与C# 调用InitializeComponent的区别 在VB.NET和C#中&#xff0c;InitializeComponent 方法的调用方式有所不同。 C#: 在C#中&#xff0c;InitializeComponent 方法通常是在构造函数中显式调用的。它用于初始化窗体和控件的属性。代码示例如下&#xff1a; public pa…...

【数据结构与算法 刷题系列】求带环链表的入环节点(图文详解)

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法 经典例题》C语言 期待您的关注 ​ 目录 一、问题描述 二、解题思路 方法一&#xff1a;数学公式推导法 方法…...

独立游戏之路:Tap篇 -- Unity 集成 TapTap 广告详细步骤

Unity 集成 TapADN 广告详细步骤 前言一、TapTap 广告介绍二、集成 TapTap 广告的步骤2.1 进入广告后台2.2 创建广告计划2.3 选择广告类型三、代码集成3.1 下载SDK3.2 工程配置3.3 源码分享四、常见问题4.1 有展现量没有预估收益 /eCPM 波动大?4.2 新建正式媒体找不到预约游戏…...

设计灵感源泉!7个令人赞叹的网页界面设计展示

网页的界面设计主要是指视觉设计和风格设计。高质量的界面更容易吸引用户的注意力&#xff0c;从而更准确地向用户传达信息。对于设计师来说&#xff0c;他们需要从高质量的作品中获得稳定的灵感&#xff0c;以帮助他们更高效地实现设计目标。在本文中&#xff0c;梳理了7个高质…...

vivado PIN

描述 引脚是基元或层次单元上的逻辑连接点。引脚允许 要抽象掉单元格的内容&#xff0c;并简化逻辑以便于使用。引脚可以 是标量的&#xff0c;包含单个连接&#xff0c;或者可以定义为对多个进行分组的总线引脚 信号在一起。 相关对象 引脚连接到一个单元&#xff0c;并且可以…...

网络搭建教学视频/seo优化排名推广

启动nginx发现 nginx: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory 遂检查pcre的安装&#xff0c;由于是在测试安装脚本&#xff0c;遂检查安装是否成功&#xff0c;从脚本运行来看&#xff0c;是成功编译…...

昆明网站建站推广/黑帽seo优化推广

1、新建个文本文件 2、譬如输入: start iexplore.exe del.cnblogs.com 3、保存为 *.bat(保存时从保存类型选择"所有文件"), 譬如保存为 abc.bat 4、运行这个 abc.bat 文件转载于:https://www.cnblogs.com/del/archive/2008/07/26/1252139.html...

西安双语网站建设/搜索引擎优化的定义

为什么会有模块 我们最初只会有index.js的文件&#xff0c;后来随着业务的发展&#xff0c;这个代码发展到了1000多行&#xff0c;就很难读懂并且很难维护了了&#xff0c;因此我们就想到了分块&#xff0c;就是把相同业务逻辑的代码放在一起&#xff0c;这个就是模块.通常是会…...

昆明官方网站建设/福州百度推广电话

ExecutorService是java中的一个异步执行的框架&#xff0c;通过使用ExecutorService可以方便的创建多线程执行环境。 本文将会详细的讲解ExecutorService的具体使用。 创建ExecutorService 通常来说有两种方法来创建ExecutorService。 第一种方式是使用Executors中的工厂类…...

众筹网站建设 网站定制开发/中国万网官网登录

2008年6月&#xff0c;上海市宝山有线电视中心成功实施Mocha BSM。该项目的实施&#xff0c;使宝山有线电视中心能够更加快捷的进行IT运维管理&#xff0c;使IT管理人员从被动响应式的工作方式转变为主动服务&#xff0c;准确、快速地定位故障产生的根本原因。客户简介宝山有线…...

java 框架用来做网站/移动广告联盟

开发板&#xff1a;荔枝派zero linux&#xff1a;5.10 rootfs&#xff1a;buildroot 2017.8.1 使用最新的主线linux内核5.10&#xff0c;主线5.10内核linux make ARCHarm licheepi_zero_defconfig 默认打开了8723BS编译为模块且只能编译成模块 因为要加载固件到8723内部 编译后…...