数据一致性问题剖析与实践(三)——分布式事务的一致性问题
一、前言
之前我们讨论了几种场景的一致性问题
- 冗余数据存储中的一致性问题
- 分布式共识中的一致性问题
- 单机事务中的一致性问题
本文将围绕分布式事务中的一致性问题展开讨论。
二、分布式环境的最大难题
相对于单机环境,分布式环境中,一致性问题最大的挑战,就是不可靠的网络和时钟。
2.1 不可靠的网络
互联网及多数数据中心内部网络为异步网络 。在此网络中,节点间数据包传输存在诸多不确定性。消息发送后等待响应期间,状况百出:
- 请求可能滞留于消息队列或因网络分区无法及时抵达远程接收节点;
- 远程接收节点可能崩溃、暂时无法响应(如执行长时间垃圾回收);
- 即便远程节点正确处理请求,回复消息也可能在网络中丢失。
由于网络延迟不确定,数据包及回复消息皆可能丢失或延迟,发送者仅知未收到响应,却难判原因,常只能不断重发消息 。
2.2 不可靠的时钟
现代计算机内部至少有两种不同的时钟,墙上时钟返回的是自 1970 年 1 月 1 日以来的秒数或毫秒数,即 UNIX 时间戳;单调时钟是一个单调自增的时间计数器,常用于测量持续的时间间隔。
每一台计算机都拥有自己的石英时钟设备,也就是说每台机器都维护了自己本地的时间版本。但是这些石英钟设备并非绝对准确,可能存在时钟漂移现象(运行速度加快或减慢),一个节点上的时间可能与另一个节点上的时间完全不同。例如谷歌假设其服务器的时钟偏移为 200ppm(百万分之一),相当于如果每 30 秒与 NTP 服务器重新同步一次,则可能出现的最大偏差为 6ms,如果每天同步一次,则最大偏差为 17s。
由于最后写入的消息是由一个节点上的时钟来决定的,这就避免不了一个事实:这个时钟可能是错误的。所以通过时间戳来进行跨节点的事件排序依然无法解决下面这几类问题:
- 后续发生的写操作可能无法覆盖较早版本的值,原因是后者节点的时钟太快了,导致一些数据被偷偷地丢弃;
- 由于时钟精度的限制,两个节点可能产生了完全相同的时间戳;
- 闰秒会产生一分钟为 59 秒或 61 秒的调整,这可能会使系统出现混乱。
虽然墙上时钟可以与 NTP(Network Time Protocol)服务器、GPS 或数据中心内部设立的原子钟等更加精确的时钟同步,纠正自己的时间,但如果两者的时钟差距很大,在时间重置后应用程序可能会看到时间突然倒退或向前跳跃现象,这会引发新的时钟问题:NTP 同步可能会产生时钟回拨,使得后写入的数据拥有较旧=早的时间戳,导致该写入被抛弃。
因此节点的时钟可能与其它节点存在明显的不同步,尽管可以设置 NTP 服务器进行纠正,但是依靠时钟进行事件排序仍然存在一定的风险,所以基于递增计数器的逻辑时钟或全局时钟是比物理时钟更可靠的方式。逻辑时钟依据事件的相对前后关系为其分配唯一 ID,并按照 ID 大小判断消息的新旧,这就避免了时间排序潜在的冲突。
三、理论基础
3.1 事务特性 ——ACID
单机事务的 ACID 特性,是保障数据正确性与一致性的基础准则
-
原子性(Atomicity):事务被视为一个不可分割的整体,所有操作要么全部成功提交,要么全部失败回滚。例如在银行转账中,从账户 A 扣款与向账户 B 入账必须同时完成,若扣款成功但入账失败,整个事务需回滚,确保资金不会凭空消失或增加 。
-
隔离性(Isolation):多个并发事务之间相互隔离,互不干扰。不同隔离级别(读未提交、读已提交、可重复读、串行化)定义了事务间对数据访问的可见范围,避免脏读、不可重复读和幻读等问题 。
其本质是控制数据的访问范围,在并发场景下,实现不同隔离级别下的“对外一致性”。
-
持久性(Durability):一旦事务提交成功,其对数据的修改将永久保存,即使系统出现故障(如断电、宕机)也不会丢失。银行交易完成后,账户余额的变更会持久化存储,确保数据的可靠性 。
-
一致性(Consistency):事务执行前后,数据需从一个合法状态转换到另一个合法状态。如电商下单时,库存数量必须与订单数量保持逻辑一致,不能出现超卖现象,以维持业务规则的正确性 。
只有保证了原子性、隔离性、持久性的前提下,才能实现一致性,一致性是事务的目的。
3.2 BASE理论
BASE 理论是 eBay 架构师对大规模互联网分布式系统实践的总结,并在 ACM 上发表了[3] Base: An Acid Alternative一文,其核心思想是即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。
BASE 是对 CAP 中一致性和可用性权衡的结果,对分布式系统提出了三个概念:
- 基本可用(Basically Available)
- 软(弱)状态(Soft State)
- 最终一致性(Eventually Consistent)
BASE 理论表明要实现系统的横向扩展,就要对业务进行功能分区,将数据的不同功能组迁移到相互独立的数据库服务器上。由于降低了事务的耦合度,就不能单纯依赖数据库的约束来保证功能组之间的一致性,BASE 提出使用消息队列来异步执行解耦后的命令。
BASE 理论强调的最终一致性允许系统中的数据存在中间状态,并认为该状态不影响系统的整体可用性,即允许多个节点的数据副本存在数据延时。但是在一定的期限内,应当保证所有副本数据一致,达到数据的最终一致。
3.3 一致性分类
因为一致性的实现有相当大的代价,但是在实际项目需求中,我们针对一致性的诉求是不同的,所以我们可以根据自己的应用场景去实现自己的一致性。
常见一致性分类如下:
- 强一致性:任何时刻,所有节点对同一份数据的读取结果完全相同。以金融交易系统为例,用户转账后,无论从哪个节点查询余额,都应立即显示更新后的数值。这种一致性等级能最大程度保证数据准确性,但实现难度高,通常需通过严格的锁机制、同步协议(如两阶段提交)来确保所有节点数据实时同步,这会显著降低系统并发性能。
- 最终一致性:允许系统在一段时间内存在数据不一致,但经过一段时间后,所有节点数据将达成一致。例如,社交平台的点赞数更新,用户点赞后,部分节点可能稍晚才显示点赞数量变化。这种模型适用于对实时性要求不高的场景,通过异步复制、消息队列等技术实现,在保障数据一致性的同时,提升了系统吞吐量和可用性。
- 顺序一致性:所有节点看到的操作顺序相同,不要求操作立即同步到所有节点,但需保证操作执行顺序一致。在分布式日志系统中,各节点记录的操作顺序必须相同,以便后续分析和恢复。它在一致性和性能之间取得平衡,相比强一致性,对系统性能影响较小,但仍需协调各节点操作顺序。
- 弱一致性:对数据一致性要求最低,仅保证部分数据在特定条件下的一致性。在某些实时性要求极低的缓存场景中,允许数据存在较大延迟和不一致。虽然牺牲了一致性,但能大幅提升系统性能和响应速度,适用于对数据一致性敏感度低的业务。
四、原子性
很多时候我们讲的分布式事务解决方案,都是围绕事务的原子性来展开的。
4.1 定义
分布式事务的原子性要求跨多个节点或服务的操作集合,如同单机事务一样,具备 “要么全做,要么全不做” 的特性。在微服务架构中,一个订单创建事务可能涉及订单服务创建订单记录、库存服务扣减库存、支付服务处理支付,这些操作必须整体成功或失败,否则会出现订单生成但库存未扣减、已支付却无订单记录等数据混乱情况 。
4.2 归纳演绎
我们先不管市面上的分布式事务解决方案,我们来一步一步仔细推演思考下,如果是我们自己来设计,我们会如何做。
①不可靠的网络——确认应答模式&重试机制
首先,我们需要问自己一个问题,在分布式环境中我们如何解决网络的不可靠问题的?
具体点,针对一次rpc请求,我们如何确保本次请求是成功的?
参考TCP中可靠传输机制,其实我们很容易发现,我们很多分布式的机制,都是基于请求-应答机制来保证网络的可靠性的。
这个也很好理解,在我们生活中,我们打招呼时,只有对方应答了,我们才能确认对方是听到我们的说话了。
但如果对方没听到,我们如何保证对方能够听到呢?
当然是重新打招呼呀!
对应到我们的问题,当服务提供方没有响应时,我们如何保证请求的可靠呢,方法只有一个——就是重试!
基于确认应答模式 和 重试机制,我们可以像搭积木一样开始设计我们的方案。
②二阶段提交(2PC):要么全做,要么全不做
回顾下我们的目标,我们的目标是在多节点的情况下,实现多节点上的操作要么一起成功,要么一起失败。
如何判断我们的操作成功了呢?
我们很自然能够想到,
我们可以对所有节点发送操作请求,如果所有请求返回成功了,那么就是整体成功了。
如果有其中任一节点失败了,那么整体的操作就应该一起失败。
怎么一起失败,就是把所有节点执行回滚操作。
而这就是**二阶段提交(2PC)**的雏形!
③TCC 模式:业务场景的2PC
TCC(Try - Confirm - Cancel)和 2PC 思路类似,把操作拆成三步:
- Try:尝试预留资源,比如预订酒店先锁定房间但不扣款;
- Confirm:确认提交,真正扣款并占用资源;
- Cancel:如果 Try 或 Confirm 失败,释放预留资源,比如取消房间预订。
每个阶段都靠确认应答确认成功,失败就重试或回滚,确保事务完整。
④三阶段提交(3PC):减少等待,预防卡死
2PC 有个问题:如果协调者在第二阶段崩溃,节点可能一直等待,导致系统卡住。3PC 加了一个预提交阶段,就像聚会前先和大家确认 “时间地点没问题吧?”,提前排除潜在问题。这样即便协调者中途出故障,节点也能根据预提交结果,更自主地决定提交或回滚,减少阻塞。
本质是增加环节,减少占用实际资源的时间,减少阻塞。
⑤回滚操作的灵魂拷问
Mysql为什么能够回滚?
在Mysql中,因为写操作会占有行锁,这意味着在事务提交前,该数据行的写操作是串行化的,这就避免数据竞态条件竞争的问题。
同时通过redo log事务日志,我们可以回溯到之前的数据版本,使我们回滚操作成了可能。
锁机制和事务日志使Mysql可以正确的进行回滚操作。
可以不回滚吗?
答案是可以!
审一下题目,目标是要么全部成功,要么全部失败。
那么我只要保证都成功,就不会有失败,这样就可以实现一样的效果。
⑥消息队列实现的思考——尽最大努力交付
这里我们可以参考消息队列实现。
消息队列的消息消费,支持至少消费一次,那消息队列是如何实现的呢?
答案就是我们在开头说的 重试 !通过不断的重试来保证消息最终的到达。
这也是为什么消息消费逻辑要支持幂等。
重试也有讲究,如何优雅的重试?
比如消息队列会设计重试间隔时间,基于短时间无法恢复的基础,会有重试间隔的设计。
重试次数也有讲究,不可能一直无限重试下去,所以会有死信队列的设计。
那我们如何实现事务呢,就是重试!
所以,在异步场景下,我们很多方案都是通过消息队列来实现最终的一致性,保证全部成功。
⑦消息队列发送如何保障一致性
mq消费能实现最终一致性,但是针对于业务服务来说,消息队列发送消息也是一次网络通信,也可能会出现不一致的问题。
所以我们需要保证消息队列的一致性问题
本地消息表
本地消息表是一种通过在本地数据库中记录消息状态来保障消息发送一致性的方法。
其核心思想是将消息的发送与本地事务绑定,通过定时任务或其他机制来确保消息最终能够成功发送到消息队列。
在这个过程中,应用系统在执行本地业务操作后,将相关消息记录插入本地数据库,并提交本地事务。定时任务会定期查询本地数据库中状态为未发送的消息,并尝试将其发送到消息队列。当消息发送成功后,定时任务会更新消息在本地数据库中的状态为已发送。
本质还是重试的思路,用定时任务重试发送失败的消息。
事务消息
事务消息是一种借助消息队列自身特性来保障消息发送一致性的方式。它通常基于消息队列提供的半事务消息机制,确保本地事务和消息发送的原子性。
应用系统首先向消息队列发送半事务消息,消息队列接收到消息后将其状态设置为暂存,并返回成功响应。然后应用系统开启本地事务并执行本地业务操作。如果本地事务成功,应用系统向消息队列确认发送消息;如果本地事务失败,应用系统则向消息队列回滚消息。消息队列根据应用系统的指令进行相应的操作,确保消息发送与本地事务的一致性。
这种方式和2PC类似,都是基于**prepare - commit **的思路。
只不过两者角度不同,2PC针对多节点的事务操作;事务消息保障的是本地事务和发送消息操作之间的事务操作。
4.3 原子性问题解决范式
原子性的解决思路大致分为两类:
- 回滚:当事务中任何一个操作失败时,通过补偿机制撤销已成功执行的操作,将系统状态恢复到事务开始前。
- 回滚,一般针对数据库说的
- 补偿,一般针对业务场景
- 最大努力交付:优先保证事务中尽可能多的操作能够成功执行,即使部分操作失败,也让系统处于相对可用的状态。
怎么实现呢,万变不离其宗,核心都是通过 确认应答模式 拉齐认知,利用重试机制 进行可靠性兜底。
4.4 思考——分布式事务的优与劣
4.4.1 优势:支撑复杂业务的基石
- 业务扩展性强:在互联网电商大促场景下,订单创建、库存扣减、支付处理等操作分布在不同微服务节点,分布式事务的原子性确保各环节要么共同完成,要么全部回滚。以双十一大促为例,即便每秒数万笔订单并发,也能避免超卖、资金错配等问题,保障业务顺利开展。
- 数据一致性保障:在金融分布式账本系统中,跨地域的转账交易涉及多个节点数据更新,通过分布式事务方案(如2PC),确保转出账户扣款与转入账户到账操作同步,避免资金凭空增减,维护金融数据的精准性。
- 高可用架构支撑:采用分布式事务的系统可通过多节点部署实现负载均衡与故障转移。当某节点出现故障时,其他节点可继续参与事务处理,如分布式数据库集群中,部分节点宕机不影响整体事务的原子性,维持系统服务的连续性 。
4.4.2 劣势:性能与复杂度的双重挑战
-
性能损耗显著:2PC、3PC等协议在协调多节点时,需多次网络通信与等待确认,引入额外延迟。例如在高并发订单场景中,2PC的两阶段确认过程可能使订单处理响应时间增加数倍,影响用户体验。
-
系统复杂度激增:分布式事务涉及协调者、参与者、消息传递等多个组件,故障排查困难。以TCC模式为例,每个服务需实现Try、Confirm、Cancel三个阶段逻辑,且需处理网络超时、事务回滚等异常,增加开发与维护成本。
-
资源消耗大:为保证原子性,锁机制(如分布式锁)会占用大量资源,降低系统并发能力。在秒杀活动中,大量事务竞争锁资源,可能导致部分请求长时间等待,甚至超时失败,影响业务吞吐量。
-
网络依赖风险:由于依赖网络通信实现节点间协调,不可靠网络会放大事务失败概率。例如网络分区导致节点间无法通信,可能使2PC陷入阻塞,3PC也难以完全规避此类问题,威胁系统稳定性。
4.5 实现场景
4.5.1 OceanBase(2PC)
OceanBase 数据库实现了原生的两阶段提交协议,保证分布式事务的原子性。
两阶段提交协议中包含两种角色,协调者(Coordinator)和参与者(Participant)。协调者负责整个协议的推进,使得多个参与者最终达到一致的决议。参与者响应协调者的请求,根据协调者的请求完成 prepare 操作及 commit/abort 操作。
PREPARE 阶段
协调者:协调者向所有的参与者发起 prepare request
参与者:参与者收到 prepare request 之后,决定是否可以提交,如果可以则持久化 prepare log 并且向协调者返回 prepare 成功,否则返回 prepare 失败。
COMMIT阶段
协调者:协调者收齐所有参与者的 prepare ack 之后,进入 COMMIT 状态,向用户返回事务 commit 成功,然后向所有参与者发送事务 commit request。
参与者:参与者收到 commit request 之后释放资源解行锁,然后提交 commit log,日志持久化完成之后给协调者回复commit ok
消息,最后释放事务上下文并退出。
4.5.2 Seata框架——业务框架
Seata(Simple Extensible Autonomous Transaction Architecture)是一款开源的分布式事务解决方案框架,提供了AT、TCC、Saga等多种事务模式,可适配不同业务场景需求,尤其适用于微服务架构下的复杂业务逻辑。
以AT(自动补偿)模式为例,它对业务代码的侵入性较低。在执行事务时,Seata会自动对业务数据进行快照保存,执行本地事务操作后,将操作记录和快照信息上报给事务协调器TC(Transaction Coordinator)。当事务需要回滚时,根据快照和操作记录自动生成反向SQL,恢复数据到事务开始前的状态。在电商订单场景中,涉及订单服务、库存服务、支付服务等多个微服务,Seata能确保这些服务的操作在分布式环境下满足原子性要求,同时通过模块化设计降低开发和维护成本,开发者只需关注业务逻辑,无需手动编写复杂的事务补偿代码。
AT 模式本质是回滚,通过 全局锁+自动生成的反向SQL 实现回滚操作。
4.5.3 QMQ——本地消息表实现
QMQ(Quantum Message Queue)是去哪儿网自主研发的分布式消息队列,在保障消息一致性方面采用本地消息表方案。在业务系统执行本地事务(如订单创建)时,会同时将消息相关信息(消息内容、状态等)插入到本地数据库的消息表中,确保消息与本地事务的原子性。
随后,QMQ通过定时任务或异步线程扫描消息表,将状态为“未发送”的消息发送到消息队列。当消息成功发送后,更新消息表中的状态为“已发送”;若发送失败,则继续重试。这种方式简单可靠,适用于对一致性要求较高且业务逻辑相对简单的场景,如电商系统中订单状态变更通知、物流信息推送等。通过本地消息表,QMQ实现了业务操作与消息发送的最终一致性,同时降低了系统的耦合度。
4.5.4 Rocketmq——事务消息
RocketMQ是一款分布式消息中间件,其事务消息功能基于半事务消息机制,确保本地事务与消息发送的原子性,适用于分布式事务场景中的异步解耦与最终一致性保障。
在发送事务消息时,生产者先向RocketMQ发送半事务消息,此时消息对消费者不可见;接着执行本地事务,根据事务执行结果向RocketMQ发送提交或回滚请求。若本地事务成功,RocketMQ将消息标记为可消费,消费者接收并处理消息;若本地事务失败,RocketMQ删除半事务消息,避免无效消息被消费。(本质是二阶段提交)
兜底情况通过定时任务回查实现。(本质是重试)
五、隔离性
常见场景
在分布式环境中,事务隔离性面临更多挑战,一些典型问题严重影响数据一致性。
以下列举几种业务中常见的因为隔离性产生的问题:
- 主从延迟:在主从数据库架构下,主库数据更新后同步到从库存在时间差。若应用在同步完成前从从库读取数据,可能获取到旧值,导致数据不一致。例如电商商品价格在主库修改后,从库因延迟未及时更新,用户查询时看到的仍是旧价格 。
- mq 消费反查查询到旧值:通过消息队列(MQ)进行数据同步时,消费者接收到消息后进行业务处理,若处理过程中需要反查数据库确认数据状态,可能因数据库更新不及时查到旧值,进而导致业务逻辑错误。如订单状态变更消息发送到 MQ,消费者处理时反查数据库,却因数据库同步延迟获取到未更新的状态 。
解决思路
和单机事务类似,只不过分布式环境更为复杂。
- 读屏障
- 强制读主,避免多节点读
比如业务操作中,我们常会提供主库查询接口用于某些一致性要求高的场景 - 分布式快照读,该方案常见于数据库,和单机事务类似,唯一不同就是需要解决分布式的事务id问题
以蚂蚁的分布式数据库OceanBase为例,它利用分布式共识算法维护的全局时间戳(解决不可靠的时钟问题)来定义快照版本,根据事务隔离级别来决定读取对应的数据快照。
- 强制读主,避免多节点读
- 使用锁机制控制并发:本质是细粒度维度(如数据行、数据范围)去串行化写操作,来保证数据写的正确性
就隔离性而言,分布式环境 和单机环境基本一致,不过需要考虑 多副本数据的读写规则,来实现对外的一致性。本质其实冗余数据存储场景下的数据一致性问题,详细的可以看本系列的第一篇文章,数据一致性问题剖析与实践(一)——冗余数据存储&分布式共识决策中的一致性问题。
六、持久性
定义
分布式事务的持久性指事务提交后,其产生的数据变更在分布式环境下的多个节点或存储介质中,都能可靠持久保存,不会因节点故障、网络分区等问题丢失。在分布式数据库集群中,数据写入成功提交后,无论哪个节点出现故障,数据都应可恢复且保持一致 。
解决范式
- 持久化存储,避免数据丢失:采用多副本存储、日志持久化等技术保障数据持久性。分布式数据库通过将数据同步复制到多个节点,即使个别节点故障,其他副本仍可提供数据服务;同时,事务操作日志会持久化记录到磁盘,用于故障恢复时重做或回滚事务,确保数据不丢失、事务可恢复 。
- 副本存储,异地容灾
七、总结
分布式事务和单机事务非常类似,都需要去实现ACID特性。
只不过,在分布式环境中,由于不可靠的网络和时钟,导致我们需要通过确认应答模式&重试机制来增加一些机制来实现 事务的原子性。
由于这些额外的机制,会导致性能的急剧下滑(全局锁&重试),所以我们常常为了平衡,会根据自己的业务场景去决策实现哪种程度的一致性(强一致性/顺序一致性/最终一致性)。
所以考虑到分布式事务的高昂成本,常规的设计思路应是:
1.思考当前场景是否需要分布式事务,如果不需要,则尽量避免,比如 商品库存和库存流水常常都在一个领域操作内,我们就尽量设计在一个库中,因为此时本地事务就可以解决,不需要分布式事务
2.如果实在需要分布式事务,思考几个问题
- 思考业务可以容忍的场景,是强一致性,还是最终一致性?
- 思考业务逻辑是否可以回滚,是否支持补偿?
- 思考业务逻辑之间的依赖,是异步执行还是同步执行?
3.根据公司已有的基建选择合适(成本低)的方案
- 回滚
- 前提:业务支持回滚/补偿
- 适用场景:
- 强一致性
- 支持回滚/补偿
- 同步执行
- 2PC、3PC
- TCC
- 尽最大努力交付
- 前提:业务异步执行
- 适用场景:
- 最终一致性
- 异步执行
- 消息队列
- 本地消息表
- 事务消息
从模型领域设计上来讲,理想的领域交互,应该是通过事件机制,通过类似消息队列去实现事件的异步扩散,实现模型之间的最终一致性。
参考文档
OceanBase两阶段提交
设计数据密集型应用 - 中文翻译
漫谈分布式共识算法与数据一致性
RocketMQ事务消息
相关文章:
数据一致性问题剖析与实践(三)——分布式事务的一致性问题
一、前言 之前我们讨论了几种场景的一致性问题 冗余数据存储中的一致性问题分布式共识中的一致性问题单机事务中的一致性问题 本文将围绕分布式事务中的一致性问题展开讨论。 二、分布式环境的最大难题 相对于单机环境,分布式环境中,一致性问题最大…...
分布式理论和事务
微服务和分布式 微服务 是一种软件架构风格,它将应用程序拆分成一系列小型、独立的服务,每个服务专注于单一功能,彼此通过轻量级通信机制(如 API)进行交互。微服务通常是松耦合的,可以独立开发、部署和扩展…...
基于Flask与Ngrok实现Pycharm本地项目公网访问:从零部署
目录 概要 1. 环境与前置条件 2. 安装与配置 Flask 2.1 创建虚拟环境 2.2 安装 Flask 3. 安装与配置 Ngrok 3.1 下载 Ngrok 3.2 注册并获取 Authtoken 4. 在 PyCharm 中创建 Flask 项目 5. 运行本地 Flask 服务 6. 启动 Ngrok 隧道并获取公网地址 7. 完整示例代码汇…...
flutter和vue3项目利用webview_flutter插件通信
近来需要实现一个功能: flutter项目的会员中心页面跳转到vue3项目的活动页,点击该活动页面的“签到”按钮后到flutter项目的积分中心页面进行签到,签到成功后手动返回上一个页面即vue3活动页面的按钮状态更新问题(需更新为“已签到”)。 实现方法:通过webview_flutter …...
sql 根据时间范围获取每日,每月,年月的模版数据
1:获取每日模版数据(参数也支持跨年) SELECT a.selected_date cdate FROM(SELECT adddate(1970-01-01,t4.i * 10000 t3.i * 1000 t2.i * 100 t1.i * 10 t0.i) selected_dateFROM( SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELEC…...
亚信安全与联通数科达成战略合作,成立联信事业部
4月22日,亚信安全与联通数字科技有限公司(以下简称“联通数科”)正式签署战略合作协议,双方宣布将联合成立“联信事业部”,仪式上,联通数科董事长孙江山与亚信安全董事长何政为“联信事业部”成立揭牌&…...
第五节:进阶特性高频题-Teleport与Suspense组件应用
Teleport:解决模态框/弹窗的DOM层级问题(如挂载到body) Suspense:处理异步组件加载状态(fallback内容展示) 深入解析 Vue3 的 Teleport 与 Suspense 组件 一、Teleport 组件:突破 DOM 层级限制…...
如何使用 uv 构建 Python 包并本地安装
本文将逐步指导你创建一个简单的 Python 包,并将其本地安装到机器或云环境中。完成本教程后,你将拥有一个可复用的 Python 库,可直接通过 pip 安装或在项目中导入使用。 步骤详解 Step 0: 选择构建工具 - 使用 uv 推荐理由:uv 是…...
集结号海螺捕鱼组件搭建教程与源码结构详解(第一篇)
本系列将基于 C Unity3D Java MySQL 构建的集结号海螺捕鱼平台,全面拆解组件架构、服务部署、客户端接入、数据库结构等内容,适合技术团队二次开发及运维部署。 一、整体架构说明 集结号海螺捕鱼平台采用三层结构: 客户端(Uni…...
RabbitMQ复习笔记
文章目录 MQ 概述同步调用拓展性差的问题性能下降的问题级联失败问题 异步调用举例 技术选型 RabbitMQRabbitMQ 安装RabbitMQ 收发消息交换机队列绑定关系模拟发送消息 RabbitMQ 数据隔离用户管理virtual host 授权 SpringAMOPSpringAMOP 快速入门消息发送消息接收 Work Queues…...
游戏开发核心技术解析——从引擎架构到攻防体系的完整技能树
游戏开发必备的7大技术体系,涵盖从Unity/Unreal引擎应用、C/C#编程范式到图形渲染管线构建等核心技术,特别剖析MMO游戏开发中的网络安全架构设计要点。通过2023年某头部游戏公司DDoS攻击事件,揭示实时防御策略与合规审计的关键作用。一、游戏…...
Execl 最佳字体和大小推荐[特殊字符]
文章目录 ✅ **通用推荐字体与字号**🔤 **字体说明**📊 场景推荐📁 办公文档(如财务报表、周报等)📈 数据可视表格📋 打印友好 🌐 多语言场景(中英文混排) ✅…...
JavaScript学习教程,从入门到精通,Ajax与Node.js Web服务器开发全面指南(24)
Ajax与Node.js Web服务器开发全面指南 一、初识Ajax 1.1 Ajax基本概念 语法知识点: Ajax (Asynchronous JavaScript and XML) 是一种无需重新加载整个网页的情况下,能够更新部分网页的技术核心对象:XMLHttpRequest工作原理: 创…...
VR 全景看车的独特优势
全方位沉浸式体验 VR 全景看车最显著的优势,就是为用户带来了全方位的沉浸式体验。通过 VR 技术,用户仿佛置身于真实的汽车展厅或试驾场景之中,能够 360 度无死角地观察车辆的外观、内饰、细节等各个方面 。无论是车辆的整体造型࿰…...
Kotlin高阶函数 vs Lambda表达式:关键区别与协作关系
先说结论: ✅ 高阶函数既可以用 Lambda 表达式,也可以用函数引用! 在 Kotlin 中,高阶函数(Higher-Order Function)和 Lambda 表达式密切相关,但它们是两个不同的概念: ✅ 简单理解…...
SQL技术终极指南:从内核原理到超大规模应用
一、DDL核心应用场景与最佳实践 1.1 表结构设计场景矩阵 业务场景核心语法要素典型实现案例电商用户画像JSON字段虚拟列索引CREATE TABLE users (id INT, profile JSON, AS (profile->>$.age) VIRTUAL, INDEX idx_age((profile->>$.age)))物联网时序数据分区表压…...
Qt实现语言切换的完整方案
在Qt中实现语言动态切换需要以下几个关键步骤,我将提供一个完整的实现方案: 一、准备工作 在代码中使用tr()标记所有需要翻译的字符串 cpp button->setText(tr("Submit")); 创建翻译文件 在.pro文件中添加: qmake TRANSLATION…...
消息中间件RabbitMQ02:账号的注册、点对点推送信息
一、默认用户登录和账号注册 1.登录 安装好了RMQ之后,我们可以访问如下地址: RabbitMQ Management 输入默认的管理员密码,4.1.0的管理员账号和密码是: guest guest 2.添加账号 consumer consumer 添加成功后: 角色…...
php 支付宝官方 Alipay Easy SDK
使用 Alipay Easy SDK。 打造最好用的支付宝开放平台服务端SDK,Alipay Easy SDK让您享受极简编程体验,快速访问支付宝开放平台开放的各项核心能力。 要求: PHP版本 > 7.0安装PHP cURL扩展安装PHP OpenSSL扩展安装PHP fileinfo扩展 使用…...
深入理解 java synchronized 关键字
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
即时角色:使用可扩展的扩散变换器框架个性化任何角色
Paper Title: InstantCharacter: Personalize Any Characters with a Scalable Diffusion Transformer Framework 论文发布于2025年4月16日 Abstract部分 U-Net架构的局限性:传统的基于U-Net架构的定制方法存在一些问题,如泛化能力不足和生成图像质量的损失。 U-Net模型需要…...
开源作业调度框架Quartz框架详细使用说明
Quartz框架详细使用说明 Quartz 是一个功能强大的开源作业调度框架,广泛用于在Java应用程序中执行定时任务。以下是Quartz框架的详细使用说明、完整代码示例、同类框架对比以及总结表格。 1. Quartz框架概述 特点: 灵活的调度:支持多种调度方…...
配置Spark历史服务器,轻松查看任务记录
在大数据处理中,Spark是一个强大的分布式计算框架。但当Spark服务重启后,之前的运行记录就会消失,给我们排查问题和分析任务执行情况带来不便。这时,配置Spark历史服务器就显得尤为重要,它能帮助我们保存和查看历史任务…...
身份证实名认证:通往数字安全与便捷生活的钥匙
在数字化日益深入我们生活的今天,信息安全和隐私保护成为了每个人关心的焦点。而身份证实名认证作为保障个人信息安全的重要环节,正扮演着越来越关键的角色。它不仅是连接现实世界与数字世界的桥梁,更是确保个人在线活动安全、可靠的基础。 什…...
0基础可以考MySQL OCP么?备考时间需要多久?
最近被问爆的 “0 基础能不能考 MySQL OCP”“备考要多久” 终于来答疑啦!作为过来人,负责任地说:0 基础完全能冲! 0 基础真的能考 MySQL OCP? 很多姐妹担心自己是数据库小白,连 SQL 都没摸过,…...
node.js 实战——(概念以及Buffer 知识点学习)
概念 node.js是一个开源的、跨平台的javascript运行环境;它可以开发服务器应用,可以开发工具类应用(webpack、vite、Babel),也可以开发桌面端应用(vscode、Figma、Postman) #mermaid-svg-0TkAt8LEFhyrVrsw {font-fami…...
论文阅读 | 大模型工具调用控制的策略优化
文章目录 I. 背景II. 方法细节2.1 问题定义2.2 工具集成RL2.3 PPO2.4 GRPO2.5 OTC-PO2.5.1 OTC-PPO2.5.2 OTC-GRPO2.5.3 工具集成奖励设计 III. 实验 题目: OTC: Optimal Tool Calls via Reinforcement Learning 论文地址: OTC: Optimal Tool Calls via…...
【论文阅读】Dual-branch Cross-Patch Attention Learning for Group Affect Recognition
【论文阅读】Dual-branch Cross-Patch Attention Learning for Group Affect Recognition 摘要1.介绍2.相关工作3.双分支交叉Patch注意力Transformer4.实验5.局限性 摘要 本篇博客参考IEEE 2022年收录的论文Dual-branch Cross-Patch Attention Learning for Group Affect Reco…...
centos stream 10 修改 metric
1. 查看当前网络连接 nmcli connection show 2. 查看当前网络连接的metric ip route show 3. 修改指定连接的 metric sudo nmcli connection modify "Wired connection 1" ipv4.route-metric 100 ipv6.route-metric 100 值越大,优先级越低ÿ…...
Java从入门到“放弃”(精通)之旅——String类⑩
Java从入门到“放弃”(精通)之旅🚀——String类⑩ 前言 在Java编程中,String类是最常用也是最重要的类之一。无论是日常开发还是面试,对String类的深入理解都是必不可少的。 1. String类的重要性 在C语言中…...
MVCWebAPI使用FromBody接受对象的方法
近期在做软件升级操作的时候突然想着需要的参数比较多,如果需要参数的话参数比较多,所有想着使用frombody来集合数据统一操作做了个样张希望对您有帮助 代码如下: /// <summary>/// 入口当前文件接口下的操作数据/// </summary>/…...
知识储备-DC综合相关
DC flow相关 要点描述命令区别DC基础版,使用wireloadmodelcompile_ultraDCT 含DC所有非冲突feature(如wlm),按照DC-prefloorplan-DCT流程获取布局信息更精确评估时序收敛 dc_shell -topoDCG含DCT所有feature,多了layer和congestion信息等 dc_…...
力扣-第645题《错误的集合》
一 . 问题描述 集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。 给定一个数组 nums 代表了集合 S 发生错误后的结果。 …...
gem5教程第六章 为ARM扩展gem5 这也是改进gem5的一个基础
本章假设您已经使用gem5构建了一个基本的x86系统,并创建了一个简单的配置脚本。 下载ARM二进制文件 让我们从下载一些ARM基准测试二进制文件开始。从gem5文件夹的根目录开始: mkdir -p cpu_tests/benchmarks/bin/arm cd cpu_tests/benchmarks/bin/arm wget dist.gem5.org/…...
事关数据安全,ARM被爆不可修复漏洞
日前,ARM架构再次被爆出重大安全漏洞,影响波及ARMv8.3架构及以前的所有CPU。该漏洞为硬件级且无法完全修复,如被利用可能造成严重数据泄露风险。 ARM硬件级安全漏洞 来自ARM开发者官网的一项安全更新证实,存在一种名为PACMAN的新型…...
Unity中使用Cinemachine插件创建自由视角相机(freelookCamera)来实现第三人称漫游
1.安装下载Cinemachine插件 2.创建自由相机freelookCamera Follow:为我们的人物 LookAt:相机始终看向的地方,可以新建空物体,放在人物头上, invert:是反向,就是时鼠标移动方向与相机旋转方向一致 在组件最下面的…...
Python爬虫(2)Python爬虫入门:从HTTP协议解析到豆瓣电影数据抓取实战
目录 一、背景与需求二、 Web基础与HTTP协议核心解析2.1 HTTP协议:数据交互的基石2.2 为何爬虫需理解HTTP协议? 三、 Python爬虫实战:Requests库核心用法3.1 安装与环境配置3.2 案例1:GET请求抓取豆瓣电影Top2503.3…...
php基础
文章目录 基本语法基本数据类型:运算符?? 空合并 定义变量字符串操作内置变量\$_SESSION:会话信息\$_GET:获取URL参数 内置函数功能工具类的,utils网络通信类的会话管理类的 基本语法 每一个statement后面以;结尾,与C/C和Java一样注释用//,…...
蓝桥杯17. 机器人塔
机器人塔 原题目链接 题目描述 X 星球的机器人拉拉队有两种服装:A 和 B。 这次他们表演的是“搭机器人塔”,类似下图: AB BA B AA A B BB B B A BA B A B B A组塔规则: A 只能站在 AA 或 BB 的肩上;B 只能站在 AB…...
rpm包管理
1.介绍 rpm用于互联网下包的打包及安装工具,包含在某些Linux发布版中,它生成具有.RPM扩展名的文件.RPM是RedHat Package Manage (RedHat软件包管理公具)的编写 类似windows的setup.exe,这一文件格式名称虽然打上RedHat的标志,但理念是通用的. Linux的…...
es 自动补全
安装拼音分词器 选择es版本对应的pinyin分词器版本 下载后解压,放到es的插件目录下 重启es 自定义分词器 拼音分词器——可选配置 1. 首字母处理配置 keep_first_letter (默认: true) 解释:是否提取每个汉字的首字母组合,用于支持首字母…...
NLTK 文本分类与情感分析
在自然语言处理(NLP)的领域中,文本分类和情感分析是两个非常重要且具有广泛应用的任务。文本分类旨在将文本数据分配到预定义的类别中,而情感分析则专注于确定文本所表达的情感倾向,如积极、消极或中性。Python 的 Nat…...
Android开发常用外部组件及使用指南(上)
文章目录 一、前言二、外部组件的引入方式1. Gradle依赖管理1.1 项目级build.gradle1.2 模块级build.gradle 2. 本地库引入3. 模块化引入 三、网络请求组件1. Retrofit1.1 引入依赖1.2 基本使用1.3 高级特性 2. OkHttp2.1 基本使用2.2 拦截器 四、图片加载组件1. Glide1.1 基本…...
系统架构师2025年论文《系统架构风格》
论企软件架构风格 摘要: 我所在单位是某市主要医院,2017 年 1 月医院决定开发全新一代某市医院预约挂号系统,我担任本次系统的架构师,主要负责整个系统的架构设计工作。该系统旨在优化医院挂号流程,提高患者就医体验,是医院应对医疗信息化变革和提升服务质量的重要举措…...
Linux部署Redis主从
Linux部署Redis主从 1.下载2.安装2.1编译 & 安装 3.修改配置文件4.启动 1.下载 在Redis版本库:https://download.redis.io/releases/ 可根据自己的需求选择下载对应的版本,然后直接下载 2.安装 通过Xftp工具进行上传,选择指定的应用拖…...
【Python 学习笔记】 pip指令使用
系列文章目录 pip指令使用 文章目录 系列文章目录前言安装配置使用pip 管理Python包修改pip下载源 前言 提示:这里可以添加本文要记录的大概内容: 当前文章记录的是我在学习过程的一些笔记和思考,可能存在有误解的地方,仅供大家…...
Django DRF实现用户数据权限控制
在 Django DRF 中使用 ModelViewSet 时,若需实现用户仅能查看和操作自己的数据详情,同时允许所有认证用户访问列表,需结合权限类和动态权限分配。以下是具体步骤: 1. 自定义对象权限类 创建一个 IsOwner 权限类,检查…...
eplan许可证与防火墙安全软件冲突
在使用EPLAN电气设计软件时,有时会遇到许可证与防火墙或安全软件之间的冲突。这种冲突可能导致许可证无法激活或软件无法正常运行,给用户带来诸多不便。本文将为您解析EPLAN许可证与防火墙/安全软件冲突的原因,并提供解决方案,帮助…...
《多Agent架构VS千万字长文本VS深度推理引擎——拆解Coze、通义、Kimi的AI终局博弈密码》
Coze、通义和Kimi终局竞争深度分析 技术路线分野:多Agent协同 vs. 超长文本 vs. 结构化提示 架构差异:三者在技术路线上的侧重点各异,塑造了不同的市场边界。Coze(“扣子”)采用多Agent协同架构,强调插件工…...
《浔川代码编辑器v2.1.0预告》
《浔川代码编辑器v2.1.0预告》 尊敬的浔川代码编辑器用户: 我们很高兴向大家预告即将到来的v2.1.0版本更新计划。以下是各版本的发布时间安排: 版本发布计划 1. **v2.1.0公测版** - 发布时间:待v2.0测试版结束后两周 - 特点:包…...