OceanBase 功能解析之 Binlog Service

news/2024/9/18 22:52:11/ 标签: oceanbase, 分布式数据库, Mysql兼容

前言

MySQL,是在全球广泛应用的开源关系型数据库,除了其稳定性、可靠性和易用性,他早期推出的二进制日志功能,即binlog,也是MySQL广受欢迎的原因。

MySQL binlog,即二进制日志,是 MySQL 中用于记录数据库更改的日志文件。自 MySQL 数据库较早地引入了 binlog,这项功能就为它赢得了开发者和企业用户的青睐。MySQL 的二进制日志以高效、易读的二进制格式存储了所有影响数据库状态变化的 SQL 语句,从而为数据库提供了数据集成、复制等多种强大的能力。多年积累下来,MySQL 生态也基于 binlog 逻辑复制能力做出了一些比较成熟的增量解析系统并被广泛使用在数据集成中,比如 Canal、Debezium 等。

OceanBase 数据库早期就推出了 MySQL 兼容模式,使得一些希望替换 MySQL 的用户能够以较小的成本切换到 OceanBase 数据库。考虑到 MySQL 生态系统中一些成熟的 binlog 增量解析系统已经被广泛使用,当用户从 MySQL 转向 OceanBase 数据库时,可以直接利用现有的 binlog 增量解析系统,这也加快了 OceanBase Binlog Service 的诞生。

OceanBase Binlog Service 提供了类似于 MySQL 的 binlog 功能,可以记录数据库的变更日志。这对于实现数据迁移、同步以及数据一致性检查至关重要。该服务使得 MySQL 用户能够利用熟悉的 binlog 方案来监控、备份,并通过数据复制保持 OceanBase 数据库实时更新。

MySQL binlog 逻辑复制架构

1719456500

MySQL 复制机制基于 binlog 来实现,具体来说,binlog 主要在 SQL 引擎层记录数据的逻辑更改,而非在事务引擎层通过 redo log 进行物理更改的记录。这样的设计思路背后有着明确的目的。

MySQL 旨在支持多种存储引擎,如 InnoDB、MyISAM 等,每种存储引擎都有其独特的特征和优势。通过在 SQL 引擎层以 binlog 形式记录数据变更,MySQL 实现了一种灵活的复制机制,它不仅支持多种存储引擎间的无缝数据复制,还允许不同存储引擎之间进行异构同步复制。换句话说,这种机制为数据的一致性和兼容性带来了极大的便利。

这种设计展现了其在保证数据复制灵活性和系统兼容性方面的优势。通过逻辑而非物理记录数据变更,MySQL 成功地整合了多样化的存储引擎特性,并在全球范围内被广泛应用于需要高度兼容性和灵活性的复制架构中。

另外,在大数据领域,MySQL binlog 起着至关重要的作用,因为它提供一种机制来实现数据变更捕获(Change Data Capture,CDC),这是数据处理和分析的关键组成部分。

以下是 binlog 在大数据环境中的重要作用。

  1. 数据同步:binlog 允许持续地监控和记录 MySQL 数据库中的所有数据更改,包括插入、更新和删除操作。这些实时数据流可以被大数据工具捕获并同步到数据湖、数据仓库或其它任何大数据处理系统中,以进行进一步分析。 
  2. 实时分析:通过从 binlog 中捕获实时变化,企业可以将这些数据推送到流处理引擎(如 Apache Kafka、Apache Flink 或 Apache Storm)进行实时分析,从而实现即时的业务洞察和决策。 
  3. 跨平台数据整合:在多种数据库和存储系统中维护数据的一致性是大数据环境中的一个挑战。binlog 通过CDC 工具,如 Canal 或 Debezium,将数据无缝地同步到 Hadoop、Apache Hive、Elasticsearch 或任何其他目标平台,解决了数据整合的需求。 
  4. 系统解耦:binlog 允许基于事件的数据架构设计,这意味着数据生产者(数据库)和消费者(如大数据处理服务)可以松耦合、独立扩展,既增加了系统的灵活性,也提高了系统的稳定性。 
  5. 历史数据审计和回溯:binlog 为审计过去的数据变更提供了机会,分析历史数据走势和模式对于预测分析以及审计跟踪都是必要的。 

MySQL binlog 特点

MySQL 在处理事务型存储引擎和非事务型存储引擎时 binlog 的行为实际是稍有些差异的,本文仅会讨论事务型存储引擎 InnoDB 的相关 binlog 行为。一是因为 MySQL 虽然支持多种存储引擎,但目前默认的存储引擎以及普遍被用户使用的都是 InnoDB 存储引擎;二是因为 OceanBase 数据库本身支持事务,在设计 OceanBase Binlog Service 兼容 MySQL binlog 时,也需要按 InnoDB 存储引擎的 binlog 行为来进行处理。

MySQL binlog 文件支持两种格式:Statement-Based Replication(SBR)和 Row-Based Replication(RBR)。SBR 格式记录了 SQL 语句本身及其相关上下文信息,其优势在于较低的磁盘空间需求。然而在特定情况下,SBR 可能导致复制的同步问题。相对地,RBR 格式记录了数据变更前后的具体值,无需附加会话上下文信息,避免了 SBR 所面临的问题,并且确保了复制的一致性。

针对如 Canal/Debezium 这类的 binlog 解析系统,仅支持 RBR 格式,考虑到 Canal/Debezium 等系统的兼容性及其在实现数据同步与集成方面的广泛应用,本文将专注于 RBR 格式下的 binlog,目的是实现对 Canal/Debezium 等增量解析系统的全面支持。 

MySQL 的 binlog 由两组文件组成:

  • 一组是 binlog 文件本身,由 1 至多个编号连续的 binlog 文件组成,如上图中的 mysql-bin.000001、mysql-bin.000002、mysql-bin.000003 等。
  • 另一组是 binlog 的索引文件,即上图中的 mysql-bin.index 。该文件仅仅是一个文本文件,记录了当前所有的 binlog 文件名,SHOW BINARY LOGS命令即是通过读取该索引文件而实现。

MySQL 的 binlog 文件是由不同类型的 event 组成,在 5.7 版本中约支持 40 种 event 类型。从 CDC 增量解析的角度来看,主要需关注 Format_desc、Previous_gtids、Gtid, Rotate、Query、Xid、Table_map、Write_rows、Update_rows、Delete_rows 等 event 类型,从事务的角度来说,一个事务的所有相关 binlog events 在 binlog 文件中都是连续的,即不同事务间的 events 不会有交叉,此外一个事务的所有 binlog events 也不会跨 binlog 文件。以下是通过SHOW BINLOG EVENTS列出的 binlog events 示例:

mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000009';
+------------------+------+----------------+------------+-------------+--------------------------------------------------------------------+
| Log_name         | Pos  | Event_type     | Server_id  | End_log_pos | Info                                                               |
+------------------+------+----------------+------------+-------------+--------------------------------------------------------------------+
| mysql-bin.000009 |    4 | Format_desc    | 1147473732 |         123 | Server ver: 5.7.35-log, Binlog ver: 4                              |
| mysql-bin.000009 |  123 | Previous_gtids | 1147473732 |         194 | ebd2d3b0-6399-11ec-86ea-0242ac110004:1-38                          |
| mysql-bin.000009 |  194 | Gtid           | 1147473732 |         259 | SET @@SESSION.GTID_NEXT= 'ebd2d3b0-6399-11ec-86ea-0242ac110004:39' |
| mysql-bin.000009 |  259 | Query          | 1147473732 |         353 | create database test                                               |
| mysql-bin.000009 |  353 | Gtid           | 1147473732 |         418 | SET @@SESSION.GTID_NEXT= 'ebd2d3b0-6399-11ec-86ea-0242ac110004:40' |
| mysql-bin.000009 |  418 | Query          | 1147473732 |         543 | use `test`; CREATE TABLE t1(id int primary key, v varchar(30))    |
| mysql-bin.000009 |  543 | Gtid           | 1147473732 |         608 | SET @@SESSION.GTID_NEXT= 'ebd2d3b0-6399-11ec-86ea-0242ac110004:41' |
| mysql-bin.000009 |  608 | Query          | 1147473732 |         733 | use `test`; CREATE TABLE t2(id int primary key, v varchar(30))    |
| mysql-bin.000009 |  733 | Gtid           | 1147473732 |         798 | SET @@SESSION.GTID_NEXT= 'ebd2d3b0-6399-11ec-86ea-0242ac110004:42' |
| mysql-bin.000009 |  798 | Query          | 1147473732 |         870 | BEGIN                                                              |
| mysql-bin.000009 |  870 | Table_map      | 1147473732 |         918 | table_id: 114 (test.t1)                                            |
| mysql-bin.000009 |  918 | Write_rows     | 1147473732 |         963 | table_id: 114 flags: STMT_END_F                                    |
| mysql-bin.000009 |  963 | Table_map      | 1147473732 |        1011 | table_id: 115 (test.t2)                                            |
| mysql-bin.000009 | 1011 | Write_rows     | 1147473732 |        1056 | table_id: 115 flags: STMT_END_F                                    |
| mysql-bin.000009 | 1056 | Xid            | 1147473732 |        1087 | COMMIT /* xid=57 */                                                |
| mysql-bin.000009 | 1087 | Gtid           | 1147473732 |        1152 | SET @@SESSION.GTID_NEXT= 'ebd2d3b0-6399-11ec-86ea-0242ac110004:43' |
| mysql-bin.000009 | 1152 | Query          | 1147473732 |        1224 | BEGIN                                                              |
| mysql-bin.000009 | 1224 | Table_map      | 1147473732 |        1272 | table_id: 114 (test.t1)                                            |
| mysql-bin.000009 | 1272 | Update_rows    | 1147473732 |        1328 | table_id: 114 flags: STMT_END_F                                    |
| mysql-bin.000009 | 1328 | Table_map      | 1147473732 |        1376 | table_id: 115 (test.t2)                                            |
| mysql-bin.000009 | 1376 | Update_rows    | 1147473732 |        1432 | table_id: 115 flags: STMT_END_F                                    |
| mysql-bin.000009 | 1432 | Xid            | 1147473732 |        1463 | COMMIT /* xid=61 */                                                |
| mysql-bin.000009 | 1463 | Gtid           | 1147473732 |        1528 | SET @@SESSION.GTID_NEXT= 'ebd2d3b0-6399-11ec-86ea-0242ac110004:44' |
| mysql-bin.000009 | 1528 | Query          | 1147473732 |        1600 | BEGIN                                                              |
| mysql-bin.000009 | 1600 | Table_map      | 1147473732 |        1648 | table_id: 114 (test.t1)                                            |
| mysql-bin.000009 | 1648 | Delete_rows    | 1147473732 |        1693 | table_id: 114 flags: STMT_END_F                                    |
| mysql-bin.000009 | 1693 | Xid            | 1147473732 |        1724 | COMMIT /* xid=67 */                                                |
| mysql-bin.000009 | 1724 | Rotate         | 1147473732 |        1771 | mysql-bin.000010;pos=4                                             |
+------------------+------+----------------+------------+-------------+--------------------------------------------------------------------+
28 rows in set (0.00 sec)

Canal/Debezium 的解析原理

Canal/Debezium 都是数据变更捕获(Change Data Capture,简称 CDC)工具,它们的核心作用是监控数据库中的变更并将这些变更以某种方式传播出去。尽管它们为不同的数据库生态系统提供服务(Canal 主要针对 MySQL,而 Debezium 支持多种数据库),但是它们都利用了相似的原理来解析和传递数据变更。

Canal/Debezium 模仿了 MySQL slave 的通信过程,对 MySQL 的 binlog 二进制格式进行解析,提取出数据的增加、删除、更新这些变更,并转换为统一的格式。

  1. 建立连接:Canal/Debezium 连接到 MySQL 主服务器,模拟从服务器的行为。 
  2. 请求 binlog:Canal/Debezium 请求 MySQL 发送 binlog,并指定从特定的位置开始。 
  3. 解析 binlog:Canal/Debezium 从连接中读取 binlog 流并将其解析为可识别的数据变更事件。 
  4. 转换数据:解析后的事件被转换为通用的消息格式,供后续的系统消费。 
  5. 传播变更:变更数据可以被发送到各种中间件或直接被其他系统使用,如消息队列(Kafka 等),监控系统,缓存或搜索引擎。 

Canal/Debezium 会将自己伪装成一个 slave,设置自己的server_idserver_uuid,再通过COM_BINLOG_DUMPCOM_BINLOG_DUMP_GTID协议来定位和拉取 binlog events。另外为了支持对 binlog 的解析,还要求binlog_formatbinlog_row_image两个系统变量必须为 ROW 和 FULL。

Canal/Debezium 做 binlog 解析时,主要关注事务本身的 DML 操作及 DDL 操作,所以对 binlog event 类型处理上主要以以下几种 binlog event 类型为主。此外还需要对一些控制类型的 binlog event 类型进行解析处理,比如 Format_desc、Rotate、Previous_gtids、Gtid 等。

event 类型说明
Query即可以表示一个事务的 BEGIN,也可以表示 DDL 操作。
Xid表示一个事务的 COMMIT。
Table_map在一个事务内,一条 DML SQL 会对一到多张表的数据变更,在进行 binlog 记录时,会把涉及到的每张表都产生一个 Table_map event 并将其写到 binlog 文件用于记录内部 table id 和对应的表名。Table_map events 会先于 DML 操作产生的所有 Write_rows/Update_rows/Delete_rows events 出现在该事务的 binlog evens 中。
Write_rowsINSERT 产生的 event 类型:一条 event 可以包含多行插入的记录,但都属于同一 table id。若一条 INSERT 插入了多行,会产生多条连续的该 event 类型。
Update_rowsUPDATE 产生的 event 类型:一条 event 可以包含多行记录的更改,但都属于同一 table id。若一条 UPDATE 更改了多行,会产生多条连续的该 event 类型。
Delete_rowsDELETE 产生的 event 类型:一条 event 可以包含多行记录的删除,但都属于同一 table id。若一条 DELETE 删除了多行,会产生多条连续的该 event 类型。

虽然 Write_rows/Update_rows/Delete_rows 中记录的变更的前、后的值,但其中记录的元信息部分并不包含对应表中的列名,所以 Canal/Debezium 在做 binlog 解析时,还需要在启动初始化时先查询 MySQL 的元信息获取到所有相关表的 schema 定义。另外,MySQL 提供 SQL 服务和 binlog 服务都是相同的地址和端口(默认为 3306 端口)。

OceanBase Binlog Service 兼容 MySQL binlog 技术架构

OceanBase Binlog Service 为兼容 MySQL binlog 而诞生,支持现有的 MySQL binlog 生态工具来同步 OceanBase,现有的 MySQL binlog 生态工具可以平滑切换至 OceanBase 数据库。

技术要点

OceanBase Binlog Service 整套主要包含三部分:OceanBase 数据库、OBProxy 和 OBLogProxy,其中 binlog 服务主要主体为 OBLogProxy。

整套系统的技术要点包括:

  • 按租户级别创建 binlog 服务(OceanBase 数据库为多租户设计,其中每一个“租户”对应一个 MySQL 实例)。
  • OceanBase 数据库 clog 经 obcdc 获取后,需要转换为 ROW 格式、 FULL image 的 binlog events, 然后按 binlog 文件的组织方式存储到 binlog 文件中,支持被多个下游 MySQL binlog 解析系统所共用、支持回拉等,同时支持被 MySQL binlog 工具分析等。
  • 支持 MySQL 通信协议。
    • 用于 binlog dump 的COM_BINLOG_DUMPCOM_BINLOG_DUMP_GTID本身也是 MySQL 通信协议的一部分,OBProxy 和 OBLogProxy 需识别和处理这两个协议指令。
    • Canal/Debezium 做 binlog 解析时。需查询 MySQL 的元信息获取相关表的 schema 定义,也需要检查 binlog 相关系统变量确认 binlog 格式是否符合预期。此外,Debezium 在进行 binlog dump 前,还支持全量基准数据的快照导出。这三类场景会涉及SELECTSHOW两类 SQL,这些 SQL 将通过 OBProxy 进行转发。
    • MySQL 的 SQL 服务和 binlog 服务都是通过相同的地址进行的(默认为 3306 端口),而 OceanBase 数据库的 SQL 服务是通过 OBProxy 地址进行访问(默认为 2883 端口),为了使 OceanBase 数据库的 binlog 服务和 SQL 服务统一完全兼容 MySQL 的能力,需要 OBProxy 支持 binlog dump 协议并将请求转发给对应的 OBLogProxy 实例。

术语

此处列出相关名词含义,以便更好地理解本文。

  • OceanBase 数据库:OceanBase 数据库集群。
  • OBProxy:OceanBase 的访问代理,SQL 和 binlog 协议及相关命令通过 OBProxy 作为统一入口进行访问。
  • OBLogProxy:OceanBase binlog 服务的主体。
  • MySQL binlog 生态工具:泛指 MySQL binlog 增量解析系统,如常见的 Canal/Debezium 等。
  • BC:OBLogProxy 中 binlog converter 子模块,拉取并解析 clog,再按照 binlog 格式转换为 binlog 文件。
  • BD:OBLogProxy 中 binlog dumper 子模块,对下游(MySQL binlog 生态系统)的订阅请求提供 binlog 订阅服务。
  • BCM:OBLogProxy 中 BC 的管理模块。
  • BDM:OBLogProxy 中 BD 的管理模块。

系统架构

1719456552

上图所示为 OceanBase Binlog Service 兼容 MySQL binlog 系统的整体技术架构。整体的交互流程如下:

  • 需要为 OceanBase 数据库租户创建 binlog 服务:相比于 MySQL 的 binlog 服务,这一步骤是 OceanBase Binlog Service 额外需要的操作,由用户在需要时进行创建。
    • 使用 MySQL Client 连接 OBLogProxy 后,发起CREATE BINLOGSQL 请求。
    • OBLogProxy 收到 CREATE BINLOG请求后,通过 BCM 创建 BC 子模块。
  • BC 子模块初始化完成后,使用 MySQL Client 通过 OBProxy 执行 binlog 相关 SQL 可以查看 binlog 的状态,这类 SQL 包括如下几种。OBProxy 需识别这些 SQL 并转发给对应的 OBLogProxy 实例,由 BCM 返回相关结果集。
    • SHOW MASTER STATUS
    • SHOW BINARY LOGS
    • SHOW BINLOG EVENTS
  • 使用 MySQL Client 通过 OBProxy 执行非 binlog 相关 SQL 查询时,由 OBProxy 直接查询对应 OceanBase 数据库实现。
  • MySQL binlog 生态工具(如 Canal/Debezium 等)向 OBproxy 发起COM_BINLOG_DUMPCOM_BINLOG_DUMP_GTID命令时,OBProxy 识别到这两个命令后,需将请求转发到对应 OBLogProxy 实例。OBLogProxy 收到COM_BINLOG_DUMPCOM_BINLOG_DUMP_GTID请求后,然后通过 BDM 创建一个 BD 子模块提供 binlog dump 服务。

尾声

OceanBase Binlog Service 的出现,是对现代数据库技术和 MySQL 生态兼容性的一次显著进步。随着数据库技术发展,用户需求的扩展,以及对于实时数据处理和分析的迫切需求,OceanBase Binlog Service 的推出不仅拓展了 MySQL 的功能,而且创造了一个适应分布式、多租户数据库环境的灵活解决方案。通过在现有的 MySQL binlog 生态中无缝地整合 OceanBase 数据库,用户能够在享受 OceanBase 数据库高性能、高扩展性、高可用性等优点的同时,还能够无缝地维持与现有基于 MySQL binlog 的应用和工具之间的兼容性,保持以往 MySQL binlog 的使用习惯。

技术角度来看,OceanBase Binlog Service 简化了数据变更捕捉和数据复制流程,使得数据迁移、同步、集成、审核和灾难恢复等流程更加平滑、高效。


http://www.ppmy.cn/news/1519388.html

相关文章

django之ForeignKey、OneToOneField 和 ManyToManyField

在Django中,ForeignKey、OneToOneField 和 ManyToManyField 是用于定义模型之间关系的字段类型。 ForeignKey ForeignKey 用于定义多对一的关系。例如,一个Employee可以属于一个Department,一个Department可以有多个Employee。 from djang…

String的基本特;String的内存分配;字符串拼接操作;intern()的使用;经典面试题

目录 String的基本特性String的内存分配字符串拼接操作intern()的使用经典面试题 String的基本特性 创建的两种方式 String s “a” //字面量的定义方式 String s2 new String(“fd”) String类声明为final,不可被继承,实现了Serializable接口&#xf…

昇腾AI处理器的计算核心 - AI Core即DaVinci Core

昇腾AI处理器的计算核心 - AI Core即DaVinci Core flyfish 从一段代码的解释开始 template <typename T> class GlobalTensor { public:void setGlobalBuffer(T* buffer, uint32_t buffersize) {// 在这里实现设置全局缓冲区的逻辑} };语法的说明&#xff0c;主要用于…

优化 Webpack 打包体积的思路

在现代前端开发中&#xff0c;优化 Webpack 打包体积是提升应用性能的重要手段。以下是一些有效的优化思路&#xff1a; 提取第三方库&#xff1a;将第三方库单独打包&#xff0c;并通过 CDN 引入。这样不仅减少了打包体积&#xff0c;还利用了 CDN 的缓存优势&#xff0c;提高…

索迪迈科技油罐车监控系统中车载摄像头的布局策略

随着科技的不断发展&#xff0c;车载监控系统在油罐车上的安装已经成为了一种趋势。这不仅大大降低了车辆的安全隐患与运营成本&#xff0c;更对石油运输企业优化资源配置、提高市场竞争力起到了积极的促进作用。那么&#xff0c;在油罐车监控系统中&#xff0c;如何合理布局车…

html table tbody deleteRow有残留?

html table tbody deleteRow有残留? 问题描述&#xff1a;这个问题描述的是在使用 HTML 的 deleteRow 方法从一个 table 的 tbody 中删除行时&#xff0c;表格中仍然存在某些行。 参考方法1&#xff1a;表格移除多行的时候, 移除行数字索引顺序要从大到小, 而不能从小到大。 …

【华为OD】2024D卷——查找众数与中位数

题目&#xff1a; 众数是指一组数据中出现次数量多的那个数&#xff0c;众数可以是多个。 中位数是指把一组数据从小到大排列&#xff0c;最中间的那个数&#xff0c;如果这组数据的个数是奇数&#xff0c;那最中间那个就是中位数&#xff0c;如果这组数据的个数为偶数&#xf…

【我的Android进阶之旅】使用TabLayout自定义一个TitleTabView

文章目录 零、效果图一、自定义一个TitleTabView1.1 自定义属性(attrs.xml 中)1.2 自定义TitleTabView1.3 TabItem的子布局1.4 颜色值二、在 XML 中使用 `TitleTabView`2.1 布局文件(XML)2.1.1属性说明三、在 Kotlin 中使用 `TitleTabView`:零、效果图 其中Tab 2是选中的效果…

【笔记】数据结构——8月27日

toc 静态链表 静态链表的存储结构 #define maxn 15struct space {int cur;int key; }s[maxn];int LocateElem_SL(SLinkList *s,ElemType e) {//在静态链表中查找第一个值为e的元素//若找到&#xff0c;则返回它在链表中的位置&#xff0c;否则返回0 is[0].cur;while(i&…

使用本地IP无法访问前端项目的问题

说明&#xff1a;记录一次使用本机IP无法访问前端项目的问题 场景&解决 前端项目在我本机电脑上部署完成&#xff0c;我想通过局域网的IP把地址发给测试&#xff0c;发现使用localhost和127.0.0.0都能访问到前端项目&#xff0c;但是这个地址只能在自己的电脑上访问。 解…

记一次学习--webshell绕过(利用清洗函数)

目录 样本 样本修改 样本 <?php $a array("t", "system"); shuffle($a); $a[0]($_POST[1]); 通过 shuffle 函数打乱数组,然后通过$a[0]取出第一个元素&#xff0c;打乱后第一个元素可能是t也可能是system。然后再进行POST传参进行命令执行。 这里抓…

使用 Puppeteer 在 PHP 中解决 reCAPTCHA 以进行网页抓取

您是否在抓取数据时遇到 reCAPTCHA 障碍&#xff1f;我也遇到过。这些 CAPTCHA 挑战会将简单的抓取任务变成一大障碍。但别担心&#xff0c;我有一个解决方案可以帮助您轻松绕过这些障碍。 在本博文中&#xff0c;我将引导您使用 Puppeteer&#xff08;一个功能强大的 Node.js…

瑞芯微RK3566开发板USB OTG模式介绍及命令切换,触觉智能EVB3566主板鸿蒙硬件厂商

一、USB OTG的模式 host模式&#xff08;下行&#xff09;&#xff1a;为u盘等设备供电&#xff0c;不可以进行调试&#xff0c;连接adb或者烧录等操作。 device模式&#xff08;上行&#xff09;&#xff1a;可以进行调试&#xff0c;连接adb或者烧录等操作&#xff0c;即US…

基于xr-frame实现微信小程序的人脸识别3D模型叠加AR功能(含源码)

前言 xr-frame是一套小程序官方提供的XR/3D应用解决方案&#xff0c;基于混合方案实现&#xff0c;性能逼近原生、效果好、易用、强扩展、渐进式、遵循小程序开发标准。xr-frame在基础库v2.32.0开始基本稳定&#xff0c;发布为正式版&#xff0c;但仍有一些功能还在开发&#…

商圣集团:数字创新,引领智慧生活新篇章

在全球化经济不断演进的大潮中&#xff0c;数字经济已成为推动社会进步的关键引擎&#xff0c;重塑着我们的生产与生活模式。商圣集团&#xff0c;以服务社会、创新驱动为核心价值观&#xff0c;致力于利用数字化技术&#xff0c;为个人和企业带来高效、便捷的服务体验&#xf…

OpenCV绘图函数(7)从一个椭圆定义中提取出多边形的顶点坐标函数ellipse2Poly()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 近似一个椭圆弧为一个多边形线。 函数 ellipse2Poly 计算近似指定椭圆弧的多边形线的顶点。它被 ellipse 函数所使用。如果 arcStart 大于 arcEn…

自学数据结构的网站

自学数据结构的网站有很多&#xff0c;以下是一些推荐的高质量和受欢迎的网站&#xff1a; LeetCode 描述&#xff1a;LeetCode是一个知名的在线编程训练平台&#xff0c;特别适合算法和数据结构的学习与练习。它提供了大量的编程题目&#xff0c;涵盖了从简单到困难的各个难度…

基于YOLO的车牌检测识别(YOLO+Transformer)

概述&#xff1a; 基于深度学习的车牌识别&#xff0c;其中&#xff0c;车辆检测网络直接使用YOLO侦测。而后&#xff0c;才是使用网络侦测车牌与识别车牌号。 车牌的侦测网络&#xff0c;采用的是resnet18&#xff0c;网络输出检测边框的仿射变换矩阵&#xff0c;可检测任意形…

「bug」nvitop ERROR: Failed to initialize curses

nvitop 作为一个优秀个 Nvidia显卡查询库&#xff0c;简单易用且显示信息十分丰富&#xff0c;相比 Nvidia-smi 更方便&#xff0c;简直是每个 开发人员必备的库&#xff0c;安装也十分方便&#xff0c;直接采用 pip install nvitop 即可&#xff0c;调用的时候也是直接在 Term…

【Python报错已解决】“ModuleNotFoundError: No module named ‘timm‘”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言&#xff1a;一、问题描述1.1 报错示例&#xff1a;当我们尝试导入timm库时&#xff0c;可能会看到以下错误信息。…