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

【分布式】分布式事务

目录

1、事务的发展

2、本地事务

(1)如何保障原子性和持久性?       

(2)如何保障隔离性?

2、全局事务 

(1)XA事务的两段式提交

(2)XA事务的三段式提交

3、分布式事务

(1)CAP定理

(2)如何保证最终一致性?

(3)TCC事务(冻结资源)

(4)SAGA事务(补偿资源)


1、事务的发展

        我们都知道数据库中事务的“ACID”特性,但事务的概念今天已经有所延伸,不再局限于数据库本身了。所有需要保证数据一致性的应用场景,包括但不限于数据库、事务内存、缓存、消息队列、分布式存储,等等,都有可能用到事务。

        当一个服务只使用一个数据源时,通过 A、I、D 来获得一致性是最经典的做法,也是相对容易的。此时,多个并发事务所读写的数据能够被数据源感知是否存在冲突,并发事务的读写在时间线上的最终顺序是由数据源来确定的,这种事务间一致性被称为“内部一致性”。// C是最终结果

        当一个服务使用到多个不同的数据源,甚至多个不同服务同时涉及多个不同的数据源时,问题就变得困难了许多。此时,并发执行甚至是先后执行的多个事务,在时间线上的顺序并不由任何一个数据源来决定,这种涉及多个数据源的事务间一致性被称为“外部一致性”。//外部一致性少了一个统一的数据源去协调一致性,所以我们需要模拟内部一致性的实现,去创造一个统一的外部的协调器

2、本地事务

        本地事务是指仅操作单一事务资源的、不需要全局事务管理器进行协调的事务。

        本地事务是一种最基础的事务解决方案,只适用于单个服务使用单个数据源的场景。从应用角度看,它是直接依赖于数据源本身提供的事务能力来工作的,在程序代码层面,最多只能对事务接口做一层标准化的包装(如JDBC接口),并不能深入参与到事务的运作过程中,事务的开启、终止、提交、回滚、嵌套、设置隔离级别,乃至与应用代码贴近的事务传播方式,全部都要依赖底层数据源的支持才能工作,这一点与后续介绍的XA、TCC、SAGA等主要靠应用程序代码来实现的事务有着十分明显的区别。//程序不介入单一事物源的操作

        那么传统统数据库管理系统是如何通过ACID来实现事务的?

(1)如何保障原子性和持久性?       

        实现原子性和持久性的最大困难是“写入磁盘”这个操作并不是原子的,不仅有“写入”与“未写入”状态,还客观存在着“正在写”的中间状态。由于写入中间状态崩溃都不可能消除,所以如果不做额外保障措施的话,将内存中的数据写入磁盘,并不能保证原子性与持久性。

        解决方式是使用日志

        以日志的形式——即以仅进行顺序追加的文件写入的形式(这是最高效的写入方式)先记录到磁盘中。//顺序写

        只有在日志记录全部安全落盘,数据库在日志中看到代表事务成功提交的“提交记录”(Commit Record)后,才会根据日志上的信息对真正的数据进行修改,修改完成后,再
在日志中加入一条“结束记录”(End Record)表示事务已完成持久化,这种事务实现方法被称为“提交日志”(Commit Logging)。//MySQL中提交日志的两段式提交-redoLog

        你以为问题就此解决了吗?NO!单一的提交日志会带来性能问题。

        Commit Logging存在一个巨大的先天缺陷:所有对数据的真实修改都必须发生在事务提交以后,即日志写入了 Commit Record 之后。在此之前,即使磁盘 I/O 有足够空闲,即使某个事务修改的数据量非常庞大,占用了大量的内存缓冲区,无论何种理由,都决不允许在事务提交之前就修改磁盘上的数据,这一点是Commit Logging成立的前提,却对提升数据库的性能十分不利。

        为此,ARIES 提出了“提前写入日志”(Write-Ahead Logging)的日志改进方案,所谓“提前写入”(Write-Ahead),就是允许在事务提交之前写入变动数据的意思。//预写日志

        但是如果事务提交前就有部分变动数据写入磁盘,那一旦事务要回滚,或者发生了崩溃,这些提前写入的变动数据就都成了错误。又如何去避免这个问题呢?

        给出的解决办法是增加了另一种被称为 Undo Log 的日志类型,当变动数据写入磁盘前,必须先记录Undo Log,注明修改了哪个位置的数据、从什么值改成什么值等,以便在事务回滚或者崩溃恢复时根据 Undo Log 对提前写入的数据变动进行擦除。//增加回滚日志

(2)如何保障隔离性?

        隔离性保证了每个事务各自读、写的数据互相独立,不会彼此影响。只从定义上就能嗅出隔离性肯定与并发密切相关,因为如果没有并发,所有事务全都是串行的,那就不需要任何隔离。

        那么,要如何在并发下实现串行的数据访问呢?

        答案就是:加锁同步

        现代数据库均提供了以下三种锁:

  1. 写锁(排他锁):如果数据有加写锁,就只有持有写锁的事务才能对数据进行写入操作,数据加持着写锁时,其他事务不能写入数据,也不能施加读锁。
  2. 读锁(共享锁):多个事务可以对同一个数据添加多个读锁,数据被加上读锁后就不能再被加上写锁,所以其他事务不能对该数据进行写入,但仍然可以读取。对于持有读锁的事务,如果该数据只有它自己一个事务加了读锁,则允许直接将其升级为写锁,然后写入数据。
  3. 范围锁:对于某个范围直接加排他锁,在这个范围内的数据不能被写入。

        请注意“范围不能被写入”与“一批数据不能被写入”的差别,即不要把范围锁理解成一组排他锁的集合。加了范围锁后,不仅不能修改该范围内已有的数据,也不能在该范围内新增或删除任何数据,后者是一组排他锁的集合无法做到的。

        并发控制(Concurrency Control)理论决定了隔离程度与并发能力是相互抵触的,隔离程度越高,并发访问时的吞吐量就越低。

        加锁就是进行串行化,数据库不考虑性能肯定是不行的,所以数据库中如何去权衡隔离性和吞吐量呢?

        这里就要说到我们常见的数据库隔离级别了,即“串行化”,“可重复度”(幻读问题),“读已提交”(不可重复读问题),“读未提交”(脏读问题)。//四种隔离级别

        “可重复度”会产生幻读问题,原因是可重复读没有范围锁来禁止在该范围内插入新的数据,这是一个事务受到其他事务影响,隔离性被破坏的表现。//缺乏范围锁

        “读已提交”对事务涉及的数据加的写锁会一直持续到事务结束,但加的读锁在查询操作完成后会马上释放。因为缺乏贯穿整个事务周期的读锁,无法禁止读取过的数据发生变化,所以会出现不可重复读问题。//缺乏贯穿整个事务周期的读锁

        “读未提交”会产生脏读问题。原因在于它只会对事务涉及的数据加写锁,且一直持续到事务结束,但完全不加读锁。//完全无读锁,不加锁也就不会去获取锁

        总结以上三种问题:幻读、不可重复读、脏读等问题都是由于一个事务在读数据的过程中,受另外一个写数据的事务影响而破坏了隔离性。//都是“一个事务读+另一个事务写”的隔离问题

        “多版本并发控制”(Multi-Version Concurrency Control,MVCC)无锁优化方案

        MVCC是一种读取优化策略,它的“无锁”特指读取时不需要加锁。MVCC的基本思路是对数据
库的任何修改都不会直接覆盖之前的数据,而是产生一个新版本与老版本共存,以此达到读取时可以完全不加锁的目的。//使用版本快照——不加读锁(可实现读已提交和可重复读两种隔离级别) ,也就是说使用MVCC既保证了可重复读的隔离性,又具备了读未提交的性能。

        需要注意的是,MVCC是只针对“读+写”场景的优化,如果是两个事务同时修改数据,即“写+写”的情况,那就没有多少优化的空间了,此时加锁几乎是唯一可行的解决方案。

2、全局事务 

        在本节里,全局事务被限定为一种适用于单个服务使用多个数据源场景的事务解决方案。

(1)XA事务的两段式提交

        1991年,为了解决分布式事务的一致性问题,X/Open组织提出了一套名为X/Open XA(XA是 eXtended Architecture 的缩写)的处理事务架构,其核心内容是定义了全局的事务管理器(Transaction Manager,用于协调全局事务)和局部的资源管理器(Resource Manager,用于驱动本地事务)之间的通信接口。//XA架构

        XA 接口是双向的,能在一个事务管理器多个资源管理器之间形成通信桥梁,通过协调多个数据源的一致动作,实现全局事务的统一提交或者统一回滚。

        XA将事务提交拆分成两阶段:

        准备阶段:又叫作投票阶段,在这一阶段,协调者询问事务的所有参与者是否准备好提交,参与者如果已经准备好提交则回复 Prepared,否则回复 Non-Prepared。准备操作是在重做日志中记录全部事务提交操作所要做的内容,它与本地事务中真正提交的区别只是暂不写入最后一条Commit Record而已。//重量操作

        提交阶段:又叫作执行阶段,协调者如果在上一阶段收到所有事务参与者回复的 Prepared 消息,则先自己在本地持久化事务状态为 Commit,然后向所有参与者发送 Commit 指令,让所有参与者立即执行提交操作;否则,协调者将在自己完成事务状态为Abort持久化后,向所有参与者发送Abort指令,让参与者立即执行回滚操作。这个阶段的提交操作应是很轻量的,仅仅是持久化一条Commit Record而已,通常能够快速完成,只有收到Abort指令时,才需要根据回滚日志清理已提交的数据,这可能是相对重负载操作。//轻量操作

        两段式提交原理简单,并不难实现,但有几个非常显著的缺点:

        (1)单点问题:协调者在两段式提交中具有举足轻重的作用。一旦宕机所有参与者都会受到影响。如果协调者一直没有恢复,那所有参与者都必须一直等待。

        (2)性能问题:在两段式提交过程中,所有参与者相当于被绑定为一个统一调度的整体,期间要经过两次远程服务调用,三次数据持久化,整个过程将持续到参与者集群中最慢的那一个处理操作结束为止,这决定了两段式提交的性能通常都较差。//一个慢,所有都慢

        (3)一致性风险:尽管提交阶段时间很短,但这仍是一段明确存在的危险期,如果协调者在发出准备指令后,根据收到各个参与者发回的信息确定事务状态是可以提交的,协调者会先持久化事务状态,并提交自己的事务,如果这时候网络忽然断开,无法再通过网络向所有参与者发出Commit指令的话,就会导致部分数据(协调者的)已提交,但部分数据(参与者的)未提交,且没有办法回滚,产生数据不一致的问题。//提交阶段断网

(2)XA事务的三段式提交

        为了缓解两段式提交协议的一部分缺陷,具体地说是协调者的单点问题和准备阶段的性能问题,后续又发展出了“三段式提交”(3 Phase Commit,3PC)协议。//在两阶段提交的基础上增加询问阶段,增加事务成功率

        三段式提交把原本的两段式提交的准备阶段再细分为两个阶段,分别称为 CanCommit、PreCommit,把提交阶段改称为 DoCommit 阶段。其中,新增的 CanCommit 是一个询问阶段,即协调者让每个参与的数据库根据自身状态,评估该事务是否有可能顺利完成。

        将准备阶段一分为二的理由是这个阶段是重负载的操作,一旦协调者发出开始准备的消息,每个参与者都将马上开始写重做日志,它们所涉及的数据资源即被锁住,如果此时某一个参与者宣告无法完成提交,相当于大家都做了一轮无用功。所以,增加一轮询问阶段,如果都得到了正面的响应,那事务能够成功提交的把握就比较大了,这也意味着因某个参与者提交时发生崩溃而导致大家全部回滚的风险相对变小。因此,在事务需要回滚的场景中,三段式提交的性能通常要比两段式提交好很多,但在事务能够正常提交的场景中,两者的性能都很差,甚至三段式因为多了一次询问,还要稍微更差一些。//减少回滚风险

        同样也是由于事务失败回滚概率变小,在三段式提交中,如果在 PreCommit 阶段之后发生了协调者宕机,即参与者没有等到 DoCommit 的消息的话,默认的操作策略将是提交事务而不是回滚事务或者持续等待,这就相当于避免了协调者单点问题的风险。//避免单点问题

        三段式提交对单点问题和回滚时的性能问题有所改善,但是对一致性风险问题并未有任何改进,甚至是略有增加的。譬如,进入PreCommit阶段之后,协调者发出的指令不是 Ack 而是Abort,而此时因网络问题,有部分参与者直至超时都未能收到协调者的 Abort 指令的话,这些参与者将会错误地提交事务,这就产生了不同参与者之间数据不一致的问题。//三段式并没有减少一致性风险

        //探究,Spring 事务的传播级别是否可以解决多个数据源的事务呢?

3、分布式事务

        本节所说的分布式事务(Distributed Transaction)特指多个服务同时访问多个数据源的事务处理机制。

        为什么 XA 的事务机制分布式环境中不好用了呢?

        这需要从 CAP 与 ACID 的矛盾说起。

(1)CAP定理

        CAP定理(Consistency、Availability、Partition Tolerance Theorem)描述了在一个分布式系统中,涉及共享数据问题时,以下三个特性最多只能同时满足其中两个:

  1. 一致性(Consistency):代表数据在任何时刻、任何分布式节点中所看到的都是符合预期的。
  2. 可用性(Availability):代表系统不间断地提供服务的能力。
  3. 分区容忍性(Partition Tolerance):代表分布式环境中部分节点因网络原因而彼此失联后,即与其他节点形成“网络分区”时,系统仍能正确地提供服务的能力。

        由于 CAP 定理已有严格的证明,那么接下来直接分析舍弃 C、A、P 时所带来的不同影响。

        (1)如果放弃分区容忍性(CA without P),意味着我们将假设节点之间的通信永远是可靠的。永远可靠的通信在分布式系统中必定是不成立的,这不是你想不想的问题,而是只要用到网络来共享数据,分区现象就始终存在。//在分布式系统中不成立

        (2)如果放弃可用性(CP without A),意味着我们将假设一旦网络发生分区,节点之间的信息同步时间可以无限制地延长。在现实中,选择放弃可用性的情况一般出现在对数据质量要求很高的场合中,除了 DTP 模型的分布式数据库事务外,著名的HBase也属于 CP 系统。

        (3)如果放弃一致性(AP without C),意味着我们将假设一旦发生分区,节点之间所提供的数据可能不一致。选择放弃一致性的 AP 系统是目前设计分布式系统的主流选择,因为 P 是分布式网络的天然属性,你再不想要也无法丢弃;而 A 通常是建设分布式的目的,如果可用性随着节点数量增加反而降低的话,很多分布式系统可能就失去了存在的价值,除非银行、证券这些涉及金钱交易的服务,宁可中断也不能出错,否则多数系统是不能容忍节点越多可用性反而越低的。//主流方案

        那么问题来了,“事务”原本的目的就是获得“一致性”,而在分布式环境中,“一致性”却不得不成为通常被牺牲、被放弃的那一项属性。如何解决这个矛盾呢?

        无论如何,我们建设信息系统,终究还是要确保操作结果至少在最终交付的时候是正确的,这句话的意思是允许数据在中间过程出错(不一致),但应该在输出时被修正过来。为此,人们又重新给一致性下了定义,将前面我们在 CAP、ACID 中讨论的一致性称为“强一致性”(Strong Consistency),而把牺牲了 C 的 AP 系统又要尽可能获得正确结果的行为称为追求“弱一致性”。// 换一种思路思考问题,保证正确性 -> 非常聪明的想法,技术都是妥协创新出来的

        在弱一致性里,人们又总结出了一种稍微强一点的特例,被称为“最终一致性”(Eventual Consistency),它是指如果数据在一段时间之内没有被另外的操作更改,那它最终会达到与强一致性过程相同的结果

(2)如何保证最终一致性?

        最终一致性的概念来源于 BASE 理论。BASE 分别是基本可用性(Basically Available)、柔
性事务(Soft State)和最终一致性(Eventually Consistent)的缩写。

        BASE 理论为实现最终一致性提供了一种非常有价值的分布式事务解决思路,那就是“可靠事件队列”,就简单的理解为消息中间件好了,本质上差不多。

        “可靠事件队列”是依靠持续重试来保证可靠性的解决方案,它在计算机的其他领域中已被频繁使用,也有了专门的名字——“最大努力交付”(Best-Effort Delivery),譬如 TCP 协议中未收到 ACK 应答自动重新发包的可靠性保障就属于最大努力交付。而可靠事件队列还有一种更普通的形式,被称为“最大努力一次提交”(Best-Effort 1PC),指的是将最有可能出错的业务以本地事务的方式完成后,采用不断重试的方式来促使同一个分布式事务中的其他关联业务全部完成。//不断重试+幂等性

(3)TCC事务(冻结资源)

        可靠消息队列虽然能保证最终结果的相对可靠性,但整个过程完全没有任何隔离性
言,虽然在一些业务中隔离性是无关紧要的,但在有些业务中缺乏隔离性就会带来许多麻烦,比如“超售”的问题。// 消息队列无法保证隔离性

        所以如果业务需要隔离,那通常就应该重点考虑 TCC 方案,该方案天生适用于需要强隔离性的分布式事务中。

        TCC 是另一种常见的分布式事务机制,它是 “Try-Confirm-Cancel” 三个单词的缩写,它分为以下三个阶段:

  1. Try:尝试执行阶段,完成所有业务可执行性的检查(保障一致性),并且预留好全部需要用到的业务资源(保障隔离性)。
  2. Confirm:确认执行阶段,不进行任何业务检查,直接使用 Try 阶段准备的资源来完成业务处理。Confirm阶段可能会重复执行,因此本阶段执行的操作需要具备幂等性
  3. Cancel:取消执行阶段,释放 Try 阶段预留的业务资源。Cancel 阶段可能会重复执行,因此本阶段执行的操作也需要具备幂等性

        //在持续重试的模式下,会发送重复的消息,所以幂等性很重要。

        TCC 其实有点类似 2PC 的准备阶段和提交阶段,但 TCC 是在用户代码层面,而不是在基础设施层面,这为它的实现带来了较高的灵活性,可以根据需要设计资源锁定的粒度。//业务侵入式较强的事务方案

        TCC 在业务执行时只操作预留资源,几乎不会涉及锁和资源的争用,具有很高的性能潜力。但是TCC也带来了更高的开发成本和业务侵入性,即更高的开发成本和更换事务实现方案的替换成本,所以,通常我们并不会完全靠裸编码来实现 TCC,而是基于某些分布式事务中间件(譬如阿里开源的 Seata)去完成,尽量减轻一些编码工作量。

(4)SAGA事务(补偿资源)

        TCC 事务具有较强的隔离性,避免了“超售”的问题,而且其性能一般来说是本篇提及的几种柔性事务模式中最高的,但它仍不能满足所有的场景。TCC 的业务侵入性很强,并不是所有的资源都可以让你去 Try,比如尝试冻结银行余额,所以 TCC 中的第一步 Try 阶段往往无法施行。//不是所有的资源都可以去冻结

        因此只能考虑采用另外一种柔性事务方案:SAGA 事务。SAGA 在英文中是“长篇故事、长篇记叙、一长串事件”的意思。//长时间事务

        所谓“长时间事务”(Long Lived Transaction)就是把一个大事务分解为可以交错运行的一系列子事务集合。原本 SAGA 的目的是避免大事务长时间锁定数据库的资源,后来才发展成将一个分布式环境中的大事务分解为一系列本地事务的设计模式。//分解事务——再一次使用拆分思想

        SAGA 由两部分操作组成:

        阶段一:

        将大事务拆分成若干个小事务,将整个分布式事务 T 分解为 n 个子事务,命名为 T1,T2,…,Ti,…,Tn。每个子事务都应该是或者能被视为原子行为。如果分布式事务能够正常提交,其对数据的影响(即最终一致性)应与连续按顺序成功提交 Ti 等价。

        为每一个子事务设计对应的补偿动作,命名为C1,C2,…,Ci,…,Cn。Ti 与 Ci 必须满足以下条件。

  1. Ti 与 Ci 都具备幂等性。
  2. Ti 与 Ci 满足交换律(Commutative),即无论先执行 Ti 还是先执行 Ci,其效果都是一样的。
  3. Ci 必须能成功提交,即不考虑 Ci 本身提交失败被回滚的情形,如出现就必须持续重试直至成功,或者被人工介入为止。

        // 拆分事务+设计事务补偿动作

        如果 T1 到 Tn 均成功提交,那事务顺利完成,否则,要采取以下两种恢复策略之一。

        阶段二:

        正向恢复(Forward Recovery):如果 Ti 事务提交失败,则一直对 Ti 进行重试,直至成功为止(最大努力交付)。这种恢复方式不需要补偿,适用于事务最终都要成功的场景,譬如在别人的银行账号中扣了款,就一定要给别人发货。正向恢复的执行模式为:T1,T2,…,Ti(失败),Ti,(重试)…,Ti+1,…,Tn。//无需补偿

        反向恢复(Backward Recovery):如果 Ti 事务提交失败,则一直执行 Ci 对 Ti 进行补偿,直至成功为止(最大努力交付)。这里要求 Ci 必须(在持续重试后)执行成功。反向恢复的执行模式为:T1,T2,…,Ti(失败),Ci(补偿),…,C2,C1。//不断执行补偿,直至成功

        与 TCC 相比,SAGA 不需要为资源设计冻结状态和撤销冻结的操作,补偿操作往往要比冻结操作容易实现得多。譬如,账号余额直接在银行维护的场景,从银行划转货款到业务系统中,这步是经由用户支付操作来促使银行提供服务;如果后续业务操作失败,尽管我们无法要求银行撤销之前的用户转账操作,但是由业务系统将货款转回到用户账号上作为补偿措施却是完全可行的。

        SAGA 必须保证所有子事务都得以提交或者补偿,但 SAGA 系统本身也有可能会崩溃,所以它必须设计成与数据库类似的日志机制(被称为 SAGA Log)以保证系统恢复后可以追踪到子事务的执行情况,譬如执行至哪一步或者补偿至哪一步了。

        另外,尽管补偿操作通常比冻结/撤销容易实现,但保证正向、反向恢复过程严谨地进行也需要花费不少工夫,譬如通过服务编排、可靠事件队列等方式完成,所以,SAGA 事务通常也不会直接靠裸编码来实现,一般是在事务中间件的基础上完成,前面提到的 Seata 就同样支持 SAGA 事务模式。//实现复杂,依赖框架

        声明:上述文字为阅读周志明先生《凤凰架构》一书的读书笔记,大部分内容为书中摘要。

相关文章:

【分布式】分布式事务

目录 1、事务的发展 2、本地事务 (1)如何保障原子性和持久性? (2)如何保障隔离性? 2、全局事务 (1)XA事务的两段式提交 (2)XA事务的三段式提交…...

Spring Data 简介

Spring Data 是一个用于简化数据库访问的框架,它是 Spring 生态系统中的重要组成部分。以下是详细介绍: 一、背景和目的 在开发应用程序时,数据访问层的实现往往是比较复杂和繁琐的。开发人员需要编写大量的代码来实现诸如数据库连接、查询…...

【娱乐项目】基于批处理脚本与JavaScript渲染视频列表的Web页面

Demo介绍 一个简单的视频播放器应用,其中包含了视频列表和一个视频播放区域。用户可以通过点击视频列表中的项来选择并播放相应的视频,播放器会自动播放每个视频并在播放完毕后切换到下一个视频。本项目旨在通过自动化脚本和动态网页渲染,帮助…...

[MySQL]流程控制语句

流程控制语句需要借助存储过程才有效。关于存储过程,我会在后续的文章详述,本篇文章只是阐述流程控制语句。因此,大家只需要注意存储过程中相应的流程控制语句即可。 如果文中阐述不全或不对的,多多交流。 参考笔记三&#xff0c…...

Flink在Linux系统上的安装与入门

一、Flink的引入 这几年大数据的飞速发展,出现了很多热门的开源社区,其中著名的有Hadoop、Storm,以及后来的Spark,他们都有着各自专注的应用场景。Spark 掀开了内存计算的先河,也以内存为赌注,赢得了内存计…...

微信小程序Webview与H5通信

背景 近期有个微信小程序需要用到web-view嵌套H5的场景,该应用场景需要小程序中频繁传递数据到H5进行渲染,且需要保证页面不刷新。 由于微信小程序与H5之间的通信限制比较大,显然无法满足于我的业务场景 探索 由于微信小程序与webview的环境是…...

Debezium Engine监听binlog实现缓存更新与业务解耦

飞书文档 解决缓存与数据源数据不一致的方案有很多, 各有优缺点; 1.0、旁路缓存策略, 直接同步更新 读取流程: 查询缓存。如果缓存命中,则直接返回结果。如果缓存未命中,则查询数据库。将数据库查询到的数据写入缓存,并设置一个…...

docker搭建socks5代理

准备工作 VPS安全组/策略放行相应端口如启用了防火墙,放行相应端口 实际操作 我们选用“历史悠久”的Dante socks5 代理服务器,轻量、稳定。Github也有对dante进行进一步精简的镜像,更为适宜。github项目地址如下: https://gi…...

scanf函数和printf函数的格式化输入输出

#include<stdio.h> int main() {int a;double b;char c;scanf("a%d,b%lf:c%c",&a,&b,&c); //float型输入时使用%f占位&#xff0c;double型使用%lf占位&#xff1b;输出时二者相同都是%f即可。if(a>0)printf("a%-10d,b%20.3lf,c%c",a…...

Day31 贪心算法 part05

56. 合并区间 本题也是重叠区间问题&#xff0c;如果昨天三道都吸收的话&#xff0c;本题就容易理解了。 代码随想录 class Solution {public int[][] merge(int[][] intervals) {Arrays.sort(intervals, (a,b) -> Integer.compare(a[0], b[0]));List<int[]> result …...

uniapp连接mqtt频繁断开原因和解决方法

mqtt参考文档&#xff1a;MQTT.js 入门教程 | EMQ、MQTT.js 入门教程 - EMQX - 博客园 uniapp引用MQTT频繁断开的问题可能由于以下几个原因导致&#xff1a; 网络不稳定&#xff1a;频繁断开可能是由于网络不稳定导致的&#xff0c;可以尝试优化网络连接。 心跳机制问题&…...

【数据结构-队列】力扣641. 设计循环双端队列

设计实现双端队列。 实现 MyCircularDeque 类: MyCircularDeque(int k) &#xff1a;构造函数,双端队列最大为 k 。 boolean insertFront()&#xff1a;将一个元素添加到双端队列头部。 如果操作成功返回 true &#xff0c;否则返回 false 。 boolean insertLast() &#xff1…...

leetcode3250. 单调数组对的数目 I,仅需1s

题目&#xff1a; https://leetcode.cn/problems/find-the-count-of-monotonic-pairs-i/description/ 不为别的&#xff0c;只是记录下这个超过100%&#xff0c;而且比原先最快的快了一个量级 不知道咋分析&#xff0c;反正得出结论就是&#xff0c;变大不变&#xff0c;变小…...

安全基线检查

一、安全基线检测基础知识 安全基线的定义 安全基线检查的内容 安全基线检查的操作 二、MySQL的安全基线检查 版本加固 弱口令 不存在匿名账户 合理设置权限 合理设置文件权限 日志审核 运行账号 可信ip地址控制 连接数限制 更严格的基线要求 1、禁止远程连接数据库 2、修改…...

C#读取本地图像的方法总结

前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任软件经理&#xff0c;从事C#上位机软件开发8年以上&#xff01;我们在C#开发C#程序的时候&#xff0c;有时候需要读取本地图像&#xff0c;下面进行详…...

力扣81:搜索旋转排序数组II

已知存在一个按非降序排列的整数数组 nums &#xff0c;数组中的值不必互不相同。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转 &#xff0c;使数组变为 [nums[k], nums[k1], ..., nums[n-1], n…...

信息系统项目管理-论文写作方法之背景二

为响应国家政务服务“一网、一门、一次”改革&#xff0c;打破“信息孤岛”现象&#xff0c;打造线上线下相融合、多级联动的政务服务一体化平台。XX市行政审批局欲整合市局及下属13镇区、500多个村居委会政务服务中心业务&#xff0c;梳理人社、民政、卫计委、公积金、交通等多…...

使用ffmpeg命令实现视频文件间隔提取帧图片

将视频按每隔五秒从视频中提取一张图片 使用 ffmpeg 工具&#xff0c;通过设置 -vf&#xff08;视频过滤器&#xff09;和 -vsync 选项 命令格式 ffmpeg -i input_video.mp4 -vf "fps1/5" output_%03d.png 解释&#xff1a; -i input_video.mp4&#xff1a;指定输…...

我们项目要升级到flutter架构的几点原因

一、探索 Flutter打造卓越移动应用的新时代框架 在移动应用开发的世界里&#xff0c;Flutter已经成为了一个炙手可热的话题。诞生于Google的怀抱&#xff0c;Flutter以其独特的优势和理念&#xff0c;正在引领一场全球范围内的应用开发 ** 。本文将深入探讨Flutter项目的特点、…...

【简单好抄保姆级教学】javascript调用本地exe程序(谷歌,edge,百度,主流浏览器都可以使用....)

javascript调用本地exe程序 详细操作步骤结果 详细操作步骤 在本地创建一个txt文件依次输入 1.指明所使用注册表编程器版本 Windows Registry Editor Version 5.00这是脚本的第一行&#xff0c;指明了所使用的注册表编辑器版本。这是必需的&#xff0c;以确保脚本能够被正确解…...

ElasticSearch为什么不能在query阶段直接返回_id,从而避免fetch?

整理自Github的一个issue,也正好解答了我的疑惑 https://github.com/elastic/elasticsearch/issues/17159 提问 是否可以避免搜索的fetch阶段并仅返回文档ID&#xff1f;查询阶段结束时是否有_id&#xff0c;这样当我只需要_id时&#xff0c;fetch就多余了&#xff1f;可以通过…...

网安瞭望台第5期 :7zip出现严重漏洞、识别网络钓鱼诈骗的方法分享

国内外要闻 7 - Zip存在高危漏洞&#xff0c;请立刻更新 2024 年 11 月 24 日&#xff0c;do son 报道了 7 - Zip 中存在的一个高严重性漏洞 CVE - 2024 - 11477。7 - Zip 是一款广受欢迎的文件压缩软件&#xff0c;而这个漏洞可能会让攻击者在存在漏洞的系统中执行恶意代码。…...

获 2023 年度浙江省科学技术进步奖一等奖 | 网易数智日报

11 月 22 日&#xff0c;加快建设创新浙江因地制宜发展新质生产力动员部署会暨全省科学技术奖励大会在杭州隆重召开。浙江大学、网易数智等单位联合研发的“大规模结构化数据智能计算平台及产业化”项目获得 2023 年度浙江省科学技术进步奖一等奖。 加快建设创新浙江因地制宜发…...

SQL基础入门 —— SQL概述

目录 1. 什么是SQL及其应用场景 SQL的应用场景 2. SQL数据库与NoSQL数据库的区别 2.1 数据模型 2.2 查询语言 2.3 扩展性 2.4 一致性与事务 2.5 使用场景 2.6 性能与扩展性 总结 3. 常见的SQL数据库管理系统&#xff08;MySQL, PostgreSQL, SQLite等&#xff09; 3.…...

【附录】Rust国内镜像设置

目录 前言 &#xff08;1&#xff09;设置环境变量 &#xff08;2&#xff09;安装Rust &#xff08;3&#xff09;设置crates镜像 前言 本节课来介绍下如何在国内高速下载安装Rust和Rust依赖&#xff0c;由于网络原因&#xff0c;我们在安装Rust和下载项目依赖时都很慢&am…...

量化交易系统开发-实时行情自动化交易-8.2.发明者FMZ平台

19年创业做过一年的量化交易但没有成功&#xff0c;作为交易系统的开发人员积累了一些经验&#xff0c;最近想重新研究交易系统&#xff0c;一边整理一边写出来一些思考供大家参考&#xff0c;也希望跟做量化的朋友有更多的交流和合作。 接下来会对于发明者FMZ平台介绍。 发明…...

MATLAB —— 机械臂工作空间分析

系列文章目录 前言 本示例展示了如何使用可操作性指数对不同类型的机械手进行工作空间分析。工作空间分析是一种有用的工具&#xff0c;可用于确定机器人工作空间中最容易改变末端效应器位置和方向的区域。本示例的重点是利用不同的可操控性指数类型来分析各种机械手的工作空间…...

向日葵连接xrdp虚拟桌面

x2go的虚拟性没有那么好。而xrdp&#xff0c;可以实现较好的配置&#xff0c;并且能适应本机电脑的分辨率&#xff0c;非常方便。 配置xrdp可以参考这个&#xff1a; https://blog.csdn.net/weixin_54227557/article/details/143303803 然后就是重启相关服务了。 sudo pkill…...

AI智算-正式上架GPU资源监控概览 Grafana Dashboard

下载链接 https://grafana.com/grafana/dashboards/22424-ai-gpu-20241127/...

goframe框架bug-记录

implement not found for interface ICompany, forgot register? 错误解决检查&#xff1a; 1.有没有init 2. 注入问题 3. 注入问题...

济南做网站个人/商丘seo博客

[通讯]如何设置集团电话的等级? (集团电话的具体型号忘了汗 好像是 180I )客户要求分机号为826的电话 可以打出国际长途和国内长途,原来只可以打市话。注明一点,这里的编程必须使用专用话机才可以第一步首先按“转换”键&#xff0c;输入800(设定编程代码)&#xff0c;再输入…...

做外贸如何分析客户网站/如何优化网站排名

Unity 小科普 老规矩&#xff0c;先介绍一下 Unity 的科普小知识&#xff1a; Unity是 实时3D互动内容创作和运营平台 。包括游戏开发、r美术、建筑、汽车设计、影视在内的所有创作者&#xff0c;借助 Unity 将创意变成现实。Unity 平台提供一整套完善的软件解决方案&#xf…...

网站制作 需要什么网络技术/网站首页制作网站

引&#xff1a;http://www.javaeye.com/topic/283668 近期taowen同学连续发起了两起关于贫血模型和领域模型的讨论&#xff0c;引起了大家的广泛热烈的讨论&#xff0c;可是讨论(或者说是争论)的结果究竟如何&#xff0c;我想值得商榷。问题是大家对贫血模型和领域模型都有自己…...

网站开发项目比赛/舆情信息网

目的 本身装有python3.8&#xff0c;和一些依赖包。同时想使用Spyder类似MATLAB工具箱的功能Variable Explorer。 环境 win10python3.8spyder5.0.5 步骤 1、Spyder安装 按照官网建议&#xff0c;可使用Anaconda安装。若没有&#xff0c;可使用Windows独立安装包&#xff…...

价格列表 wordpress/在百度上怎么发布信息

一般只有父pom文件中才有dependencyManagement. dependencies&#xff1a;子POM会完全继承父POM中声明的dependencies&#xff0c;如果子POM中没有声明某个依赖项&#xff0c;但是父POM中声明了该依赖项&#xff0c;就会直接从父POM中继承该依赖项&#xff0c;如果子POM也声明…...

.net网站开发优点/搜索引擎优化seo论文

js 数组去重 记得js 数组去重3种方法&#xff1a; for 循环两次 使用 Array.prototype.indexOf[注意这个方法是 es5 的&#xff0c;兼容性] 使用 对象的键具有唯一性的这一特性&#xff0c;其实在python中的 sets key 也是具有唯一性的 // 使用第三种方法实现的兼容性处理&…...