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

一文搞懂后端面试之不停机数据迁移【中间件 | 数据库 | MySQL | 数据一致性】

数据迁移方面的工作:

  • 重构老系统:使用新的表结构来存储数据
  • 单库拆分分库分表、分库分表扩容
  • 大表修改表结构定义

数据备份工具

MySQL上常用的两款数据备份工具:mysqldump和XtraBackup

mysqldump:一个用于备份和恢复数据库的命令行工具,允许用户导出MySQL数据库的结构、数据及与表之间的关系,以便在数据库发生问题时进行恢复。是一个逻辑备份工具,导出的内容是一条条SQL
XtraBackup:使用了InnoDB存储引擎的数据备份技术,支持增量备份和恢复,并且支持多主机备份和恢复。是一个物理备份工具,相当于直接复制InnoDB的底层存储文件。
在这里插入图片描述
如果你使用的不是 MySQL,可以自己收集一下你使用的数据库的工具。要注意分析这些工具的优缺点,尤其是导入导出速度以及可行的优化手段。

innodb_autoinc_lock_mode

innodb_autoinc_lock_mode是InnoDB引擎里面控制自增主键生成策略的参数,有三个取值:

  • 0:使用表自增键锁,但是锁在INSERT语句结束之后就释放了
  • 1:使用表自增锁,如果是普通的INSERT INTO VALUE 或者 INSERT INTO VALUES 语句,申请了主键就释放锁,而不是整个INSERT语句执行完毕才释放。如果是INSERT SELECT 等语句,因为无法确定究竟要插入多少行,所以都是整个INSERT语句执行完毕才释放。
  • 2:使用表自增锁,所有的语句都是申请了主键就立刻释放

在执行 INSERT INTO VALUES 的时候,不管插入多少行,都只申请一次主键,一次申请够,这些主键必然是连续的。所以你可以从返回的最后一个 ID 推测出全部 ID

面试准备

  • innodb_autoinc_lock_mode的值,这回影响主键生成策略,在数据迁移的时候需要考虑处理主键问题
  • 公司的binlog模式,在后面增量校验和修复数据里面使用的是行模式的binlog
  • 公司是否有统一的数据库规范,比如必须要更新时间戳、不能硬删除,只能软删除
  • 使用的ORM框架怎么实现双写
  • 公司是否做过数据迁移?如果做过,具体的方案是什么

重构系统:

这个系统是我们公司的一个核心系统,但是又有非常悠久的历史。在我刚接手的时候,它已经处于无法维护的边缘了。但是不管是重构这个系统,还是重新写一个类似的系统,已有的数据都是不能丢的。所以我的核心任务就是重新设计表结构,并且完成数据迁移。为此我设计了一个高效、稳定的数据迁移方案。

实际落地了单库拆分 分库分表

进公司的时候,刚好遇上单库拆分分库分表。我主要负责的事情就是设计一个数据迁移方案,把数据从单库迁移到分库分表上。

解决方案

数据迁移方案的基本步骤:

  1. 创建目标表
  2. 用源表数据初始化目标表
  3. 执行一次校验,并修复数据,此时用源表数据修复目标表数据
  4. 业务代码开启双写,读源表,并且先写源表,数据以源表为主
  5. 开启增量校验和数据修复,保持一段时间
  6. 切换双写顺序,此时读目标表,并且先写目标表,数据以目标表为准
  7. 继续保持增量校验和数据修复
  8. 切换为目标表单写,读写都只操作目标表

不考虑数据校验的话,整个数据迁移过程是这样的
在这里插入图片描述
图右边的两步都要考虑校验和修复数据的问题

初始化目标表数据

在创建了一个目标表之后,第一步是先尝试初始化目标数据,问题是你怎么拿到源表数据

基本思路有两个:

  1. 使用源表的历史备份
  2. 源表导出数据

以mysqldump为例 关键词是加快导入和导出速度

我选择了从源表导出数据,使用的是 mysqldump 工具。mysqldump 是一个开源的逻辑备份工具,优点是使用简单,能够直接导出整个数据库。缺点则是导出和导入的速度都比较慢,尤其是在数据量非常大的情况下。
所以我针对 mysqldump 做了一些优化,来提高导出和导入的性能。
加快导出速度能做的事情并不多,主要就是开启 extended-insert 选项,将多行合并为一个 INSERT 语句。
加快导入速度就可以做比较多的事情。

  • 关闭唯一性检查和外键检查,源表已经保证了这两项,所以目标表并不需要检查。
  • 关闭 binlog,毕竟导入数据用不着 binlog。
  • 调整 redo log 的刷盘时机,把 innodb_flush_log_at_trx_commit 设置为 0。

注意在第 2、3 点里面,可以把话题引向的 binlog 和 redolog 内容。反过来,你也可以利用 binlog 和 redolog 把话题引导到这一节课的内容,灵活应对就可以。

第一次校验与修复

在初始化数据之后,可以先尝试立刻校验和修复一下数据,因为如果你前面用的是备份数据,那么备份数据已经落后生产数据了
比如你用的是昨天的备份,那么今天的修改目标表就没有。还有如果你是导出的数据,那么导出数据到你导入数据的这段时间,数据发生了变化,目标表依旧是没有的。
如果你们公司有明确的数据库规范的话,比如说所有的表都需要有update_time这个字段,那么校验和修复的时候就可以采用增量的方案。因为只有update_time晚于你导出数据的时间点,才说明这一行的数据已经发生了变更。在修复的时候就直接用源表的数据覆盖掉目标表的数据。

业务开启双写,以源表为准

首先要解释清楚是怎么做到双写的。
支持双写大体上有两个方向:侵入式和非侵入式两种。
侵入式方案就是直接修改业务代码,要求业务代码在写了源表之后再写目标表。但是侵入式方案是不太可行的,或者说代价很高。因为这意味着所有的业务都要检查一遍,然后修改。既然修改了,自然还要测试。所以,一句话总结就是工作量大还容易出错

非侵入式一般和你使用的数据库中间件有关,比如ORM框架。这一类框架一般会提供两种方式来帮你解决类似的问题。

  • AOP(Aspect Oriented Program 面向切面编程)方案:不同框架有不同叫法,比如说可能叫做interceptor,middleware,hook,handler,filter。这个方案的关键是捕捉到发起的增删改调用,篡改为双写模式。
    在这里插入图片描述
  • 数据库抽象操作:可能叫做Session, Connection, Connection Pool, Executor等,就是将源表的操作修改为双写模式。

不管用哪种方案,都是确保一个东西,就是双写可以在运行期间随时切换状态,单写源表、先写源表、先写目标表、单写目标表都可以。
大多数时候都是利用一个标记位,然后你可以通过配置中心或者接口直接修改它的值。

在这里插入图片描述
以GORM为例

开启双写在 GORM 上面还是比较容易做到的。最开始我觉得可以考虑使用 GORM 的 Hook 机制,用 DELETE 和 SAVE 两个 Hook 就可以了。但是这要求我必须给每一个模型或表都定义类似的 Hook,还是比较麻烦的。后来我仔细翻了 GORM 的文档,确认可以考虑使用 GORM 的 ConnPool 接口。所以我用装饰器模式封装了两个数据源,每次执行语句的时候,都根据标记位来执行双写逻辑。

func (m *DouleWritePool) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {if m.mode == '源表优先' {err = m.source.QueryContext(ctx, query, args...)if err == nil {m.target.QueryContext(ctx, query, args...)}} else if {//...}
}

在双写的时候,可以往两个方向进一步刷亮点:数据一致性问题和主键问题

数据一致性问题

正常面试官都可能会问到,如果在双写过程中,写入源表成功了,但是写入目标表失败了,该怎么办?
最基础的回答就是不管

写入源表成功,但是写入目标表失败,这个是可以不管的。因为我后面有数据校验和修复机制,还有增量校验和修复机制,都可以发现这个问题。

然后可以提出一个曾经思考过但是最终没有实施的方案,这能够证明你在数据一致性上有过很深的思考。关键词是难以确定被影响的行

在设计方案的时候,我考虑过在写入目标表失败的时候,发一个消息到消息队列,然后尝试修复数据。但是这个其实很难做到,因为我不知道该修复哪些数据。比如一个UPDATE语句在目标表上执行失败,我没办法根据UPDATE语句推断出源表上哪些行被影响到了。

在这里插入图片描述

主键问题

如果在源表中使用的是自增主键,那么在双写的时候写入目标表要不要写入主键?答案是要的。
需要在写入源表的时候拿到自增主键,然后在写入目标表的时候设置好主键。因为其实你并不能确保目标表自增的主键和源表自增的主键是同一个值。比如在并发场景下两次插入。
在这里插入图片描述
因此你可以介绍你是如何处理这个问题的

在双写的时候比较难以处理的问题是自增主键问题。为了保持源表和目标表的数据完全一致,需要在源表插入的时候拿到自增主键的值,然后用这个值作为目标表插入的主键

在这里插入图片描述
此外还可以进一步展示一个更加高级的亮点,也就是我在前置知识里说到的innodb_autoinc_lock_mode 取值会影响到自增主键的连续性,抓住关键词 自增主键的连续性

在处理批量插入的时候更要小心一些。正常来说,批量插入如果使用的是VALUES语法,那么生成的主键是连续的,可以从返回的最后一个主键推测出前面其他行的主键。即使innodb_autoinc_lock_mode 的取值是2也能保证这一点。但是如果是多个INSERT INTO VALUE语句,或者INSERT SELECT语句,这些语句生成的主键就可能不连续。在双写之前,都要先改造这一类的业务

增量校验和数据修复

增量校验基本就是一边保持双写,一边校验最新修改的数据,如果不一致,就要进行修复。这里有两个方案。第一个方案是利用更新时间戳,比如说update_time这种列;第二个方案是利用binlog。相比之下binlog更加高级,在面试的时候应该优先考虑这个方案。

利用更新时间戳

利用更新时间戳的思路很简单,就是定时查询每一张表,然后根据更新时间戳来判断某一行数据有没有发生变化。

for {// 执行查询// SELECT * FROM xx WHERE update_time >= last_timerows := findUpdatedRows()for row in rows {// 找到目标行,要用主键来找,用唯一索引也可以,看你支持到什么程度tgtRow = findTgt(row.id)if row != tgtRow {// 修复数据fix()}}// 用这一批数据里面最大的更新时间戳作为下一次的起始时间戳last_time = maxUpdateTime(row)// 睡眠一下sleep(1s)
}

所以可以介绍基本的策略,关键词是更新时间戳

我们采用的方案是利用更新时间戳找出最近更新过的记录,然后再去目标表里面找到对应的数据,如果两者不相等,就用源表的数据去修复目标表的数据。这个方案有两个条件:所有的表都是更新时间戳的,并且删除是软删除的

在这里插入图片描述
这里提到的第二个条件就是准备展示的第一个亮点,你可以等面试官追问为什么必须是软删除,也可以自己接着回答。

如果不是软删除,那么源表删掉数据之后,如果目标表没删除,在我们的匹配逻辑里是找不到的。在这种场景下,还有一个补救措施,就是反向全量校验。也就是说从目标表里再次查询全量数据,再去源表里找对应的数据,如果源表里没找到,就说明源表已经删了数据,那么目标表就是可以删除数据了

在这里插入图片描述
接下来可以进一步展示第二个亮点,主从同步延迟引发的问题。假设你在校验和修复的时候,读的是从库,那么会遇到两种异常情况,一种是目标表主从延迟,另一种是源表主从延迟。
在这里插入图片描述
那么怎么解决呢?简单粗暴的方法就是全部读主库,校验和修复都以主库数据为准。缺点是对主库的压力比较大

更加高级的方案:双重校验

校验和修复的时候要小心主从同步的问题,如果校验和修复都是用从库的话,那么就会出现校验出错,或者修复出错的情况。按照道理来说,强制走主库就可以解决问题,但是这样对主库的压力比较大
所以我采用的是双重校验方案,第一次校验的时候读从库,如果发现数据不一致,再读主库,用主库的数据再校验一次。修复的时候就只能以主库数据为准。这种方案的基本前提是,主从延迟和数据不一致的情况是小概率的,所以最终会走到主库也是小概率的。

在这个回答里面你没有提到任何异常情况的具体场景,如果面试官问到了,就回答上面图里面的两种情况。这个亮点能够凸显你在主从延迟方面的积累,也会把话题引到主从模式和主从同步上,所以要做好准备。

利用binlog

binlog是一个更加高级的方案,它还有一些变种,所以理解和记忆的难度也更高一些。这里的binlog是基于行的binlog模式。
最简单的形态就是把binlog当作一个触发器,回答的关键词就是binlog触发

在校验和修复数据的时候,采用的是监听binlog的方案。binlog只用于触发校验和修复这个动作,当我收到binlog之后,会用binlog中的主键,去查询源表和目标表,再比较两者的数据。如果不一致,就用源表的数据去修复目标表。

在这里插入图片描述
如果更进一步,会觉得binlog里面本来就有数据,那么干嘛不直接用binlog里的数据?所以就有了第二个形态:binlog的数据被看作源表数据。

拿到binlog之后,我用主键去目标表查询数据,然后把binlog里面的内容和目标表的数据进行比较。如果数据不一致,再用binlog里的主键去源表里查询到数据,直接覆盖目标表的数据。

在这里插入图片描述
这里有一点不同,就是发现不一样之后,需要查询源表,再用查询到的数据去覆盖目标表的数据。因为你要防止binlog是很古老的数据,而目标表是更加新的数据这种情况

紧接着,会发现目标表也有binlog,所以干嘛不直接比较源表的binlog和目标表的binlog?如果binlog不一样,那不就说明是目标表那边出了问题吗?
这种方案理论上是可行的,但是它有两个非常棘手的问题。

  1. 一次双写,可能立刻就收到了源表的 binlog,但是你过了好久才收到目标表的 binlog。反过来,先收到目标表的 binlog,隔了很久才收到源表的 binlog 也一样。所以你需要缓存住一端的 binlog,再等待另外一端的 binlog
  2. 顺序问题,如果有两次双写操作的是同一行,那么你可能先收到源表第一次的 binlog,再收到目标表第二次双写的 binlog,你怎么解决这个问题呢?你只能考虑利用消息队列之类的东西给 binlog 排个序,确保 binlog 收到的顺序和产生的顺序一致

虽然能够进一步减轻数据库查询的压力,但是实在过于复杂,得不偿失。

切换双写顺序

这一步本身就是一个亮点。因为很多人都是在双写的时候直接切换到目标表单写。但是这样直接切换的风险太大了,万一出了问题都没法回滚。
在这里插入图片描述
所以中间要引入一个双写的时候先写目标表,且业务读目标表的步骤,这样万一切换到写目标表出了问题还可以回滚。

介绍这一步的时候补充说明一下

引入这一步,是为了能够在切换到以目标表为准之前有一个过渡阶段。也就是说,通过先写目标表,再写源表这种方式,万一发现数据迁移出现了问题,还可以回滚为先写源表,再写目标表,确保业务没有问题。

在这里插入图片描述

保持增量校验和修复

在切换了双写顺序之后,保持增量校验和修复是顺理成章的,方案和步骤5一样,不过步骤5的校验和修复都是以源表为准,那么在这一步,就是以目标表为准

  • 不管什么先后顺序、什么并发问题,在修复的时候你永远用主表的最新数据去修复,绝对不会出问题
  • 如果源表或者目标表本身也是分库分表的,那么无非就是查询、修复数据的时候使用对应的分库分表规则而已
  • 整个方案在第八步之前,都是可以回滚的。一旦切换到第八步,就不可能回滚了。

相关文章:

一文搞懂后端面试之不停机数据迁移【中间件 | 数据库 | MySQL | 数据一致性】

数据迁移方面的工作: 重构老系统:使用新的表结构来存储数据单库拆分分库分表、分库分表扩容大表修改表结构定义 数据备份工具 MySQL上常用的两款数据备份工具:mysqldump和XtraBackup mysqldump:一个用于备份和恢复数据库的命令…...

【ESP01开发实例】- ISD1820录音控制

ISD1820录音控制 文章目录 ISD1820录音控制1、ISD1820模块介绍2、硬件准备及接线3、代码以实现录音技术已经取得了长足的进步,它已成为从语音助手到安全系统的各种应用不可或缺的一部分。如果您有兴趣构建自己的录音系统,将 ISD1820 模块与 ESP01 微控制器相结合可能是一个不…...

Linux驱动面试高频考点后面继续改整理

Linux驱动开发是将硬件设备与操作系统内核连接起来的重要环节,它涉及到设备模型、中断处理、文件操作等方面,是一项挑战性且充满乐趣的工作。今天给大家分享45道Linux驱动面试高频考点,直接上干货。 1、驱动程序分为几类? 内核驱动…...

【Python】nn.ConvTranspose1、2、3d()函数详解和示例

前言 在深度学习中,特别是在处理图像、音频和三维数据时,转置卷积(Transposed Convolution)或称为反卷积(Deconvolution)是一种非常重要的操作。PyTorch提供了nn.ConvTranspose1d、nn.ConvTranspose2d和nn…...

vtkConnectivityFilter提取连通区域中的问题

直接使用vtkConnectivityFilter提取连通区域&#xff0c;渲染上没问题&#xff0c;但是打印出polydata中的点数&#xff0c;发现跟原始数据是一致的。 for (int i 0; i < numRegions; i){vtkSmartPointer<vtkConnectivityFilter> connectivityFilter vtkSmartPointe…...

购物系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;商品分类管理&#xff0c;商品信息管理&#xff0c;特价商品管理&#xff0c;用户管理&#xff0c;留言板管理&#xff0c;订单管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&…...

做报表用什么工具?不想再用Excel了!!!

一、什么是中国式报表&#xff1f; 不知道大家现在还是使用Excel来制作报表&#xff0c;然后跟领导汇报工作吗&#xff1f;虽然Excel功能很强大&#xff0c;但是用Excel做过中国式报表的小伙伴一定知道它的制作过程有多复杂。 中国式报表可以用一句话简单概括&#xff1a;格式…...

c++实现学生管理系统(附源码)

目录 一、基本功能&#xff1a; 二、包含的模块&#xff1a; 三、系统介绍 1. 学生管理系统的功能&#xff1a; 2. 具体的需求&#xff1a; 3. 支持的标准&#xff1a; 四、系统结构功能图&#xff1a; 五、系统设计 1. 退出系统&#xff1a; 2. 增加学生&#xff1a…...

JS防抖是什么?干嘛用的?

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏和关注&#xff01;个人知乎 防抖在前端开发中可以说经常用到&#xff0c;有诸多使用场景。接下来我们一起看下防抖的定义、防抖函数的实现、应用场景、lodash防抖函数以及防抖在框架中的使用。Let’s go 一、什么是防…...

Linux磁盘管理与文件系统(二):实用工具和命令、fdisk分区示例

文章目录 4、查看或管理磁盘分区-fdisk格式选项示例 4、示例&#xff1a;使用 fdisk 命令创建分区需求操作步骤 5、创建文件系统-mkfs格式常用选项示例创建其他类型的文件系统 6、创建文件系统-mkswap格式常用选项示例拓展&#xff1a;关闭和启用交换分区拓展&#xff1a;swap分…...

使用vtkRenderer创建的显示点云的窗口如何刷新(QT/C++)

一、使用vtkRenderer创建点云显示窗口&#xff0c;参考 在Qt创建的UI中放一个显示点云的窗口&#xff08;PCLQT5&#xff09;_pcl点云和qt-CSDN博客 二、刷新vtkRenderer创建的窗口 使用场景&#xff1a;在某些情况下代码中需要对显示窗口的显示物改动&#xff0c;例如通过滑…...

Mysql绕过小技巧

上源码。 <?php $mysqli new mysqli("localhost", "root", "root", "security");/* check connection */ if ($mysqli->connect_errno) {printf("Connect failed: %s\n", $mysqli->connect_error);exit(); }$my…...

气象大数据案例项目(求各气象站的平均气温)

气象大数据案例项目&#xff08;求各气象站的平均气温&#xff09; 一、项目需求二、数据格式三、项目开发3.1 在windows 进行开发3.2 运行结果3.3 对项目打包 一、项目需求 现在有一份来自美国国家海洋和大气管理局的数据集&#xff0c;里面包含近30年每个气象站、每小时的天…...

博客摘录「 一个ModBus RTU程序(支持01、02、03、05、06、15、16功能码)」2024年4月19日

发送数据最好改为中断模式&#xff0c;不然通信速度不够。...

Vue3学习笔记第一天

MVVM Vue是一种用于构建用户界面的JavaScript框架。MVVM 是Vue采用的一种软件架构模式&#xff0c;用于构建交互式的用户界面。它的全称是 Model-View-ViewModel&#xff0c;这三个部分分别代表了应用程序的不同层次和角色&#xff1a; Model&#xff08;模型&#xff09;&…...

C++之类与对象(完结撒花篇)

目录 前言 1.再探构造函数 2.类型转换 3.static成员 4. 友元 5.内部类 6.匿名对象 7.对象拷贝时的编译器优化 结束语 前言 在前面的博客中&#xff0c;我们对类的默认成员函数都有了一定了解&#xff0c;同时实现了一个日期类对所学的没内容进行扩展延伸&#xff0c;本…...

代码质量的守护者:Python静态代码分析工具的集成之道

标题&#xff1a;代码质量的守护者&#xff1a;Python静态代码分析工具的集成之道 在软件开发过程中&#xff0c;代码质量是至关重要的一环。Python作为一种流行的编程语言&#xff0c;拥有众多的静态代码分析工具&#xff0c;它们能够在代码运行之前检测潜在的错误和代码风格…...

JVM -- 类加载器

类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现访问接口和类字节码数据的技术。类加载器只负责加载过程中的字节码获取并加载到内存的这一过程。 一、 类加载器的分类 类加载器的详细信息可以使用Arthas通过classloader命令查看&#xff1a; 1.启动类加载器(Boots…...

OLAP引擎之StarRocks

StarRocks 是一款新兴的开源分布式实时分析型数据库&#xff0c;专为高性能、高并发的数据分析场景设计。它结合了传统数据仓库和大数据技术的优势&#xff0c;提供了强大的实时数据处理和分析能力。以下是对 StarRocks 的详细介绍&#xff0c;涵盖其基本概念、核心特性、架构设…...

基于微信小程序的小区业主服务系统(源码+论文+部署讲解等)

博主介绍&#xff1a;✌全网粉丝10W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术栈介绍&#xff1a;我是程序员阿龙&#xff…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比

在机器学习的回归分析中&#xff0c;损失函数的选择对模型性能具有决定性影响。均方误差&#xff08;MSE&#xff09;作为经典的损失函数&#xff0c;在处理干净数据时表现优异&#xff0c;但在面对包含异常值的噪声数据时&#xff0c;其对大误差的二次惩罚机制往往导致模型参数…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...