Apache Doris 2.1 核心特性 Variant 数据类型技术深度解析

在最新发布的 Apache Doris 2.1 新版本中,我们引入了全新的数据类型 Variant,对半结构化数据分析能力进行了全面增强。无需提前在表结构中定义具体的列,彻底改变了 Doris 过去基于 String、JSONB 等行存类型的存储和查询方式。为了让大家快速学习和使用 Doris Variant 数据类型,我们为大家提供了实操演示视频,详细展示使用方式和性能表现。

半结构化数据是一种灵活多变的数据形式,不受固定结构限制,无需事先定义固定的表结构,为数据存储和分析提供了强大的灵活性及便捷性。常见的半结构化数据包括 XML、JSON、日志文件等。半结构化数据被广泛应用于以下场景:

  • 电商平台可以利用半结构化数据来存储用户对产品的评价,这些评价包括文字、图片甚至视频。这种数据结构有助于进行复杂的情感分析和用户行为模式挖掘。

  • 移动应用利用半结构化数据记录用户行为数据,随着新功能的引入,用户行为的属性可能会发生改变。半结构化数据能够灵活适应这些变化,无需频繁修改数据库结构。

  • 车联网、物联网等场景可使用半结构化数据存储车辆传感器的实时信息,如速度、位置和油耗,提供高度灵活性以适应技术更新。这使得平台能够提供实时监控、故障预警和智能路线规划等服务,提升驾驶体验和车辆性能。

为应对半结构化数据的处理,Apache Doris 2.1 之前版本提供了两种解决方案:预定义表结构和直接将数据存储为 JSON 。虽然早期方案各有优势,但在解析性能、数据读取效率以及运维研发成本方面仍面临巨大的挑战。例如:将数据直接存储为 JSON 后,在查询时需要实时解析 JSON 数据 ,这将导致较高的 CPU/IO 消耗和查询延迟,尤其是在处理大量或复杂半结构化数据时,性能瓶颈尤为突出。此外,也由于缺乏预定义结构,查询优化将变得更加复杂,从而影响数据处理分析的效率。

全新 Variant 数据类型

在最新发布的 Apache Doris 2.1 新版本中,我们引入了全新的数据类型 Variant,对半结构化数据分析能力进行了全面增强。

Variant 数据类型支持存储半结构化数据,并支持存储包含不同数据类型(如整数、字符串、布尔值等)的复杂数据结构,无需提前在表结构中定义具体的列,彻底改变了 Doris 过去基于 String、JSONB 等行存类型的存储和查询方式。

Variant 类型擅长处理复杂多变的嵌套结构。在写入过程中,Variant 类型可以自动根据列的结构和类型推断列信息,并将其合并到现有表的 Schema 中,将 JSON 键及其对应的值灵活存储为动态子列。同时,一个表可以同时包含灵活的 Variant 对象列和预先定义类型的更严格的静态列,从而在数据存储、查询上提供了更大的灵活性,这种写入方式为 Schema On Write。除此之外,Variant 类型能够与 Doris 核心特性融合,利用列式存储、向量化引擎、优化器等技术,为用户带来极高性价比的查询性能及存储性能。

Variant 的引入,使得存储和查询性能上均有显著提升,相较于 JSON 类型,存储空间减少了约 65%,查询速度提升超 8 倍。

功能及使用介绍

建表:建表语法关键字variant

-- 无索引
CREATE TABLE IF NOT EXISTS ${table_name} (
    k BIGINT,
    v VARIANT
)
table_properties;

-- 在v列创建bloom filter
CREATE TABLE IF NOT EXISTS ${table_name} (
    k BIGINT,
    v VARIANT
)
...
properties("replication_num" = "1", "bloom_filter_columns" = "v");

查询:通过[]访问子列,子列的类型同样为Variant类型

SELECT v["properties"]["title"] from ${table_name}

接下来,我们使用 Github Events 数据展示 Variant 的建表、导入、查询。下面是其中一条格式化后的数据。

{
  "id": "14186154924",
  "type": "PushEvent",
  "actor": {
    "id": 282080,
    "login": "brianchandotcom",
    "display_login": "brianchandotcom",
    "gravatar_id": "",
    "url": "https://api.github.com/users/brianchandotcom",
    "avatar_url": "https://avatars.githubusercontent.com/u/282080?"
  },
  "repo": {
    "id": 1920851,
    "name": "brianchandotcom/liferay-portal",
    "url": "https://api.github.com/repos/brianchandotcom/liferay-portal"
  },
  "payload": {
    "push_id": 6027092734,
    "size": 4,
    "distinct_size": 4,
    "ref": "refs/heads/master",
    "head": "91edd3c8c98c214155191feb852831ec535580ba",
    "before": "abb58cc0db673a0bd5190000d2ff9c53bb51d04d",
    "commits": [""]
  },
  "public": true,
  "created_at": "2020-11-13T18:00:00Z"
}

01 建表

  • 创建 3 个 Variant 类型的列, actorrepopayload
  • 创建表的同时创建 payload 列的倒排索引 idx_payload
  • USING INVERTED 指定索引类型是倒排索引,用于加速子列的条件过滤
  • PROPERTIES("parser" = "english") 指定采用english 分词
CREATE DATABASE test_variant;

USE test_variant;

CREATE TABLE IF NOT EXISTS github_events (
    id BIGINT NOT NULL,
    type VARCHAR(30) NULL,
    actor VARIANT NULL,
    repo VARIANT NULL,
    payload VARIANT NULL,
    public BOOLEAN NULL,
    created_at DATETIME NULL,
    INDEX idx_payload (`payload`) USING INVERTED PROPERTIES("parser" = "english") COMMENT 'inverted index for payload'
)
DUPLICATE KEY(`id`)
DISTRIBUTED BY HASH(id) BUCKETS 10
properties("replication_num" = "1");

需要注意的是: 在 Variant 列上创建索引,如果 Payload 的子列较多时,可能会造成索引列过多,影响写入性能。如果全部是等值查询,可以在 Variant 上构建布隆过滤器来加速等值过滤,与倒排索引相比,布隆过滤器的索引写入性能会有明显提升。同一个 Variant 列的分词属性是相同的,如果有不同的分词需求,那么可以创建多个 Variant 分别指定索引属性。

02 使用 Stream Load 导入

导入 gh_2022-11-07-3.json,该数据是 Github Events 一个小时的数据,格式化后的一行数据为:

wget http://doris-build-hk-1308700295.cos.ap-hongkong.myqcloud.com/regression/variant/gh_2022-11-07-3.json

curl --location-trusted -u root:  -T gh_2022-11-07-3.json -H "read_json_by_line:true" -H "format:json"  http://127.0.0.1:18148/api/test_variant/github_events/_strea
m_load

{
    "TxnId": 2,
    "Label": "086fd46a-20e6-4487-becc-9b6ca80281bf",
    "Comment": "",
    "TwoPhaseCommit": "false",
    "Status": "Success",
    "Message": "OK",
    "NumberTotalRows": 139325,
    "NumberLoadedRows": 139325,
    "NumberFilteredRows": 0,
    "NumberUnselectedRows": 0,
    "LoadBytes": 633782875,
    "LoadTimeMs": 7870,
    "BeginTxnTimeMs": 19,
    "StreamLoadPutTimeMs": 162,
    "ReadDataTimeMs": 2416,
    "WriteDataTimeMs": 7634,
    "CommitAndPublishTimeMs": 55
}

确认数据导入成功

-- 查看行数
mysql> select count() from github_events;
+----------+
| count(*) |
+----------+
|   139325 |
+----------+
1 row in set (0.25 sec)

-- 随机看一条数据
mysql> select * from github_events limit 1;
+-------------+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+---------------------+
| id          | type      | actor                                                                                                                                                                                                                       | repo                                                                                                                                                     | payload                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | public | created_at          |
+-------------+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+---------------------+
| 25061821748 | PushEvent | {"gravatar_id":"","display_login":"jfrog-pipelie-intg","url":"https://api.github.com/users/jfrog-pipelie-intg","id":98024358,"login":"jfrog-pipelie-intg","avatar_url":"https://avatars.githubusercontent.com/u/98024358?"} | {"url":"https://api.github.com/repos/jfrog-pipelie-intg/jfinte2e_1667789956723_16","id":562683829,"name":"jfrog-pipelie-intg/jfinte2e_1667789956723_16"} | {"commits":[{"sha":"334433de436baa198024ef9f55f0647721bcd750","author":{"email":"98024358+jfrog-pipelie-intg@users.noreply.github.com","name":"jfrog-pipelie-intg"},"message":"commit message 10238493157623136117","distinct":true,"url":"https://api.github.com/repos/jfrog-pipelie-intg/jfinte2e_1667789956723_16/commits/334433de436baa198024ef9f55f0647721bcd750"}],"before":"f84a26792f44d54305ddd41b7e3a79d25b1a9568","head":"334433de436baa198024ef9f55f0647721bcd750","size":1,"push_id":11572649828,"ref":"refs/heads/test-notification-sent-branch-10238493157623136113","distinct_size":1} |      1 | 2022-11-07 11:00:00 |
+-------------+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+---------------------+
1 row in set (0.23 sec)

使用desc查看 Schema 信息,子列会在存储层自动扩展,并进行类型推导:

-- 未开启扩展列展示
mysql> desc github_events;
+------------+-------------+------+-------+---------+-------+
| Field      | Type        | Null | Key   | Default | Extra |
+------------+-------------+------+-------+---------+-------+
| id         | BIGINT      | No   | true  | NULL    |       |
| type       | VARCHAR(30) | Yes  | false | NULL    | NONE  |
| actor      | VARIANT     | Yes  | false | NULL    | NONE  |
| repo       | VARIANT     | Yes  | false | NULL    | NONE  |
| payload    | VARIANT     | Yes  | false | NULL    | NONE  |
| public     | BOOLEAN     | Yes  | false | NULL    | NONE  |
| created_at | DATETIME    | Yes  | false | NULL    | NONE  |
+------------+-------------+------+-------+---------+-------+
7 rows in set (0.01 sec)

-- 开启Variant扩展列展示
mysql> set describe_extend_variant_column = true;
Query OK, 0 rows affected (0.01 sec)

mysql> desc github_events;
+------------------------------------------------------------+------------+------+-------+---------+-------+
| Field                                                      | Type       | Null | Key   | Default | Extra |
+------------------------------------------------------------+------------+------+-------+---------+-------+
| id                                                         | BIGINT     | No   | true  | NULL    |       |
| type                                                       | VARCHAR(*) | Yes  | false | NULL    | NONE  |
| actor                                                      | VARIANT    | Yes  | false | NULL    | NONE  |
| actor.avatar_url                                           | TEXT       | Yes  | false | NULL    | NONE  |
| actor.display_login                                        | TEXT       | Yes  | false | NULL    | NONE  |
| actor.id                                                   | INT        | Yes  | false | NULL    | NONE  |
| actor.login                                                | TEXT       | Yes  | false | NULL    | NONE  |
| actor.url                                                  | TEXT       | Yes  | false | NULL    | NONE  |
| created_at                                                 | DATETIME   | Yes  | false | NULL    | NONE  |
| payload                                                    | VARIANT    | Yes  | false | NULL    | NONE  |
| payload.action                                             | TEXT       | Yes  | false | NULL    | NONE  |
| payload.before                                             | TEXT       | Yes  | false | NULL    | NONE  |
| payload.comment.author_association                         | TEXT       | Yes  | false | NULL    | NONE  |
| payload.comment.body                                       | TEXT       | Yes  | false | NULL    | NONE  |
....
+------------------------------------------------------------+------------+------+-------+---------+-------+
406 rows in set (0.07 sec)

desc 可以指定 Partition 查看某个 Partition 的 Schema, 语法如下:

DESCRIBE ${table_name} PARTITION ($partition_name);

03 查询

需要注意的是:在使用过滤和聚合等功能查询子列时,需对子列执行额外的 CAST 操作,以确保数据类型一致性。这是因为存储类型可能不固定,需要通过 SQL 的CAST表达式来统一数据类型。例如,可以使用 SELECT * FROM tbl WHERE CAST(var['title'] AS TEXT) MATCH 'hello world' 来进行查询。

以下简化的示例说明如何使用 Variant 进行查询,下面是典型的三个查询场景:

1. 从 github_events 表中获取 Top5 Star 数的代码库

mysql> SELECT
    ->     cast(repo["name"] as text) as repo_name, count() AS stars
    -> FROM github_events
    -> WHERE type = 'WatchEvent'
    -> GROUP BY repo_name
    -> ORDER BY stars DESC LIMIT 5;
+--------------------------+-------+
| repo_name                | stars |
+--------------------------+-------+
| aplus-framework/app      |    78 |
| lensterxyz/lenster       |    77 |
| aplus-framework/database |    46 |
| stashapp/stash           |    42 |
| aplus-framework/image    |    34 |
+--------------------------+-------+
5 rows in set (0.03 sec)

2. 获取评论中包含doris的数量

mysql> SELECT
    ->     count() FROM github_events
    ->     WHERE cast(payload['comment']['body'] as text) MATCH 'doris';
+---------+
| count() |
+---------+
|       3 |
+---------+
1 row in set (0.04 sec)

3. 查询 Comments 最多的 Issue 号以及对应的库

mysql> SELECT 
    ->   cast(repo["name"] as string) as repo_name, 
    ->   cast(payload["issue"]["number"] as int) as issue_number, 
    ->   count() AS comments, 
    ->   count(
    ->     distinct cast(actor["login"] as string)
    ->   ) AS authors 
    -> FROM  github_events 
    -> WHERE type = 'IssueCommentEvent' AND (cast(payload["action"] as string) = 'created') AND (cast(payload["issue"]["number"] as int) > 10) 
    -> GROUP BY repo_name, issue_number 
    -> HAVING authors >= 4
    -> ORDER BY comments DESC, repo_name
    -> LIMIT 50;
+--------------------------------------+--------------+----------+---------+
| repo_name                            | issue_number | comments | authors |
+--------------------------------------+--------------+----------+---------+
| facebook/react-native                |        35228 |        5 |       4 |
| swsnu/swppfall2022-team4             |           27 |        5 |       4 |
| belgattitude/nextjs-monorepo-example |         2865 |        4 |       4 |
+--------------------------------------+--------------+----------+---------+
3 rows in set (0.03 sec)

04 注意事项

Variant 动态列与预定义静态列在效率上几乎相当。然而,对于处理类似日志数据的情况,经常需要动态添加字段,比如在 Kubernetes 中的容器标签。尽管 Variant 动态列提供了灵活性,但在写入时解析 JSON 和类型推断会增加额外的开销。

为了在处理大量动态属性和保持高效性之间取得一个平衡,我们建议在保持列数在 1000 以下的范围内。保持较少的列数有助于减少写入过程中的解析和类型推断开销,从而提高写入性能。

我们建议尽可能保证字段的类型一致性。这是因为 Doris 在处理数据时会自动进行兼容类型转换,将不同数据类型的字段进行统一处理。当字段无法进行兼容类型转换时,Doris 会将其统一转换为 JSONB 类型,JSONB 列的性能与 int、text 等列性能会有所退化。

Variant 性能对比

为了验证引入 Variant 数据类型后,在存储以及查询上所带来的优势,我们基于 Clickbench 数据对预定义静态列、Variant 数据类型、JSON 数据类型进行了测试,测试环境为一台配置为 16 核 64GB 内存的阿里云 ECS 实例,配备了 1TB ESSD 云盘,测试结果如下:

01 存储空间

通过下方存储空间占用情况可知,Variant 类型的存储空间基本与预定义静态列相当;而相比于 JSON 类型的存储, Variant 类型的存储空间减少了约65%, 仅占JSON类型存储空间1/3。在一些低基数场景,由于列存的优势空间占用减少会更加明显。

2.1-comparied-to-Json.png

02 查询性能

我们基于 Clickbench 43 个 SQL 进行了测试,如下表可知,Variant 类型与预定义静态列的查询性能差异在 10% 左右;而对于 JSON 类型来说,Variant 类型的查询速度相比于 JSON 类型提升了 8 倍以上(由于 I/O 原因,JSONB 类型的 冷查询大部分超时)。

2.1-comparied-to-Json-2.png

Variant 的设计实现

01 写入与类型推断

Apache Doris 写入流程是在 Memtable 中进行排序、合并并生成 Segment 文件。与之相同的是, Variant 的写入核心也是在 Memtable 中对相同的 JSON 键进行类型推导和合并,最后生成一颗前缀树。如下图所示,树上记录了每个 JSON Field 的类型信息以及 Column 信息,然后将同列的所有类型信息合并成最小公共类型,生成列并编码成 Doris 中的存储格式追加写入到 Segment 中。

每个 Segment 文件不仅包含了经过类型编码压缩后的数据,还额外记录了动态生成列的元信息。这种设计确保了数据的完整性和可查询性,同时也提升了存储效率。与传统的原始文本存储方式相比,通过在内存中进行类型推导和合并,Variant 类型显著减少了磁盘上的存储空间占用,大幅增强了数据的压缩效果。

Doris Variant写入与类型推断.png

02 列变更(加列、列类型变更)

在写入过程中,会将上述前缀树所有叶子节点元信息和数据追加到 Segment 文件中,并对 Rowset 的元信息进行合并。以下为合并方式示例:

Doris 列变更.png

最终 ,Rowset 将使用最小公共列模式(Least Common Column Schema,即子列最多、子列类型是所有 Segment 最小公共类型的 Schema )作为合并后的元数据,从而实现列动态扩展、类型变更。因此,对于 Variant 来说,其存储的 Schema 可以认为由数据驱动产生,与 Doris 中传统的 Schema Change 流程不同,具备更大的灵活性。下图展示了类型变更的方向(只支持按箭头所指方向进行变更,JSONB 类型是所有类型的公共类型):

Doris Variant Rowset 元信息合并.png

03 索引以及查询加速

Variant 中的叶子节点是以列存的方式存储在 Segment 文件中,与静态预定义的列存储格式完全相同。因此,可以直接利用预定义列的优化技术,例如字典编码、向量化和索引(ZoneMap、倒排、BloomFilter 等)进行查询加速。由于相同的列在不同文件中可能具有不同的类型,因此在查询时需要用户指定一个类型作为 hint,例如下面的查询示例:

 -- var['title']是访问var这个variant字段下的title子列
 SELECT * FROM tbl where CAST(var['titile'] as text) MATCH "hello world"
 
 -- 如果var上有BloomFilter, 则利用BloomFilter加速等值过滤
 SELECT * FROM tbl where CAST(var['id'] as bigint) = 1010101

在处理谓词的时候, 会将此类谓词下推到存储层(Segment), 并在存储层判断存储类型是否与CAST操作的目标类型一致。 如果类型一致,将使用更高效的谓词过滤机制进行处理。这样可以减少不必要的数据读取和转换操作,从而提升查询性能。

04 稀疏列存储优化

针对 JSON 列特别稀疏的场景, 例如以下数据:

{"a":[1], "b":2, "c":3, "x_1" : 1,"x_2": "3"}
{"a":1, "b":2, "c":3, "x_1" : 1,"x_2": "3"}
{"a":4, "b":5, "c":6, "x_3" : 1,"x_4": "3"}
{"a":7, "b":8, "c":9, "x_5" : 1,"x_6": "3"}
...

a, b, c 较为稠密,几乎每行都有该字段, x_?列则特别稀疏(sparse),只有个别行有该字段。如果每列都进行列式存储,将会造成较大的存储层压力,并导致 Meta 急剧膨胀。

在该场景中,将数据导入到 Doris 时,系统会根据 Column 中 Null 值的占比,来判断列的稠密和稀疏程度。对于较为稀疏的列(Null 占比高),存储层将其打包成 JSONB 编码,并存储在单独列中。列存结构如下所示:

稀疏列存储优化.png

当启用稀疏列存储优化后,可降低存储 Meta 以及 Compaction 的压力,并提高了 Variant 的灵活性。 稀疏列的查询方式与其他列完全一致,用户不必关心实现。

用户案例

观测云是国内领先的可观测性平台,在过去使用 Elasticsearch 来存储采集到的日志数据和用户行为数据。在面对大量的用户自定义字段时,Elasticsearch 对于 Schemaless 支持有限、原有的 Dynamic Mapping 会频繁造成字段类型冲突导致数据丢失,严重依赖人工介入进行手动处理。同时 Elasticsearch 的写入占用过多资源、面对海量数据时的低聚合性能表现,这些不足严重限制了自身业务的发展。

为了应对这一系列挑战,观测云选择基于与飞轮科技进行联合共建,基于 Apache Doris 对原有架构进行升级,打造了新一代可观测性解决方案。通过引入倒排索引、Variant 数据类型以及相关优化项,极大地提升了日志数据的查询速度,并且机器成本得到极大幅度节省,同时解决了在使用 Elasticsearch 时遇到的一系列痛点,具体包括:

  • 彻底解决了 Elasticsearch 中动态映射的问题。相比于 Elasticsearch 的动态 Schema 和类型固定的限制,Doris 使用 Variant 实现了 Partition 区级别的 Schema 变更,使得类型处理更加高效和灵活。此外,Doris 没有列数上限的限制,从而更好地满足了 Schemafree 的需求。
  • 大幅降低写入操作的资源消耗,显著降低了写入时的 CPU 占用。
  • 在处理海量数据的聚合查询时,借助倒排索引和查询优化技术,Doris 能够更快速地进行复杂的聚合查询,提供更高效的数据分析能力;

在进行架构的升级后,观测云机器成本降幅高达 70%。在更少的机器数量下,整体查询性能提升了 2 倍以上,简单查询性能提升了超过 4 倍,仅使用 Elasticsearch 的 1/3 成本、获得 2~4 倍的性能提升,整体性价比提升了近 10 倍。不仅提高了观测云的运营效率,还为客户提供了更高效、经济的服务体验。

结束语

在 Apache Doris 2.1 版本发布之前,Variant 数据类型已向用户开放 POC 测试,并取得了许多用户的积极反馈和满意的测试结果。而在 Apache Doris 2.1 版本正式发版之时,Variant 数据类型这一特性已经具备了生产可用的能力,推荐有需求的用户使用。

未来,我们将基于 Variant 数据实现更轻量级的类型变化,为用户在调整和演进数据模型时提供更便捷、可靠的支持,以满足不断演变的数据需求,前文提到的列变更(加列、列类型变更)同样适用于之后的轻量级类型变化。同时,我们也计划引入更友好的数据导入解决方案,包括采用严格模式、支持更丰富的数据模型等,旨在满足不同用户群体的广泛需求。此外,我们将持续优化 Variant 数据类型,为用户带来更卓越的半结构化数据处理和查询体验。

最后,欢迎有需求的同学能够积极使用并反馈建议,并前往 Doris 问答论坛 进行交流互动~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/467799.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 实现程序的优雅退出

🏷️个人主页:牵着猫散步的鼠鼠 🏷️系列专栏:Java全栈-专栏 🏷️个人学习笔记,若有缺误,欢迎评论区指正 目录 前言 优雅停机是什么 SpringBoot如何实现优雅停机 合理杀死进程 法一&…

【nfs报错】rpc mount export: RPC: Unable to receive; errno = No route to host

NFS错误 问题现象解决方法 写在前面 这两天搭建几台服务器,需要使用nfs服务,于是六台选其一做服务端,其余做客户端,搭建过程写在centos7离线搭建NFS共享文件,但是访问共享时出现报错:rpc mount export: RPC…

基于单片机的家庭烟雾报警系统

摘要:本文主要针对家庭等小型应用场所, 提出基于以单片机CC2530 作为控制器的智能烟雾报警系统,通过MQ-2 气体传感器来检测烟雾浓度,在单片机的A/D模块转化后,并配合蜂鸣元器件实现声音报警功能。 【关键词】烟雾报警 单片机 烟雾传感器 由于科技的发展以及各类家电走入…

sentinel系统负载自适应流控

系统负载自适应流控 规则配置 规则创建 public class SystemRule extends AbstractRule {private double highestSystemLoad -1;private double highestCpuUsage -1;private double qps -1;private long avgRt -1;private long maxThread -1; }SystemRule类包含了以下几…

unity发布安卓获取读取权限

一、Player Settings 设置 Player Settings>Player>Other Settings> Android > Write Permission > External (SDCard). 二、代码 using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Andr…

配置LVS NAT模式

配置LVS NAT模式 环境准备 client1:eth0->192.168.88.10,网关192.168.88.5lvs1: eth0 -> 192.168.88.5;eth1->192.168.99.5web1:eth1->192.168.99.100;网关192.168.99.5web2:eth1->192.168…

【深度学习实践】面部表情识别,深度学习分类模型,mmpretrain用于分类的实用教程,多任务网络头

文章目录 数据集数据集的进一步处理转换training.csv转换validation.csv 剔除无法使用的图片数据选择mmpretrain框架来训练配置四个文件改写base model改写base datasetsschedulesdefault_runtime 总配置开始训练训练分析考虑在网络上增加facial_landmarks回归head考虑是否可以…

力扣-1351 统计有序矩阵中的负数

给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非严格递减顺序排列。 请你统计并返回 grid 中 负数 的数目。 示例 1: 输入:grid [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]] 输出:8 解释&…

基于stable diffusion的IP海报生成

【AIGC】只要10秒,AI生成IP海报,解放双手!!!在AIGC市场发展的趋势下,如何帮助设计工作者解放双手。本文将从图像生成方向切入,帮助大家体系化的学习Stable diffusion的使用,完成自有…

游戏发行商的重要意义:武汉灰京文化的角色和任务

游戏发行商在游戏产业中扮演着重要的角色,他们不仅是游戏内容的传播者,还肩负着众多重要任务。武汉灰京文化作为一家游戏发行商,具有重要意义,他们在测试、本地化、版本移植、分销平台关系、品牌战略制定、法务支持等方面承担着多…

【异质集成】高k复杂氧化物栅介质在GaN HEMTs上的异质集成

COMMUNICATIONS ENGINEERING | (2024) 3:15论文阅读。 文章讨论了高k复杂氧化物栅介质在宽带隙高电子迁移率晶体管(HEMTs)上的异质集成。 其核心内容的总结如下: 研究背景: 异质集成不同晶体材料因其在高性能多功能电子和光子…

mybatis-plus 的saveBatch性能分析

Mybatis-Plus 的批量保存saveBatch 性能分析 目录 Mybatis-Plus 的批量保存saveBatch 性能分析背景批量保存的使用方案循环插入使用PreparedStatement 预编译优点:缺点: Mybatis-Plus 的saveBatchMybatis-Plus实现真正的批量插入自定义sql注入器定义通用…

B002-springcloud alibaba 微服务环境搭建

目录 创建父工程创建基础模块创建用户微服务创建商品微服务创建订单微服务微服务调用 创建父工程 新建项目springcloud-alibaba&#xff0c;本工程不需要写代码&#xff0c;删除src 导包 <parent><groupId>org.springframework.boot</groupId><artifact…

语音识别:whisper部署服务器(远程访问,语音实时识别文字)

Whisper是OpenAI于2022年发布的一个开源深度学习模型&#xff0c;专门用于语音识别任务。它能够将音频转换成文字&#xff0c;支持多种语言的识别&#xff0c;包括但不限于英语、中文、西班牙语等。Whisper模型的特点是它在多种不同的音频条件下&#xff08;如不同的背景噪声水…

CentOS7使用Docker部署.net Webapi

1 准备WebApi项目 对于已存在的WebApi项目&#xff0c;需要添加Docker支持&#xff1b; 编码时&#xff0c;先设置好项目需要的端口号&#xff1a;program.cs中&#xff0c;app.Run("http://*:8000");设置端口为&#xff1a;8000在VS中&#xff0c;选中项目&#xf…

VSCode + PicGo + Github 实现markdown图床管理

目录 PicGo客户端VSvode插件 PicGo客户端 PicGo 是一个图片上传管理工具 官网&#xff1a;https://molunerfinn.com/PicGo/ github图传使用说明&#xff1a;https://picgo.github.io/PicGo-Doc/zh/guide/config.html#GitHub图床 步骤&#xff1a; 1、创建一个github公开仓库…

ELK集群实战

1、 Elasticsearch集群部署 服务器 安装软件主机名IP地址系统版本配置ElasticsearchElk10.12.153.180centos7.5.18042核4GElasticsearchEs110.12.153.178centos7.5.18042核4GElasticsearchEs210.12.153.179centos7.5.18042核4G 2、创建运行的ES普通用户 3、上传es的数据包 …

基于Spring Boot的研究生志愿填报辅助系统

摘 要 二十一世纪我们的社会进入了信息时代&#xff0c;信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针对这一…

软件杯 深度学习 python opencv 火焰检测识别 火灾检测

文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…

Elasticsearch数据存储优化方案

优化Elasticsearch数据存储有助于提升系统性能、降低成本、提高数据查询效率以及增强系统的稳定性和可靠性。通常我们再优化Elasticsearch数据存储会遇到一些问题&#xff0c;导致项目卡壳。以下是优化Elasticsearch数据存储的一些重要作用&#xff1a; 1、问题背景 在某些场景…