mysql高可用架构设计

news2024/10/6 1:35:06

一、主从架构

主从架构一般如下所示

这里从节点一般设置成只读(readonly)模式。这样做,有以下几个考虑:

  1. 有时候一些运营类的查询语句会被放到备库上去查,设置为只读可以防止误操作;

  2. 防止切换逻辑有 bug,比如切换过程中出现双写,造成主备不一致;

  3. 可以用 readonly 状态,来判断节点的角色。

你可能会问,我把备库设置成只读了,还怎么跟主库保持同步更新呢?

这个问题,你不用担心。因为 readonly 设置对超级 (super) 权限用户是无效的,而用于同步更新的线程,就拥有超级权限。

1.主从复制

1.主从复制原理

Mysql的主从复制中主要有三个线程: master(binlog dump thread)、slave(I/O thread 、SQL thread) ,Master一条线程和Slave中的两条线程。

整体上来说,复制有3个步骤:

  1. master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
  2. 从节点 I/O线程接收 binlog 变动内容,并将其写入到 中继日志(relay log) 文件中。;
  3. 从节点的SQL 线程读取 relay log 文件内容对数据更新进行重放,最终保证主从数据库的一致性。

复制流程如下:

在这里插入图片描述

注:主从节点使用 binglog 文件 + position 偏移量来定位主从同步的位置,从节点会保存其已接收到的偏移量,如果从节点发生宕机重启,则会自动从 position 的位置发起同步。

详细流程如下:

第一部分就是master记录二进制日志。

在每个事务更新数据完成之前,master在二进制日志中记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。

第二部分就是slave将master的binary log拷贝到它自己的中继日志。

首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。

SQL slave thread(SQL从线程)处理该过程的最后一步。

SQL线程从中继日志读取事件,并重放其中的事件而更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。

此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。

2.主从复制策略

1.异步复制

上述处理流程就是异步复制的流程。

而mysql默认的复制方式是异步复制

主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。

由此产生两个概念。


2.全同步复制

主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,但是很显然这个方式的话性能会受到严重影响。

这里我理解即使是全同步复制,当在复制的过程中主库挂了,那部分数据也丢失了,但主从之间数据还是一致的。由于主库的事务没有提交,那么用户将收到的执行事务失败的错误,那么等主库恢复好了之后,用户将进行二次提交,那么数据就恢复正常了。所以我认为全同步复制只能保证主从之间的数据强一致性,但无法保证因主库宕机而造成的数据丢失问题。

3.半同步复制

和全同步不同的是,半同步复制的逻辑是这样,从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成。

配置半同步复制的时候,有一个重要的参数“rpl_semi_sync_master_wait_no_slave”,

含义是:“至少等待数据复制到几个从节点再返回”。这个数量配置的越大,丢数据的风险越小,但是集群的性能和可用性就越差。最大可以配置成和从节点的数量一样,这样就变成了同步复制。

一般情况下,配成默认值 1 也就够了,这样性能损失最小,可用性也很高,只要还有一个从库活着,就不影响主库读写。丢数据的风险也不大,只有在恰好主库和那个有最新数据的从库一起坏掉的情况下,才有可能丢数据。

另外一个重要的参数是“rpl_semi_sync_master_wait_point”,这个参数控制主库执行事务的线程,是在提交事务之前(AFTER_SYNC)等待复制,还是在提交事务之后(AFTER_COMMIT)等待复制。默认是 AFTER_SYNC,也就是先等待复制,再提交事务,这样完全不会丢数据。AFTER_COMMIT 具有更好的性能,不会长时间锁表,但还是存在宕机丢数据的风险。

另外,虽然我们配置了同步或者半同步复制,并且要等待复制成功后再提交事务,还是有一

种特别容易被忽略、可能存在丢数据风险的情况。如果说,主库提交事务的线程等待复制的时间超时了,这种情况下事务仍然会被正常提交。并且,MySQL 会自动降级为异步复制模式,直到有足够多(rpl_semi_sync_master_wait_no_slave)的从库追上主库,才能恢复成半同步复制。如果这个期间主库宕机,仍然存在丢数据的风险

3.并行复制演进

如果备库执行日志的速度持续低于主库生成日志的速度,那这个延迟就有可能成了小时级别。而且对于一个压力持续比较高的主库来说,备库很可能永远都追不上主库的节奏。

这就涉及到今天我要给你介绍的话题:备库并行复制能力。

为了便于你理解,我们再一起看一下极客时间第 24 篇文章《MySQL 是怎么保证主备一致的?》的主备流程图。

图 1 主备流程图

谈到主备的并行复制能力,我们要关注的是图中黑色的两个箭头。一个箭头代表了客户端写入主库,另一箭头代表的是备库上 sql_thread 执行中转日志(relay log)。如果用箭头的粗细来代表并行度的话,那么真实情况就如图 1 所示,第一个箭头要明显粗于第二个箭头。

在主库上,影响并发度的原因就是各种锁了。由于 InnoDB 引擎支持行锁,除了所有并发事务都在更新同一行(热点行)这种极端场景外,它对业务并发度的支持还是很友好的。所以,你在性能测试的时候会发现,并发压测线程 32 就比单线程时,总体吞吐量高。

而日志在备库上的执行,就是图中备库上 sql_thread 更新数据 (DATA) 的逻辑。如果是用单线程的话,就会导致备库应用日志不够快,造成主备延迟。

在官方的 5.6 版本之前,MySQL 只支持单线程复制,由此在主库并发高、TPS 高时就会出现严重的主备延迟问题。

从单线程复制到最新版本的多线程复制,中间的演化经历了好几个版本。接下来,我就跟你说说 MySQL 多线程复制的演进过程。

其实说到底,所有的多线程复制机制,都是要把图 1 中只有一个线程的 sql_thread,拆成多个线程,也就是都符合下面的这个模型:

图 2 多线程模型

图 2 中,coordinator 就是原来的 sql_thread, 不过现在它不再直接更新数据了,只负责读取中转日志和分发事务。真正更新日志的,变成了 worker 线程。而 work 线程的个数,就是由参数 slave_parallel_workers 决定的。根据我的经验,把这个值设置为 8~16 之间最好(32 核物理机的情况),毕竟备库还有可能要提供读查询,不能把 CPU 都吃光了。

接下来,你需要先思考一个问题:事务能不能按照轮询的方式分发给各个 worker,也就是第一个事务分给 worker_1,第二个事务发给 worker_2 呢?

其实是不行的。因为,事务被分发给 worker 以后,不同的 worker 就独立执行了。但是,由于 CPU 的调度策略,很可能第二个事务最终比第一个事务先执行。而如果这时候刚好这两个事务更新的是同一行,也就意味着,同一行上的两个事务,在主库和备库上的执行顺序相反,会导致主备不一致的问题。

接下来,请你再设想一下另外一个问题:同一个事务的多个更新语句,能不能分给不同的 worker 来执行呢?

答案是,也不行。举个例子,一个事务更新了表 t1 和表 t2 中的各一行,如果这两条更新语句被分到不同 worker 的话,虽然最终的结果是主备一致的,但如果表 t1 执行完成的瞬间,备库上有一个查询,就会看到这个事务“更新了一半的结果”,破坏了事务逻辑的隔离性。

所以,coordinator 在分发的时候,需要满足以下这两个基本要求:

  1. 不能造成更新覆盖。这就要求更新同一行的两个事务,必须被分发到同一个 worker 中。

  2. 同一个事务不能被拆开,必须放到同一个 worker 中。

各个版本的多线程复制,都遵循了这两条基本原则。

接下来,我们就看看各个版本的并行复制策略,详细的复制策略可参考极客时间第26篇​​​​​​​

官方 MySQL 5.5 版本是不支持并行复制的。

官方 MySQL5.6 版本,支持了并行复制,只是支持的粒度是按库并行。

 MySQL 5.7.22 版本里,MySQL 增加了一个新的并行复制策略,基于 WRITESET 的并行复制。

这里在多说一句,由于我们不是DBA人员,所以借用极客时间时间作者的一句话。

在介绍完每个并行复制策略后,我还和你分享了不同策略的优缺点:

  • 如果你是 DBA,就需要根据不同的业务场景,选择不同的策略;
  • 如果是你业务开发人员,也希望你能从中获取灵感用到平时的开发工作中。

从这些分析中,你也会发现大事务不仅会影响到主库,也是造成备库复制延迟的主要原因之一。因此,在平时的开发工作中,我建议你尽量减少大事务操作,把大事务拆成小事务。

2.主从切换

1.可靠性优先策略

从状态 1 到状态 2 切换的详细过程是这样的:

  1. 判断备库 B 现在的 seconds_behind_master,如果小于某个值(比如 5 秒)继续下一步,否则持续重试这一步;

  2. 把主库 A 改成只读状态,即把 readonly 设置为 true;

  3. 判断备库 B 的 seconds_behind_master 的值,直到这个值变成 0 为止;

  4. 把备库 B 改成可读写状态,也就是把 readonly 设置为 false;

  5. 把业务请求切到备库 B。

这个切换流程,一般是由专门的 HA 系统来完成的,我们暂时称之为可靠性优先流程。

图 2 MySQL 可靠性优先主备切换流程

备注:图中的 SBM,是 seconds_behind_master 参数的简写。

可以看到,这个切换流程中是有不可用时间的。

因为在步骤 2 之后,主库 A 和备库 B 都处于 readonly 状态,也就是说这时系统处于不可写状态,直到步骤 5 完成后才能恢复。

在这个不可用状态中,比较耗费时间的是步骤 3,可能需要耗费好几秒的时间。这也是为什么需要在步骤 1 先做判断,确保 seconds_behind_master 的值足够小。

试想如果一开始主备延迟就长达 30 分钟,而不先做判断直接切换的话,系统的不可用时间就会长达 30 分钟,这种情况一般业务都是不可接受的。

接下来我们再看看,按照可靠性优先的思路,异常切换会是什么效果?

假设,主库 A 和备库 B 间的主备延迟是 30 分钟,这时候主库 A 掉电了,HA 系统要切换 B 作为主库。我们在主动切换的时候,可以等到主备延迟小于 5 秒的时候再启动切换,但这时候已经别无选择了。

图 5 可靠性优先策略,主库不可用

采用可靠性优先策略的话,你就必须得等到备库 B 的 seconds_behind_master=0 之后,才能切换。但现在的情况比刚刚更严重,并不是系统只读、不可写的问题了,而是系统处于完全不可用的状态。因为,主库 A 掉电后,我们的连接还没有切到备库 B。

你可能会问,那能不能直接切换到备库 B,但是保持 B 只读呢?

这样也不行。

因为,这段时间内,中转日志还没有应用完成,如果直接发起主备切换,客户端查询看不到之前执行完成的事务,会认为有“数据丢失”。

虽然随着中转日志的继续应用,这些数据会恢复回来,但是对于一些业务来说,查询到“暂时丢失数据的状态”也是不能被接受的。

所以那‘沉默的30 分钟’只有尽快使SBM=0完成主从切换吧,使业务的伤害降到最低,那30分钟由于业务都是报错的,所以并不会产生脏数据,这也是不幸中的万幸了吧。

聊到这里你就知道了,在满足数据可靠性的前提下,MySQL 高可用系统的可用性,是依赖于主备延迟的。延迟的时间越小,在主库故障的时候,服务恢复需要的时间就越短,可用性就越高。

当然,系统的不可用时间,是由这个数据可靠性优先的策略决定的。你也可以选择可用性优先的策略,来把这个不可用时间几乎降为 0。

2.可用性优先策略

如果我强行把步骤 4、5 调整到最开始执行,也就是说不等主备数据同步,直接把连接切到备库 B,并且让备库 B 可以读写,那么系统几乎就没有不可用时间了。

我们把这个切换流程,暂时称作可用性优先流程。这个切换流程的代价,就是可能出现数据不一致的情况。

接下来,我就和你分享一个可用性优先流程产生数据不一致的例子。假设有一个表 t:

mysql> CREATE TABLE `t` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `c` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
 
insert into t(c) values(1),(2),(3);

这个表定义了一个自增主键 id,初始化数据后,主库和备库上都是 3 行数据。接下来,业务人员要继续在表 t 上执行两条插入语句的命令,依次是:

insert into t(c) values(4);

insert into t(c) values(5);

假设,现在主库上其他的数据表有大量的更新,导致主备延迟达到 5 秒。在插入一条 c=4 的语句后,发起了主备切换。

图 3 是可用性优先策略,且 binlog_format=mixed时的切换流程和数据结果。

图 3 可用性优先策略,且 binlog_format=mixed

现在,我们一起分析下这个切换流程:

  1. 步骤 2 中,主库 A 执行完 insert 语句,插入了一行数据(4,4),之后开始进行主备切换。

  2. 步骤 3 中,由于主备之间有 5 秒的延迟,所以备库 B 还没来得及应用“插入 c=4”这个中转日志,就开始接收客户端“插入 c=5”的命令。

  3. 步骤 4 中,备库 B 插入了一行数据(4,5),并且把这个 binlog 发给主库 A。

  4. 步骤 5 中,备库 B 执行“插入 c=4”这个中转日志,插入了一行数据(5,4)。而直接在备库 B 执行的“插入 c=5”这个语句,传到主库 A,就插入了一行新数据(5,5)。

最后的结果就是,主库 A 和备库 B 上出现了两行不一致的数据。可以看到,这个数据不一致,是由可用性优先流程导致的。

那么,如果我还是用可用性优先策略,但设置 binlog_format=row,情况又会怎样呢?

因为 row 格式在记录 binlog 的时候,会记录新插入的行的所有字段值,所以最后只会有一行不一致。而且,两边的主备同步的应用线程会报错 duplicate key error 并停止。也就是说,这种情况下,备库 B 的 (5,4) 和主库 A 的 (5,5) 这两行数据,都不会被对方执行。

图 4 中我画出了详细过程,你可以自己再分析一下。

图 4 可用性优先策略,且 binlog_format=row

从上面的分析中,你可以看到一些结论:

  1. 使用 row 格式的 binlog 时,数据不一致的问题更容易被发现。而使用 mixed 或者 statement 格式的 binlog 时,数据很可能悄悄地就不一致了。如果你过了很久才发现数据不一致的问题,很可能这时的数据不一致已经不可查,或者连带造成了更多的数据逻辑不一致。

  2. 主备切换的可用性优先策略会导致数据不一致。

因此,大多数情况下,我都建议你使用可靠性优先策略。毕竟对数据服务来说的话,数据的可靠性一般还是要优于可用性的。

但事无绝对,有没有哪种情况数据的可用性优先级更高呢?

答案是,有的。

我曾经碰到过这样的一个场景:

  • 有一个库的作用是记录操作日志。这时候,如果数据不一致可以通过 binlog 来修补,而这个短暂的不一致也不会引发业务问题。
  • 同时,业务系统依赖于这个日志写入逻辑,如果这个库不可写,会导致线上的业务操作无法执行。

这时候,你可能就需要选择先强行切换,事后再补数据的策略。

当然,事后复盘的时候,我们想到了一个改进措施就是,让业务逻辑不要依赖于这类日志的写入。也就是说,日志写入这个逻辑模块应该可以降级,比如写到本地文件,或者写到另外一个临时库里面。

这样的话,这种场景就又可以使用可靠性优先策略了。

3.主从延迟

1.定义

数据库中的数据在主库完成更新后,是异步同步到每个从库上的,这个过程有一个微小的时间差,这个时间差叫主从同步延迟。

正常情况下,主从延迟非常小,不超过 1ms。但即使这个非常小的延迟,也会导致在某一个时刻,主库和从库上的数据是不一致的。应用程序需要能接受并克服这种主从不一致的情况,否则就会引发一些由于主从延迟导致的数据错误。

主备切换可能是一个主动运维动作,比如软件升级、主库所在机器按计划下线等,也可能是被动操作,比如主库所在机器掉电。

接下来,我们先一起看看主动切换的场景。

在介绍主动切换流程的详细步骤之前,我要先跟你说明一个概念,即“同步延迟”。与数据同步有关的时间点主要包括以下三个:

  1. 主库 A 执行完成一个事务,写入 binlog,我们把这个时刻记为 T1;

  2. 之后传给备库 B,我们把备库 B 接收完这个 binlog 的时刻记为 T2;

  3. 备库 B 执行完成这个事务,我们把这个时刻记为 T3。

所谓主备延迟,就是同一个事务,在备库执行完成的时间和主库执行完成的时间之间的差值,也就是 T3-T1。

你可以在备库上执行 show slave status 命令,它的返回结果里面会显示 seconds_behind_master,用于表示当前备库延迟了多少秒。

seconds_behind_master 的计算方法是这样的:

  1. 每个事务的 binlog 里面都有一个时间字段,用于记录主库上写入的时间;

  2. 备库取出当前正在执行的事务的时间字段的值,计算它与当前系统时间的差值,得到 seconds_behind_master。

可以看到,其实 seconds_behind_master 这个参数计算的就是 T3-T1。所以,我们可以用 seconds_behind_master 来作为主备延迟的值,这个值的时间精度是秒。

你可能会问,如果主备库机器的系统时间设置不一致,会不会导致主备延迟的值不准?

其实不会的。因为,备库连接到主库的时候,会通过执行 SELECT UNIX_TIMESTAMP() 函数来获得当前主库的系统时间。如果这时候发现主库的系统时间与自己不一致,备库在执行 seconds_behind_master 计算的时候会自动扣掉这个差值。

需要说明的是,在网络正常的时候,日志从主库传给备库所需的时间是很短的,即 T2-T1 的值是非常小的。也就是说,网络正常情况下,主备延迟的主要来源是备库接收完 binlog 和执行完这个事务之间的时间差。

所以说,主备延迟最直接的表现是,备库消费中转日志(relay log)的速度,比主库生产 binlog 的速度要慢。接下来,我就和你一起分析下,这可能是由哪些原因导致的。

2.产生原因

1.非对称部署

首先,有些部署条件下,备库所在机器的性能要比主库所在的机器性能差。

一般情况下,有人这么部署时的想法是,反正备库没有请求,所以可以用差一点儿的机器。或者,他们会把 20 个主库放在 4 台机器上,而把备库集中在一台机器上。

其实我们都知道,更新请求对 IOPS 的压力,在主库和备库上是无差别的。所以,做这种部署时,一般都会将备库设置为“非双 1”的模式。

但实际上,更新过程中也会触发大量的读操作。所以,当备库主机上的多个备库都在争抢资源的时候,就可能会导致主备延迟了。

当然,这种部署现在比较少了。

因为主备可能发生切换,备库随时可能变成主库,所以主备库选用相同规格的机器,并且做对称部署,是现在比较常见的情况。

2.备库压力过大

做了对称部署以后,还可能会有延迟。这是为什么呢?

一般的想法是,主库既然提供了写能力,那么备库可以提供一些读能力。或者一些运营后台需要的分析语句,不能影响正常业务,所以只能在备库上跑。

我真就见过不少这样的情况。由于主库直接影响业务,大家使用起来会比较克制,反而忽视了备库的压力控制。结果就是,备库上的查询耗费了大量的 CPU 资源,影响了同步速度,造成主备延迟。

这种情况,我们一般可以这么处理:

  1. 一主多从。除了备库外,可以多接几个从库,让这些从库来分担读的压力。

  2. 通过 binlog 输出到外部系统,比如 Hadoop 这类系统,让外部系统提供统计类查询的能力。

其中,一主多从的方式大都会被采用。因为作为数据库系统,还必须保证有定期全量备份的能力。而从库,就很适合用来做备份。

还有就是当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围(即执行这些ddl语句会耗时较大),那么延时就产生了,当然还有就是可能与slave的大型query语句产生了锁等待。

以 MySQL 为例,主从复制延迟可能达到 1 秒,如果有大量数据同步,延迟 1 分钟也是有可能的。

3.大事务

大事务这种情况很好理解。因为主库上必须等事务执行完成才会写入 binlog,再传给备库。所以,如果一个主库上的语句执行 10 分钟,那这个事务很可能就会导致从库延迟 10 分钟。

不知道你所在公司的 DBA 有没有跟你这么说过:不要一次性地用 delete 语句删除太多数据。其实,这就是一个典型的大事务场景。

比如,一些归档类的数据,平时没有注意删除历史数据,等到空间快满了,业务开发人员要一次性地删掉大量历史数据。同时,又因为要避免在高峰期操作会影响业务(至少有这个意识还是很不错的),所以会在晚上执行这些大量数据的删除操作。

结果,负责的 DBA 同学半夜就会收到延迟报警。然后,DBA 团队就要求你后续再删除数据的时候,要控制每个事务删除的数据量,分成多次删除

另一种典型的大事务场景,就是大表 DDL。这个场景,我在前面的文章中介绍过。处理方案就是,计划内的 DDL,建议使用 gh-ost 方案。

3.主从延迟监控

一般现在的数据库运维系统都有备库延迟监控,其实就是在备库上执行 show slave status,采集 seconds_behind_master 的值。

如果出现下面这种情况,说明已经出现了主从延迟,产生的原因则是备库的同步在这段时间完全被堵住了。

产生这种现象典型的场景主要包括两种:

  • 一种是大事务(包括大表 DDL、一个事务操作很多行);
  • 还有一种情况比较隐蔽,就是备库起了一个长事务,比如
begin; 
select * from t limit 1;

 

然后就不动了。

这时候主库对表 t 做了一个加字段操作,即使这个表很小,这个 DDL 在备库应用的时候也会被堵住,也不能看到这个现象。

二、双主架构

大部分这种架构用的比较少,因为难以解决数据的一致性问题。

它的基本架构设计如下图所示:

图 9 MySQL 主备切换流程 -- 双 M 结构

对比图 9 和图 1,你可以发现,双 M 结构和 M-S 结构,其实区别只是多了一条线,即:节点 A 和 B 之间总是互为主备关系。这样在切换的时候就不用再修改主备关系。

但是,双 M 结构还有一个问题需要解决,那就是循环复制问题。

业务逻辑在节点 A 上更新了一条语句,然后再把生成的 binlog 发给节点 B,节点 B 执行完这条更新语句后也会生成 binlog。(我建议你把参数 log_slave_updates 设置为 on,表示备库执行 relay log 后生成 binlog)。

那么,如果节点 A 同时是节点 B 的备库,相当于又把节点 B 新生成的 binlog 拿过来执行了一次,然后节点 A 和 B 间,会不断地循环执行这个更新语句,也就是循环复制了。这个要怎么解决呢?

从上面的图 6 中可以看到,MySQL 在 binlog 中记录了这个命令第一次执行时所在实例的 server id。因此,我们可以用下面的逻辑,来解决两个节点间的循环复制的问题:

  1. 规定两个库的 server id 必须不同,如果相同,则它们之间不能设定为主备关系;

  2. 一个备库接到 binlog 并在重放的过程中,生成与原 binlog 的 server id 相同的新的 binlog;

  3. 每个库在收到从自己的主库发过来的日志后,先判断 server id,如果跟自己的相同,表示这个日志是自己生成的,就直接丢弃这个日志。

按照这个逻辑,如果我们设置了双 M 结构,日志的执行流就会变成这样:

  1. 从节点 A 更新的事务,binlog 里面记的都是 A 的 server id;

  2. 传到节点 B 执行一次以后,节点 B 生成的 binlog 的 server id 也是 A 的 server id;

  3. 再传回给节点 A,A 判断到这个 server id 与自己的相同,就不会再处理这个日志。所以,死循环在这里就断掉了。

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

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

相关文章

uniapp制作--简单的tab切换

一、实现思路 在UniApp中&#xff0c;可以使用v-if来控制Tab栏并进行切换。 创建一个方法来控制点击时的效果。 二、实现步骤 ①view部分展示 <!-- tab选项 --><view class"select-area"><view class"select-top"><view clas…

软件测试行业最真实的写照,我后悔了。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 软件测试是一个付出就有回报的工作&#xff0c;可能很多人会说软件测试就是吃青春饭&#xff0c;…

vs创建asp.net core webapi发布到ISS服务器

打开服务器创建test123文件夹&#xff0c;并设置共享。 ISS配置信息&#xff1a; 邮件网站&#xff0c;添加网站 webapi asp.net core发布到ISS服务器网页无法打开解决方法 点击ISS Express测试&#xff0c;可以成功打开网页。 点击生成&#xff0c;发布到服务器 找到服务器IP…

如何处理微服务之间的通信和数据一致性?

✨✨祝屏幕前的兄弟姐妹们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 一、微服务通信 1、同步通信&#xff1a;HTTP 1.1.同步通信示例代码&#xf…

Q-Align Teaching LMMs for Visual Scoring via Discrete Text-Defined Levels

Q-Align: Teaching LMMs for Visual Scoring via Discrete Text-Defined Levels TL; DR&#xff1a;教会多模态大模型用文本等级评价词&#xff08;如 Good、Bad、Excellent 等&#xff09;来评估视觉质量分。 图像美学质量评估是一个小方向&#xff0c;但是实际业务中很有用&…

Jenkins 将shell脚本启动方式修改为bash

platform"arm x86" if [[ "$platform" ~ "arm" ]] thenecho "arm" fi最近在调试Jenkins实现的一些功能&#xff0c;发现在本地可以运行的脚本内容到了Jenkins里面就没办法运行了&#xff0c;不是提示unexpected operator就是提示[[ : …

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:拖拽控制)

设置组件是否可以响应拖拽事件。 说明&#xff1a; 从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 ArkUI框架对以下组件实现了默认的拖拽能力&#xff0c;支持对数据的拖出或拖入响应&#xff0c;开发者只需要将这些组件…

商家转账到零钱申请时间要多久

商家转账到零钱是什么&#xff1f; 【商家转账到零钱】功能整合了微信支付之前的【企业付款到零钱】【批量转账到零钱】功能&#xff0c;支持批量对外转账&#xff0c;对有批量对用户付款需求的应用场景更友好&#xff0c;操作便捷。如果你的应用场景是单付款场景的话&#xf…

运维打工人,周末兼职送外卖的一天

运维打工人&#xff0c;周末兼职送外卖的一天 在那个不经意的周末&#xff0c;我决定尝试一份新的工作——为美团外卖做兼职配送员。这份工作对于一向规律生活的我来说&#xff0c;既是突破也是挑战。 早晨&#xff0c;空气中带着几分凉意和宁静。准备好出发时&#xff0c;线…

如何做代币分析:以 CRO 币为例

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;Mingfootprint.network 数据源&#xff1a;CRO Token Dashboard &#xff08;仅包括以太坊数据&#xff09; 在加密货币和数字资产领域&#xff0c;代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关…

Unity编辑器功能Inspector快捷自动填充数据

我们有时候可能需要在面板增加一些引用&#xff0c;可能添加脚本后要手动拖动&#xff0c;这样如果有大量的脚本拖动也是不小的工作量 实例 例如&#xff1a;我的脚本需要添加一个Bone的列表&#xff0c;一个个拖动很麻烦。 实现脚本 我们可以用这样的脚本来实现。 public…

鼠标右键没有git bash here,右键添加git bash here并增加图标

突然发现自己鼠标右键没有git bash here&#xff0c;或者安装之后就没有git bash here。后面那种情况多半是没有默认装在C盘。我们装在其他盘的时候就需要自己去配置。git gui目前用不上&#xff0c;这里只讲git bash here。网上一堆教程&#xff0c;说法不同大多不能用要么就很…

Vue router文件中本地路由配置使用i18n【解决tab名称出现undefined,导致i18n没有实现问题】

问题 点击按钮 跳转详情页后 tab名称出现错误&#xff0c;报 undefined ## 需求 点击工单详情按钮&#xff0c;跳转详情页面&#xff08;新页面&#xff09;&#xff0c;新页面tab栏名称 还是为 工单出库&#xff0c;但要求工单出库文字配置为多语言&#xff0c;使用i18n来配置…

SPC 之 I-MR 控制图

概述 1924 年&#xff0c;美国的休哈特博士应用统计数学理论将 3Sigma 原理运用于生产过程中&#xff0c;并发表了 著名的“控制图法”&#xff0c;对产品特性和过程变量进行控制&#xff0c;开启了统计过程控制新时代。 什么是控制图 控制图指示过程何时不受控制&#xff…

中医舌苔笔记

舌诊时按照舌尖-舌中-舌根-舌侧的顺序进行观察。 先看舌体再看舌苔&#xff0c;30秒左右。 如果一次望舌判断不清&#xff0c;可令病人休息3~5分钟后&#xff0c;重新观察一次 舌诊脏腑部位分属图 舌体 胖嫩而边有齿痕为气虚、阳虚。 薄白而润为风寒&#xff1b; 薄白而燥…

RabbitMQ如何实现延迟消息?

RabbitMQ中是可以实现延迟消息的&#xff0c;一般有两种方式&#xff0c;分别是通过死信队列以及通过延迟消息插件来实现。 扩展&#xff1a; 死信队列 当rabbitMQ中的一条正常的消息&#xff0c;因为过了存活时间&#xff08;TTL过期&#xff09;&#xff0c;队列长度超限&a…

【论文精读】Attention Bottlenecks for Multimodal Fusion 视频分类任务

本文并非逐句翻译&#xff0c;添加个人理解与疑惑&#xff0c;如有需要&#xff0c;请自行阅读原文。 Attention Bottlenecks for Multimodal Fusion 多模态融合的注意力瓶颈 会议&#xff1a;NIPS2021 Benchmark&#xff1a;Audioset、Epic Kitchens和VGGSound等 Backbone&…

白酒:原料的预处理技术对白酒品质的影响

在豪迈白酒的酿造过程中&#xff0c;原料的预处理技术对白酒的品质起着至关重要的作用。预处理技术包括原料的选择、清洗、破碎、润料等环节&#xff0c;这些环节的处理方式直接影响着白酒的口感、香气和品质。云仓酒庄在原料的预处理技术方面进行了深入研究和探索&#xff0c;…

图扑数字孪生水电站,水力发电可视化运维

自水轮机的早期发明被用于农业灌溉&#xff0c;到 18 世纪末期的工业革命促使水轮机技术的改良&#xff0c;再到 19 世纪末水利发电的崛起&#xff0c;直至今日&#xff0c;智慧水电站数字孪生技术正处于蓬勃发展之中。通过整合物联网、大数据、云计算等现代信息技术&#xff0…

Python图像处理【21】基于卷积神经网络增强微光图像

基于卷积神经网络增强微光图像 0. 前言1. MBLLEN 网络架构2. 增强微光图像小结系列链接 0. 前言 在本节中&#xff0c;我们将学习如何基于预训练的深度学习模型执行微光/夜间图像增强。由于难以同时处理包括亮度、对比度、伪影和噪声在内的所有因素&#xff0c;因此微光图像增…