基于资源管控+TiCDC实现多业务融合容灾测试

news2024/9/20 20:41:50

作者: 数据源的TiDB学习之路 原文来源: https://tidb.net/blog/959b8d07

背景

金融机构越来越多的选择将多套业务系统融合到一套分布式数据库集群来支撑,一方面可以节约硬件成本,另一方面可以简化运维复杂性。多租户能力及资源管控技术是数据库中实现多业务融合的最常用及有效手段。

容灾是金融机构 IT 系统满足高可用性必需的一个能力,金融机构的容灾能力根据高可用程度划分为多个等级,较常用的一种容灾部署方式是采用主备库的方案,在分布式数据库中也称为主备集群方案。

金融机构每年都有容灾切换演练的场景,根据系统重要等级不同,切换演练的频次也有所不同。对于 A 类业务系统,一般是每年覆盖一次;对于 B 类或 C 类系统,则可能是 2 年或更长时间循环覆盖一次。

在多业务融合的场景中,为了缩小切换演练的范围,避免切换演练对所有业务产生影响,金融企业期望底层数据库产品能支持单个租户 (应用) 的容灾切换能力。

构建基于 资源管控+TiCDC 的多业务融合容灾方案

TiDB 支持基于RU (Request Unit,资源单元) 的资源管控能力,方便解决多业务融合共享集群资源的场景。TiDB 也支持 TiCDC 实时同步工具,可以实现 TiDB 集群间的容灾方案。基于 TiDB 的资源管控及TiCDC,理论上可以实现一套多业务整合的容灾方案,并满足单个租户 (应用) 容灾切换而不影响其他租户的要求。

以下通过实际测试步骤来验证方案的可行性。

  1. 准备集群环境。

搭建 2 套相同节点数的 TiDB 测试环境,命名为 tidb-A 和 tidb-B,并分别安装部署 TiCDC 组件。

[tidb@host-10-17-3-151 packages]$ tiup cluster display tidb-A
tiup is checking updates for component cluster ...
Starting component `cluster`: /home/tidb/.tiup/components/cluster/v1.14.1/tiup-cluster display tidb-A
Cluster type:       tidb
Cluster name:       tidb-A
Cluster version:    v7.5.1
Deploy user:        tidb
SSH type:           builtin
Dashboard URL:      http://10.17.3.152:2379/dashboard
Grafana URL:        http://10.17.3.151:3000
ID                 Role          Host         Ports        OS/Arch        Status  Data Dir                            Deploy Dir
--                 ----          ----         -----        -------        ------  --------                            ----------
10.17.3.151:9093   alertmanager  10.17.3.151  9093/9094    linux/aarch64  Up      /data1/tidb-data/alertmanager-9093  /data1/tidb-deploy/alertmanager-9093
10.17.3.151:8300   cdc           10.17.3.151  8300         linux/aarch64  Up      /data1/cdc-free                     /data1/tidb-deploy/cdc-8300
10.17.3.152:8300   cdc           10.17.3.152  8300         linux/aarch64  Up      /data1/cdc-free                     /data1/tidb-deploy/cdc-8300
10.17.3.151:3000   grafana       10.17.3.151  3000         linux/aarch64  Up      -                                   /data1/tidb-deploy/grafana-3000
10.17.3.151:2379   pd            10.17.3.151  2379/2380    linux/aarch64  Up      /data1/tidb-data/pd-2379            /data1/tidb-deploy/pd-2379
10.17.3.152:2379   pd            10.17.3.152  2379/2380    linux/aarch64  Up|UI   /data1/tidb-data/pd-2379            /data1/tidb-deploy/pd-2379
10.17.3.153:2379   pd            10.17.3.153  2379/2380    linux/aarch64  Up|L    /data1/tidb-data/pd-2379            /data1/tidb-deploy/pd-2379
10.17.3.151:9095   prometheus    10.17.3.151  9095/12020   linux/aarch64  Up      /data1/tidb-data/prometheus-9095    /data1/tidb-deploy/prometheus-9095
10.17.3.151:4000   tidb          10.17.3.151  4000/10080   linux/aarch64  Up      -                                   /data1/tidb-deploy/tidb-4000
10.17.3.152:4000   tidb          10.17.3.152  4000/10080   linux/aarch64  Up      -                                   /data1/tidb-deploy/tidb-4000
10.17.3.153:4000   tidb          10.17.3.153  4000/10080   linux/aarch64  Up      -                                   /data1/tidb-deploy/tidb-4000
10.17.3.151:20160  tikv          10.17.3.151  20160/20180  linux/aarch64  Up      /data1/tidb-data/tikv-20160         /data1/tidb-deploy/tikv-20160
10.17.3.152:20160  tikv          10.17.3.152  20160/20180  linux/aarch64  Up      /data1/tidb-data/tikv-20160         /data1/tidb-deploy/tikv-20160
10.17.3.153:20160  tikv          10.17.3.153  20160/20180  linux/aarch64  Up      /data1/tidb-data/tikv-20160         /data1/tidb-deploy/tikv-20160
Total nodes: 14

[tidb@host-10-17-3-151 packages]$ tiup cluster display tidb-B
tiup is checking updates for component cluster ...
Starting component `cluster`: /home/tidb/.tiup/components/cluster/v1.14.1/tiup-cluster display tidb-B
Cluster type:       tidb
Cluster name:       tidb-B
Cluster version:    v7.5.1
Deploy user:        tidb
SSH type:           builtin
Dashboard URL:      http://10.17.3.151:12399/dashboard
Grafana URL:        http://10.17.3.151:13009
ID                 Role          Host         Ports        OS/Arch        Status  Data Dir                                Deploy Dir
--                 ----          ----         -----        -------        ------  --------                                ----------
10.17.3.151:19089  alertmanager  10.17.3.151  19089/19084  linux/aarch64  Up      /data1/tidb-re-data/alertmanager-19089  /data1/tidb-re-deploy/alertmanager-19089
10.17.3.151:8400   cdc           10.17.3.151  8400         linux/aarch64  Up      /data1/cdc-recover                      /data1/tidb-re-deploy/cdc-8400
10.17.3.152:8400   cdc           10.17.3.152  8400         linux/aarch64  Up      /data1/cdc-recover                      /data1/tidb-re-deploy/cdc-8400
10.17.3.151:13009  grafana       10.17.3.151  13009        linux/aarch64  Up      -                                       /data1/tidb-re-deploy/grafana-13009
10.17.3.151:12399  pd            10.17.3.151  12399/12390  linux/aarch64  Up|UI   /data1/tidb-re-data/pd-12399            /data1/tidb-re-deploy/pd-12399
10.17.3.152:12399  pd            10.17.3.152  12399/12390  linux/aarch64  Up|L    /data1/tidb-re-data/pd-12399            /data1/tidb-re-deploy/pd-12399
10.17.3.153:12399  pd            10.17.3.153  12399/12390  linux/aarch64  Up      /data1/tidb-re-data/pd-12399            /data1/tidb-re-deploy/pd-12399
10.17.3.151:19099  prometheus    10.17.3.151  19099/22029  linux/aarch64  Up      /data1/tidb-re-data/prometheus-19099    /data1/tidb-re-deploy/prometheus-19099
10.17.3.151:24000  tidb          10.17.3.151  24000/20090  linux/aarch64  Up      -                                       /data1/tidb-re-deploy/tidb-24000
10.17.3.152:24000  tidb          10.17.3.152  24000/20090  linux/aarch64  Up      -                                       /data1/tidb-re-deploy/tidb-24000
10.17.3.153:24000  tidb          10.17.3.153  24000/20090  linux/aarch64  Up      -                                       /data1/tidb-re-deploy/tidb-24000
10.17.3.151:30169  tikv          10.17.3.151  30169/30190  linux/aarch64  Up      /data1/tidb-re-data/tikv-30169          /data1/tidb-re-deploy/tikv-30169
10.17.3.152:30169  tikv          10.17.3.152  30169/30190  linux/aarch64  Up      /data1/tidb-re-data/tikv-30169          /data1/tidb-re-deploy/tikv-30169
10.17.3.153:30169  tikv          10.17.3.153  30169/30190  linux/aarch64  Up      /data1/tidb-re-data/tikv-30169          /data1/tidb-re-deploy/tikv-30169
Total nodes: 14
  1. 创建用户并绑定资源组。

分别在两套集群中创建 3 个用户 (userA、userB、userC) 及 3 个资源组 (rgA、rgB、rgC),用户和资源组一一绑定。分别使用不同用户在数据库中创建各自的 database,分别为 sbtest_a、sbtest_b、sbtest_c,它们代表不同业务系统的后台数据库。

mysql> create user userA;
Query OK, 0 rows affected (0.06 sec)

mysql> create user userB;
Query OK, 0 rows affected (0.05 sec)

mysql> create user userC;
Query OK, 0 rows affected (0.03 sec)

mysql> create resource group rgA RU_PER_SEC=1000;
Query OK, 0 rows affected (0.54 sec)

mysql> create resource group rgB RU_PER_SEC=2000;
Query OK, 0 rows affected (0.55 sec)

mysql> create resource group rgC RU_PER_SEC=3000;
Query OK, 0 rows affected (0.54 sec)

mysql> alter user userA resource group rgA;
Query OK, 0 rows affected (0.04 sec)

mysql> alter user userB resource group rgB;
Query OK, 0 rows affected (0.04 sec)

mysql> alter user userC resource group rgC;
Query OK, 0 rows affected (0.04 sec)

mysql> select user, user_attributes from mysql.user;
+-------+---------------------------+
| user  | user_attributes           |
+-------+---------------------------+
| root  | NULL                      |
| userA | {"resource_group": "rga"} |
| userB | {"resource_group": "rgb"} |
| userC | {"resource_group": "rgc"} |
+-------+---------------------------+
4 rows in set (0.01 sec)

mysql> alter user userA identified by 'userA123';
Query OK, 0 rows affected (0.05 sec)

mysql> alter user userB identified by 'userB123';
Query OK, 0 rows affected (0.04 sec)

mysql> alter user userC identified by 'userC123';
Query OK, 0 rows affected (0.04 sec)

mysql> create database sbtest_a;
Query OK, 0 rows affected (0.54 sec)

mysql> grant all on sbtest_a.* to userA;
Query OK, 0 rows affected (0.06 sec)

mysql> create database sbtest_b;
Query OK, 0 rows affected (0.54 sec)

mysql> grant all on sbtest_b.* to userB;
Query OK, 0 rows affected (0.03 sec)

mysql> create database sbtest_c;
Query OK, 0 rows affected (0.54 sec)

mysql> grant all on sbtest_c.* to userC;
Query OK, 0 rows affected (0.04 sec)

  1. 创建同步链路。

创建 3 条 TiCDC 同步链路 (changefeed),分别为 sbtest_a (集群 A) -> sbtest_a (集群 B) 、sbtest_b (集群 A) -> sbtest_b (集群 B) 、sbtest_c (集群 A) -> sbtest_c (集群 B) 。

[tidb@host-10-17-3-151 packages]$ cat changfeed_sbtest_a.toml
[filter]
rules = ['sbtest_a.*']
[tidb@host-10-17-3-151 packages]$ cat changfeed_sbtest_b.toml
[filter]
rules = ['sbtest_b.*']
[tidb@host-10-17-3-151 packages]$ cat changfeed_sbtest_c.toml
[filter]
rules = ['sbtest_c.*']

tiup cdc cli changefeed create --server=http://10.17.3.151:8300 --sink-uri="mysql://userA:userA123@10.17.3.151:24000/" --changefeed-id="sbtest-a-atob" --config=changfeed_sbtest_a.toml
tiup cdc cli changefeed create --server=http://10.17.3.151:8300 --sink-uri="mysql://userB:userB123@10.17.3.151:24000/" --changefeed-id="sbtest-b-atob" --config=changfeed_sbtest_b.toml
tiup cdc cli changefeed create --server=http://10.17.3.151:8300 --sink-uri="mysql://userC:userC123@10.17.3.151:24000/" --changefeed-id="sbtest-c-atob" --config=changfeed_sbtest_c.toml

[tidb@host-10-17-3-151 packages]$ tiup cdc cli changefeed list --server=http://10.17.3.151:8300
tiup is checking updates for component cdc ...
Starting component `cdc`: /home/tidb/.tiup/components/cdc/v7.5.1/cdc cli changefeed list --server=http://10.17.3.151:8300
[
  {
    "id": "sbtest-a-atob",
    "namespace": "default",
    "summary": {
      "state": "normal",
      "tso": 451948847132835850,
      "checkpoint": "2024-08-19 14:13:51.360",
      "error": null
    }
  },
  {
    "id": "sbtest-b-atob",
    "namespace": "default",
    "summary": {
      "state": "normal",
      "tso": 451948847132835850,
      "checkpoint": "2024-08-19 14:13:51.360",
      "error": null
    }
  },
  {
    "id": "sbtest-c-atob",
    "namespace": "default",
    "summary": {
      "state": "normal",
      "tso": 451948847132835850,
      "checkpoint": "2024-08-19 14:13:51.360",
      "error": null
    }
  }
]
  1. 模拟业务。

运行 3套 sysbench 测试,模拟 3 个业务场景。第 1 套 sysbench 测试使用 userA 用户连接到集群 A 的 sbtest_a,第 2 套 sysbench 测试使用 userB 用户连接到集群 A 的 sbtest_b,第 3套 sysbench 测试使用 userC 用户连接到集群 A 的 sbtest_c。

sh run_sysbench_a.sh auto

sh run_sysbench_b.sh auto

sh run_sysbench_c.sh auto

查看各资源组 RU 使用情况,可以看到都按照之前设置的1000 RU、2000 RU、3000 RU 使用到最大上限,且未出现超用的情况。

  1. 验证数据一致性。

停止 sysnbech 模拟测试,使用 sync-inspector 检验两边集群数据是否一致。

对比配置文件

[tidb@host-10-17-3-151 packages]$ cat sync-diff.toml
# Diff Configuration.

######################### Global config #########################

# 检查数据的线程数量,上下游数据库的连接数会略大于该值
check-thread-count = 4

# 如果开启,若表存在不一致,则输出用于修复的 SQL 语句。
export-fix-sql = true

# 只对比表结构而不对比数据
check-struct-only = false

# 如果开启,会跳过校验上游或下游不存在的表。
skip-non-existing-table = false

######################### Datasource config #########################
[data-sources]
[data-sources.tidba] # mysql1 是该数据库实例唯一标识的自定义 id,用于下面 task.source-instances/task.target-instance 中
    host = "10.17.3.151"
    port = 4000
    user = "userA"
    password = "userA123" # 设置连接上游数据库的密码,可为明文或 Base64 编码。

    #(可选)使用映射规则来匹配上游多个分表,其中 rule1 和 rule2 在下面 Routes 配置栏中定义
    route-rules = ["rule1"]

[data-sources.tidbb]
    host = "10.17.3.151"
    port = 24000
    user = "userA"
    password = "userA123" # 设置连接下游数据库的密码,可为明文或 Base64 编码。

    #(可选)使用 TLS 连接 TiDB
    # security.ca-path = ".../ca.crt"
    # security.cert-path = ".../cert.crt"
    # security.key-path = ".../key.crt"

    #(可选)使用 TiDB 的 snapshot 功能,如果开启的话会使用历史数据进行对比
    # snapshot = "386902609362944000"
    # 当 snapshot 设置为 "auto" 时,使用 TiCDC 在上下游的同步时间点,具体参考 <https://github.com/pingcap/tidb-tools/issues/663>
    # snapshot = "auto"

########################### Routes ###########################
# 如果需要对比大量的不同库名或者表名的表的数据,或者用于校验上游多个分表与下游总表的数据,可以通过 table-rule 来设置映射关系
# 可以只配置 schema 或者 table 的映射关系,也可以都配置
[routes]
[routes.rule1] # rule1 是该配置的唯一标识的自定义 id,用于上面 data-sources.route-rules 中
schema-pattern = "sbtest_a"      # 匹配数据源的库名,支持通配符 "*" 和 "?"
target-schema = "sbtest_a"         # 目标库名

######################### Task config #########################
# 配置需要对比的*目标数据库*中的表
[task]
    # output-dir 会保存如下信息
    # 1 sql:检查出错误后生成的修复 SQL 文件,并且一个 chunk 对应一个文件
    # 2 log:sync-diff.log 保存日志信息
    # 3 summary:summary.txt 保存总结
    # 4 checkpoint:a dir 保存断点续传信息
    output-dir = "./output2"

    # 上游数据库,内容是 data-sources 声明的唯一标识 id
    source-instances = ["tidba"]

    # 下游数据库,内容是 data-sources 声明的唯一标识 id
    target-instance = "tidbb"

    # 需要比对的下游数据库的表,每个表需要包含数据库名和表名,两者由 `.` 隔开
    # 使用 ? 来匹配任意一个字符;使用 * 来匹配任意;详细匹配规则参考 golang regexp pkg: https://github.com/google/re2/wiki/Syntax
    target-check-tables = ["sbtest_a.*"]

对比结果,3个 schema 的数据结果完全一致

[tidb@host-10-17-3-151 packages]$ ./tidb-community-toolkit-v7.5.1-linux-arm64/sync_diff_inspector --config=sync-diff-a.toml
A total of 5 tables need to be compared

Comparing the table structure of ``sbtest_a`.`sbtest1`` ... equivalent
Comparing the table structure of ``sbtest_a`.`sbtest2`` ... equivalent
Comparing the table structure of ``sbtest_a`.`sbtest4`` ... equivalent
Comparing the table structure of ``sbtest_a`.`sbtest3`` ... equivalent
Comparing the table structure of ``sbtest_a`.`sbtest5`` ... equivalent
Comparing the table data of ``sbtest_a`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest_a`.`sbtest3`` ... equivalent
Comparing the table data of ``sbtest_a`.`sbtest2`` ... equivalent
Comparing the table data of ``sbtest_a`.`sbtest4`` ... equivalent
Comparing the table data of ``sbtest_a`.`sbtest5`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 5 table have been compared and all are equal.
You can view the comparision details through './output3/sync_diff.log'

[tidb@host-10-17-3-151 packages]$ ./tidb-community-toolkit-v7.5.1-linux-arm64/sync_diff_inspector --config=sync-diff-b.toml
A total of 5 tables need to be compared

Comparing the table structure of ``sbtest_b`.`sbtest3`` ... equivalent
Comparing the table structure of ``sbtest_b`.`sbtest5`` ... equivalent
Comparing the table structure of ``sbtest_b`.`sbtest2`` ... equivalent
Comparing the table structure of ``sbtest_b`.`sbtest4`` ... equivalent
Comparing the table structure of ``sbtest_b`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest_b`.`sbtest3`` ... equivalent
Comparing the table data of ``sbtest_b`.`sbtest4`` ... equivalent
Comparing the table data of ``sbtest_b`.`sbtest5`` ... equivalent
Comparing the table data of ``sbtest_b`.`sbtest2`` ... equivalent
Comparing the table data of ``sbtest_b`.`sbtest1`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 5 table have been compared and all are equal.
You can view the comparision details through './output4/sync_diff.log'

[tidb@host-10-17-3-151 packages]$ ./tidb-community-toolkit-v7.5.1-linux-arm64/sync_diff_inspector --config=sync-diff-c.toml
A total of 5 tables need to be compared

Comparing the table structure of ``sbtest_c`.`sbtest1`` ... equivalent
Comparing the table structure of ``sbtest_c`.`sbtest4`` ... equivalent
Comparing the table structure of ``sbtest_c`.`sbtest5`` ... equivalent
Comparing the table structure of ``sbtest_c`.`sbtest3`` ... equivalent
Comparing the table structure of ``sbtest_c`.`sbtest2`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest4`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest5`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest3`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest2`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 5 table have been compared and all are equal.
You can view the comparision details through './output5/sync_diff.log'
  1. 切换单个同步链路。

模拟切换单个同步链路,选择 sbtest_c (集群 A) -> sbtest_c (集群 B)。首先需要停止 sbtest_c 上的业务并移除(或暂停)当前同步链路,其次重新构建反向同步链路 sbtest_c (集群 B) -> sbtest_c (集群 A),最后将模拟业务连接切换到集群 B 上。

删除正向同步链路:

tiup cdc cli changefeed remove --server=http://10.17.3.151:8300 --changefeed-id="sbtest-c-atob"
tiup cdc cli changefeed list --server=http://10.17.3.151:8300

此时观察到业务C对应的资源组的 RU 消耗为0,而另外两个资源组仍然在稳定运行当中。

搭建反向同步链路:

tiup cdc cli changefeed create --server=http://10.17.3.151:8400 --sink-uri="mysql://userC:userC123@10.17.3.151:4000/" --changefeed-id="sbtest-c-atob" --config=changfeed_sbtest_c.toml
tiup cdc cli changefeed list --server=http://10.17.3.151:8400

此时再查看各资源组 RU 使用情况,由于此时业务的主要压力来自于 TiCDC 同步过来的压力,所以跟直接在源库执行时会有差异,从图中看到平均使用 RU 数约为 500。

  1. 验证数据一致性。

重新启动 sbtest_c 上的业务并写入集群 B,运行一段时间后停止并验证切换后的 sbtest_c 两边数据是否一致,同时也验证原来的同步链路 sbtest_a 和 sbtest_b 数据是否仍然保持一致性同步。

//运行模拟业务c,并写入集群 B
sh run_sysbench_c_revers.sh auto

[tidb@host-10-17-3-151 packages]$ ./tidb-community-toolkit-v7.5.1-linux-arm64/sync_diff_inspector --config=sync-diff-c.toml
A total of 5 tables need to be compared

Comparing the table structure of ``sbtest_c`.`sbtest3`` ... equivalent
Comparing the table structure of ``sbtest_c`.`sbtest1`` ... equivalent
Comparing the table structure of ``sbtest_c`.`sbtest5`` ... equivalent
Comparing the table structure of ``sbtest_c`.`sbtest4`` ... equivalent
Comparing the table structure of ``sbtest_c`.`sbtest2`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest5`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest4`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest3`` ... equivalent
Comparing the table data of ``sbtest_c`.`sbtest2`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 5 table have been compared and all are equal.
You can view the comparision details through './output5/sync_diff.log'

问题记录

问题1:CDC 报错 Error 1044 Access denied for user xxx

解决:用户权限不足,执行 GRANT ALL PRIVILEGES ON `sbtest_a`.* TO 'userA'@'%';

mysql> show grants for userA;
+-----------------------------------+
| Grants for userA@%                |
+-----------------------------------+
| GRANT USAGE ON *.* TO 'userA'@'%' |
+-----------------------------------+
1 row in set (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON `sbtest_a`.* TO 'userA'@'%';
Query OK, 0 rows affected (0.05 sec)

mysql> show grants for userA;
+-----------------------------------------------------+
| Grants for userA@%                                  |
+-----------------------------------------------------+
| GRANT USAGE ON *.* TO 'userA'@'%'                   |
| GRANT ALL PRIVILEGES ON `sbtest_a`.* TO 'userA'@'%' |
+-----------------------------------------------------+
2 rows in set (0.00 sec)

添加完权限后, changefeed 任务并不会自动更新,需要先 pause 再 resume。

tiup cdc cli changefeed pause --server=http://10.17.3.151:8300 --changefeed-id="sbtest-a-atob"
tiup cdc cli changefeed resume --server=http://10.17.3.151:8300 --changefeed-id="sbtest-a-atob"

问题2:sync-diff-inspector 报错 SHOW command denied to user 'userC'@'%'SHOW command denied to user 'userC'@'%'

解决:原因是 changfeed 定义的连接下游数据库用户对要同步的对象不具有 SELECT 等权限,重新删除 changefeed 并创建

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【电控笔记z26】串级PID单环位置PID

1P-PI 传函(梅森法) : 2PI-P 3PID 三者等效

HyperMesh概述与有限元分析简介

1.1 HyperMesh 概述 本节将介绍有限单元法基本原理&#xff0c;HyperMesh 软件基本功能及界面介绍&#xff0c;获取在线帮助等内容。 1.1.1 有限元分析方法简介 有限单元法&#xff08;FEM&#xff09;是一种可以精确预测复杂结构在外界载荷作用下响应的方法&#xff0c;该数…

问界都回暖了,是谁还在持续掉队?

文/王俣祺 导语&#xff1a;在8月份的最后一个完整周&#xff0c;国内汽车市场的销量表现全面提升&#xff0c;乘用车市场销量达到了46.6万辆车&#xff0c;环比增长13.1%。其中&#xff0c;新能源汽车销量达到24.2万辆&#xff0c;环比增长11.6%&#xff0c;市场渗透率达到了…

《探索现代JavaScript中的异步编程》

探索现代JavaScript中的异步编程 随着Web应用变得越来越复杂&#xff0c;前端开发中对异步处理的需求也日益增加。JavaScript 作为 Web 开发中最主要的语言之一&#xff0c;提供了多种异步编程的方法来帮助开发者编写高效、可维护的应用程序。本文将介绍几种现代 JavaScript 中…

P5928 [国家集训队] 文学 题解

Description 给定 n n n 个半平面 a i x b i y ≤ c i a_i xb_i y\le c_i ai​xbi​y≤ci​ 和 p p p 个关键点 ( x i , y i ) (x_i,y_i) (xi​,yi​)&#xff0c;第 i i i 个半平面有价格 w i w_i wi​&#xff0c;你需要选择一些半平面覆盖所有的关键点&#xff0c;同…

深入探索Elasticsearch:从零基础到实战精通的全方位指南

ElasticSearch 一、初识ElasticSearch1、ES的介绍2、索引3、正排索引3、倒排索引 一、安装1、下载2、检查是否启动 二、语法1、添加一个文档编辑2、批量插入3、搜索4、查询某个特定的字段5、根据id查询6、修改7、删除8、mapping 三、分词器 一、初识ElasticSearch 1、ES的介绍…

大型公司网络系统集成方案

一、前言 1.1.公司综合信息系统建设目标 -----------------------------------------------------3 1.2. 用户具体需求----------------------------------------------------------------------------4 1.3.公司综合信息系统建设原则 -------------------------------…

vue3+ts+mock实现增删改查json文件

1.代码结构图&#xff1a; 2.路由 import { createRouter, createWebHashHistory } from "vue-router";import Home from "/pages/home/index.vue"; import AppDetail from "/pages/app-detail/index.vue"; import PageDetail from "/pages…

hadoop生态圈(四)- MapReduce

目录 MapReduce的基本原理 MapReduce流程图 Map阶段执行流程 Reduce阶段执行流程 Shuffle机制 MapReduce解决的是海量数据计算 MapReduce的思想核心是“分而治之”。就是把一个复杂的问题按一定的“分解”方法分为规模较小的若干部分&#xff0c;然后逐个解决&#xff0c;…

作业0828

使用C手动封装一个顺序表&#xff0c;包含成员数组一个&#xff0c;成员变量N个 #include <iostream> #include <string>using namespace std;using datatype int;struct Seqlist { private:datatype *data NULL;int size 0;int len 0;public://初始化函数voi…

从零成本到高效能:免费报表工具在金融行业的实践与应用

在当今金融行业中&#xff0c;多样化的报表体系是支撑机构高效运营、精准决策的重要基石。这些报表不仅反映了金融机构的财务状况&#xff0c;还涵盖了风险管理、业绩评估、流动性管理及合规监管等多个维度。今天我将带领大家深入探讨金融行业中这些报表的多样性和重要性&#…

数据的存储3(第三十二天)

1.整形在内存中的存储&#xff08;补充&#xff09; 原码&#xff0c;反码&#xff0c;补码的概念 &#xff08;1&#xff09;正数的原码&#xff0c;反码&#xff0c;补码相同 &#xff08;2&#xff09;对于整数来说&#xff1a;数据存放内存中其实存放的就是补码 2.浮点…

最长的一帧学习 part3

文章目录 八、osgUtil:: SceneView::cull ()part1 初始化必要的SceneView类成员变量part2 立体显示的处理part3 执行SceneView::cullStage函数&#xff0c;它也是场景视图筛选工作的核心函数part3.1 首先统计场景中的遮挡节点&#xff08;OccluderNode&#xff09;&#xff0c;…

【python】关于判断空值None、判断len()=0,和 if not 的区别

如果我们问一个问题&#xff1a;如果一个东西是不存在的&#xff0c;那么它的长度是多少&#xff1f; 我一开始会不假思索地回答&#xff1a;都不存在了&#xff0c;长度肯定是0啦。 但是细想一下&#xff0c;它都不存在了&#xff0c;还怎么会有长度呢&#xff1f; 这就有点像…

【Java】数据类型与变量(二)

目录 3.变量 3.1什么是变量&#xff08;变量的概念&#xff09; 3.2语法格式 ​编辑​编辑3.3整型变量 3.3.1整型变量如何定义 ​编辑 3.3.2长整型变量 3.3.3短整型变量 3.3.4字节型变量 3.4浮点型变量 3.4.1双精度浮点型 3.4.2单精度浮点型 3.4.3单精度浮点型与双…

【大模型开源教程】Git开源教程「动手学大模型应用开发」,学微调也太简单了

LLM 正逐步成为信息世界的新革命力量&#xff0c;其通过强大的自然语言理解、自然语言生成能力&#xff0c;为开发者提供了新的、更强大的应用开发选择。随着国内外井喷式的 LLM API 服务开放&#xff0c;如何基于 LLM API 快速、便捷地开发具备更强能力、集成 LLM 的应用&…

AI搜索“懒人神器”,如何向谷歌和百度发起挑战?

“属于传统搜索的时代&#xff0c;已经彻底落幕了。” 2024年2月&#xff0c;全球IT分析与评估机构Gartner在一份报告中如此判断。同时该机构预测&#xff0c;到2026年&#xff0c;传统搜索引擎的搜索量将减少25&#xff05;。 与此同时&#xff0c;从最近公布的财报来看&…

源代码加密是什么?给源代码加密如何做?

一、源代码加密是什么&#xff1f; 源代码加密是一种通过特定的加密算法和工具对软件源代码文件进行保护的技术&#xff0c;使得只有授权用户才能解密和访问代码。加密技术可以防止未经授权的访问、阅读、修改或复制源代码。源代码加密&#xff0c;则是对源代码文件进行加密处…

Kubernetes高级调度2

一.Taint和Toleration 1.为什么使用taint &#xff08;1&#xff09;不让pod被部署到被设置为污点的节点上。 &#xff08;2&#xff09;不让master节点部署业务&#xff0c;只部署系统组件 &#xff08;3&#xff09;除了指点pod外&#xff0c;不想让节点部署其他pod 2.为…

解决ESP32 VScode环境报错:Something went wrong while trying to build the project。

当我在vscode开发esp32时&#xff0c;点击构建项目 报了个错。 说明&#xff1a;项目目录包含了中文字符&#xff0c;我给换成全英文路径&#xff0c;再次尝试 成功 改完发现还有问题&#xff0c;来到这个目录&#xff0c;里面的中文也要改成英文。&#xff08;不止&#xff0…