背景

随着微服务的普及,分布式事务成为了系统设计中不得不面对的一个问题,而分布式事务的实现则十分复杂。阅读本文之前,需要你对数据库事务的ACID、CAP理论、Base理论以及两阶段提交有一定的认知,不熟悉者请自行百度或者阅读参考博客1、2、3和4。除此之外,在阅读本文过程中,如果对某种方案不理解,强烈建议先阅读对应方案中的参考博客后再阅读本文中对应的介绍。

为了便于后文叙述,这里对ACID中的C(一致性)做一个强调:严格的事务一致性是使数据库从一个一致性状态变到另一个一致性状态,且事务中间状态不能被观察到。

分布式事务的七种实现方案:

1、基于可靠消息服务(基于可靠消息中间件);

2、最大努力尝试(基于消息中间件);

3、TX-LCN(对LCN的实现);

4、X/Open DTP模型(XA规范,基于两阶段提交);

5、阿里DTS(基于TCC);

6、华为ServiceComb(对SAGA模式的实现);

7、阿里GTS(开源产品为Fescar,对XA协议改进后的实现)。

1、基于可靠消息服务

我们常见的消息中间件比如LinkedLin公司的Kafka、Rabbit科技有限公司的RabbitMQ以及Apache提供的ActiveMQ等等,都不支持事务。而阿里提供的RocketMQ则在解决了消息的顺序性和重复消息幂等性的基础上,实现了对事务的支持(详见参考博客5)。因而基于RocketMQ,就可以实现分布式事务(详见参考博客6)。实际上,参考博客6中给出了两套基于消息服务的实现方案:第一,基于本地消息服务的方案,针对的是消息中间件本身不支持事务的场景,需要从应用设计的角度实现消息数据的可靠性;第二,基于独立消息服务的方案,针对的是消息中间件本身支持事务的场景。为了便于后面对比分析,这里贴出了基于独立消息服务的设计方案:

基于可靠消息服务的分布式事务方案的核心原理是对发送到消息中间件的消息进行“两阶段提交”,即先提交,执行完本地事务后再确认消息。通过这样的机制,给事务的回滚提供了可能。

如下图所示。如果用ACID来衡量该方案,基于可靠消息服务的分布式事务方案能保证事务的最终原子性和持久性,但无法保证一致性和隔离性。这里在原子性前面加“最终”二字,是因为基于消息的操作本质上属于异步操作,显然是非实时的。持久性自然不必多说。那么为什么说该方案无法保证一致性和隔离性呢?由下图可知,本地事务执行提交成功之后,才会对消息进行确认,而这个时候,远程事务还未提交,一致性显然无法满足。

我们知道,数据库的隔离性是通过锁机制来保证的,因而基于可靠消息服务的分布式事务方案要想满足隔离性,往往还需要在事务发起方采用分布式锁机制。因而总的来说,基于可靠消息服务的分布式方案适用于对业务的实时一致性以及事务的隔离性要求都不高的内部系统。

2、最大努力尝试

最大努力尝试方案和基于可靠消息服务一样,都依赖于消息中间件(参考博客7)。不同的是,消息中间件不需要保证可靠性,分布式事务的实现是依靠额外的校对系统或者报警系统(报警后人工处理)来保障的。因而和基于可靠消息服务一样,最大努力尝试的分布式方案只能保证事务的最终原子性和持久性,无法保证一致性和隔离性。在应用场景方面,正如参考博客7中所说,最大努力尝试方案常常用于对业务的实时一致性以及事务的隔离性要求都不高的内部系统或者跨企业的业务活动中。下图为最大努力尝试的方案:

同基于可靠消息服务的方案一样,最大努力尝试方案能保证事务的最终原子性和持久性,但无法保证一致性和隔离性。尽管最大努力尝试方案只能保证最终原子性和持久性,但因其实现十分简单,常常成为企业很多非核心业务的首选方案。

3、TX-LCN

由LCN的官网(参考博客8)可知,LCN是lock、confirm和notify三个单词的缩写。个人人为,LCN方案是本文中七个方案中除了刚刚已经介绍的两个基于消息中间件的方案之外,最容易理解的方案,因而将其排在第三位来介绍。正如其官网文档(详见参考博客8)所说,LCN并不产生事务,LCN只是本地事务的协调工。这就意味着,使用LCN的系统完全依赖于本地事务。遗憾的是,LCN的官网对其核心原理介绍得比较简略,看完不得其要领,反而是在另外的博客(参考博客9和10)中相对详细地介绍了其实现原理。

LCN中包含一个TxManager和一个TxClient。其中TxManager负责维护全局的事务信息,而TxClient位于业务模块和本地事务层之间,其作用是代理本地事务层,通过代理连接词实现了javax.sql.DataSource接口,并重写了close方法,事务模块在提交关闭以后TxClient连接池将执行"假关闭"操作,等待TxManager协调完成事务以后在关闭连接,如下图所示。

LCN的核心步骤

1. 创建事务组

是指在事务发起方开始执行业务代码之前先调用TxManager创建事务组对象,然后拿到事务标示GroupId的过程。

2. 添加事务组

添加事务组是指参与方在执行完业务方法以后,将该模块的事务信息添加通知给TxManager的操作。

3. 关闭事务组

是指在发起方执行完业务代码以后,将发起方执行结果状态通知给TxManager的动作。当执行完关闭事务组的方法以后,TxManager将根据事务组信息来通知相应的参与模块提交或回滚事务。

以数据库为例,前面提到的“假关闭”就是指步骤2中执行完业务方法后调用的close()方法是覆写后的方法,该方法并不会真正提交事务,而是一直持有数据库连接,并持有事务所需的相关资源锁,直到第3步,由TxManager异步通知事务提交或回滚才释放锁。

以参考博客10中的时序图为例(见下图),参与方A和参与方B在执行完业务操作后,事务实际上并未提交,而是将提交前本地事务的操作结果返回给事务发起方,由事务发起方通知TxManager,并由后者根据通知的结果来异步通知各参与方最终提交或回滚事务。当然TxManager对参与方的通知可能会失败,因而需要补偿机制。

由此可知,LCN中的三个单词对应了LCN分布式事务操作中的三个关键步骤:1、分布式事务操作前先锁定(lock)所有资源直到异步通知(notify)释放资源;2、执行业务操作,根据操作结果确认(confirm)事务应该提交还是回滚;3、根据第2步中的操作结果异步通知(notify)事务的提交或回滚并最终释放资源。

至此,我们了解到,LCN的核心原理是通过协调本地事务来实现分布式事务,分布式事务的实现依赖于本地事务。因而基于LCN的分布式事务的ACID特性取决于本地事务的ACID特性。一般来说,如果本地事务都能保证ACID,那么基于LCN的分布式事务也能满足AID。而对于一致性(Consistency),这是分布式事务的一个通病。

由Base理论可知,对于分布式系统,我们更关注的是最终一致性和最终一致性的实时性。相对于前面介绍的基于消息中间件的两种方案来说,基于LCN的分布式事务方案最终一致性的实时性远高于前两者。当然,其代价是并发性能的极大降低。实际上,对于分布式系统而言,能做到准实时的最终一致性就已经能满足绝大多数应用场景。对于像银行业务等对一致性有极致要求的极端场景,还可以通过在业务系统中使用分布式锁或者分布式队列来保证。

小结:LCN方案相对于后面将要介绍的其他方案来说,其优点是实现相对简单,但其缺点也是显然的:第一,依赖本地事务,如果要操作的资源不支持本地事务,则LCN模式无法直接使用。当然,对于这个限制,新版的TX-LCN通过支持后面将会介绍的TCC模式和TXC模式来解决。第二,LCN事务提交的整个过程都需要锁住资源,因而性能低于TCC和TXC(TCC和TXC就是为了缩短分布式事务操作过程中资源的锁定时间)。

4、基于XA规范的X/Open DTP模型

X/Open,即现在的open group,是一个独立的组织,主要负责制定各种行业技术标准。X/OpenDTP即为该组织制定的一套分布式事务的方案。关于该模型详细的介绍请阅读参考博客11,这里只介绍其最核心的原理。

DTP模型元素

应用程序(Application Program ,简称AP):用于定义事务边界(即定义事务的开始和结束),并且在事务边界内对资源进行操作。

资源管理器(Resource Manager,简称RM):如数据库、文件系统等,并提供访问资源的方式。

事务管理器(Transaction Manager ,简称TM):负责分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚等。

通信资源管理器(Communication Resource Manager,简称CRM):控制一个TM域(TMdomain)内或者跨TM域的分布式应用之间的通信。

通信协议(Communication Protocol,简称CP):提供CRM提供的分布式应用节点之间的底层通信服务。

这里我们重点看看AP、TM和RM之间的关系:

由上图可知,XA规范的最主要作用是,定义了RM-TM的交互接口。实际上,XA规范除了定义的RM-TM交互的接口之外,还对两阶段提交协议进行了优化。具体的优化包括只读断言和一阶段提交。具体请阅读参考博客11。

接下来我们来看XA规范的具体工作原理。参考博客14中给出了XA规范提交流程示意图:

提交步骤为:

在开始一个全局事务之前,涉及的RM必须通过ax_regr(),向TM注册以加入集群;对应的,在没有事务需要处理的时候,RM可以通过ax_unreg()向TM要求注销,离开集群。

TM在对一个RM执行xa_开头的具体操作前,必须先通过xa_open()打开这个RM(本质是建立对话)——这其实也是分配XID的一个行为;与之相应的,TM执行xa_close()来关闭RM。

TM对RM调用的xa_start()和xa_stop()这对组合,一般用于标记局部事务的开头和结尾。这里需要注意的有三点:

对于同一个RM,根据全局事务的要求,可以前后执行多对组合——俾如说,先标记一个流水账INSERT的局部事务操作,然后再标记账户UPDATE的局部事务操作。

TM执行该组合只是起到标记事务的作用,具体的业务命令是由AP交给RM的。

该组合除了执行这些标记工作外,其实还能在RM中实现多线程的join/suspend/resume管理。

TM调用RM的xa_prepare()来进行第一阶段,调用xa_commit()或xa_rollback()执行第二阶段。

这里需要强调的是,XA规范中,整个两阶段提交过程资源都是处于锁定状态(见下图)。在下图中,无论Phase2的决议是commit还是rollback,事务性资源的锁都要保持到Phase2完成才释放。由此可知,基于XA规范的X/OpenDTP和LCN都存在资源长期锁定的问题。

 

小结:X/Open DTP的核心原理是基于两阶段提交(XA规范),通过在整个提交过程中对资源进行锁定来实现分布式事务,能很好地满足AID特性,以及准实时的最终一致性。此外,该方案同LCN类似,性能低于TCC和TXC。因而在实际应用中,较少有系统会选择该方案。

5、基于TCC的支付宝DTS

关于TCC原理,强烈建议先阅读参考博客12和13。这里给出参考博客13中的示意图:

TCC 分布式事务模型包括三部分:

主业务服务:主业务服务为整个业务活动的发起方,服务的编排者,负责发起并完成整个业务活动。

从业务服务:从业务服务是整个业务活动的参与方,负责提供 TCC 业务操作,实现初步操作(Try)、确认操作(Confirm)、取消操作(Cancel)三个接口,供主业务服务调用。

业务活动管理器:业务活动管理器管理控制整个业务活动,包括记录维护 TCC 全局事务的事务状态和每个从业务服务的子事务状态,并在业务活动提交时调用所有从业务服务的Confirm 操作,在业务活动取消时调用所有从业务服务的 Cancel 操作。

一个完整的 TCC 分布式事务流程如下:

1. 主业务服务首先开启本地事务;

2. 主业务服务向业务活动管理器申请启动分布式事务主业务活动;

3. 然后针对要调用的从业务服务,主业务活动先向业务活动管理器注册从业务活动,然后调用从业务服务的 Try 接口;

4. 当所有从业务服务的 Try 接口调用成功,主业务服务提交本地事务;若调用失败,主业务服务回滚本地事务;

5. 若主业务服务提交本地事务,则 TCC 模型分别调用所有从业务服务的 Confirm 接口;若主业务服务回滚本地事务,则分别调用Cancel 接口;

6. 所有从业务服务的 Confirm 或 Cancel 操作完成后,全局事务结束。

小结:以ACID来衡量TCC可知,TCC能满足AID特性,以及准实时的最终一致性。TCC的核心原理是,在分布式事务操作中,先将所需资源预占,然后将锁释放,最后再根据资源预占的情况来决定使用资源还是退回资源。相比于XA规范,TCC方案采用预留资源的方式,将两阶段提交过程中的全局锁分成了两段本地事务锁,缩短了分布式资源锁定的时间,从而提高了事务的并发度。相对于后面即将介绍的SAGA而言,因为TCC采用预占资源的方式,其补偿动作实现比较简单。当然,TCC的缺点是业务入侵性大,尤其是已有业务如果想使用TCC方案,就需要修改原来的业务逻辑(后面介绍SAGA时还会再强调这一点)。

6、基于SAGA的华为ServiceComb

saga是1987年的一篇数据库论文里提到的一个概念(参考博客16~19,重点是16),而ServiceComb是华为一个项目组对saga模式的实现方案。论文中指出,一个Saga事务就是一个Long Live Transaction(LLT),而一个LLT可以分解为多个本地事务所组成,即LLT= T1+ T2 + ... + Tn。每个本地事务执行完提交之后就会立即生效,比如执行完T1和T2之后,在执行T3时,T1和T2的事务就已经提交了。

假如执行T3失败,由于T1和T2已经提交,无法回滚了。为了解决这个问题,saga要求业务服务方对每个本地事务Tx都提供对应的反向补偿操作Cx(反向补偿是指Tx的逆向操作),反向补偿操作也是执行完就立即生效。在执行一个LLT的过程中,如果任意一个Tx出错了,则通过调用所有已执行的Tx对应的Cx来进行反向补偿。比如执行完T1和T2之后,执行T3时出错,则需要执行C3、C2和C1来进行补偿。

论文中对被saga调用的服务提出了两点要求:其一是被调用的服务要支持幂等。由于分布式服务一定存在网络超时,所以这一点对于分布式服务来说,一般都能满足。其二是服务要满足可交换补偿。如图所示:

 

这里有必要对可交换补偿做一下说明。其实服务支持幂等和服务满足可交换补偿这两点要求是为了处理执行补偿操作时必然会遇到的两个细分场景。我们首先来说说执行补偿操作时会遇到的哪两个场景:第一,事务操作Tx根本未被执行(比如因网络丢包导致事务操作Tx在图中被丢弃,未到达服务端,或者在服务端执行失败)。

对于这种场景,Cx无须也不能执行,否则反而会出错,也就是说,saga执行Cx操作的前提是服务方确实执行了Tx操作(成功或失败均可);第二,如上图中的右图所示,事务操作T发出后事务操作在网络中出现了较大的延时,触发了saga的超时机制,因而执行了正向重试,发现重试失败,接着执行反向补偿操作C,当C已经执行完之后,最开始的事务操作T才到达服务方。

这个时候,saga要求最开始的事务操作T不能生效,因为C已经生效了。也就是说,saga要求服务一旦接受并执行了反向补偿操作C,则不会再处理与之对应的正向操作。这么做的目的是为了防止先到达的反向补偿操作被后到达的正向事务操作给覆盖掉。

其实场景二的实现依赖场景一中提供的保障,因为示例中正向的重试操作也有可能无法到达服务端,这就变成了场景一了。其实这个问题在后面介绍的TCC方案中也会遇到,并需要被解决(有兴趣可提前看参考博客20)。

除此之外,参考博客16中还说明了saga模式本身只支持ACID中的ACD,而无法支持隔离性(而如果用本文的评判标准来看,saga也无法只能满足准实时的一致性,而无法满足强一致性)。为了支持隔离性,需要考虑在业务层加入锁机制或者类似TCC的方式,采用在业务层预先冻结资源的方式对资源进行隔离。

关于saga模式的隔离性我还想补充说明的是,因为saga模式的本地事务是执行完就立即提交,而不能回滚,那么在没有隔离性保障的情况下,反向补偿操作很可能无法执行成功。比如说有A和B和C三个账户,账户余额都为100元,执行如下两个并发事务:

小结:saga模式的核心原理是,将一个全局事务分成若干个能独立提交的本地事务,每个本地事务都对应一个反向补偿操作,当本地事务提交失败后,通过反向补偿操作来取消本地事务的影响。

相比于TCC,Saga缺少预留动作,导致某些业务的补偿动作的实现比较麻烦,比如业务是发送邮件,在TCC模式下,先保存草稿(Try)再发送(Confirm),撤销的话直接删除草稿(Cancel)就行了。而Saga则就直接发送邮件了(Ti),如果要撤销则得再发送一份邮件说明撤销(Ci)。当然,对于另外一些简单业务来说,Saga没有预留动作也可以认为是优点(详见参考博客18):

有些业务很简单,套用TCC需要修改原来的业务逻辑,而Saga只需要添加一个补偿动作就行了。

TCC最少通信次数为2n,而Saga为n(n=sub-transaction的数量)。

有些第三方服务没有Try接口,TCC模式实现起来就比较tricky了,而Saga则很简单。

没有预留动作就意味着不必担心资源释放的问题,异常处理起来也更简单(请对比Saga的恢复策略和TCC的异常处理)。

7、基于改进XA协议的阿里GTS

GTS,最初名为TXC,是Taobao Transaction Constructor的缩写,于2014年4月立项,2014年10月发布了TXC1.0版本,2015年12月发布TXC 2.0版本,2017年2月阿里云公测,外部更名为GTS(GlobalTransaction Service)。2019年1月,阿里分布式事务框架GTS开源了一个免费社区版Fescar。

前面在介绍XA规范的时候提到,两阶段提交过程资源都是处于锁定状态,为了便于对比,我再次贴出XA规范的提交示意图(参考博客21):

由图可知,无论Phase2的决议是commit还是rollback,事务性资源的锁都要保持到Phase2完成才释放。设想一个正常运行的业务,大概率是90%以上的事务最终应该是成功提交的,我们是否可以在Phase1 就将本地事务提交呢?这样 90% 以上的情况下,可以省去 Phase2 持锁的时间,整体提高效率。

 

分支事务中数据的 本地锁 由本地事务管理,在分支事务 Phase1 结束时释放。

同时,随着本地事务结束,连接 也得以释放。

分支事务中数据的 全局锁(详见参考博客25) 在事务协调器侧管理,在决议 Phase2 全局提交时,全局锁马上可以释放。只有在决议全局回滚的情况下,全局锁 才被持有至分支的 Phase2 结束。

这个设计,极大地减少了分支事务对资源(数据和连接)的锁定时间,给整体并发和吞吐的提升提供了基础。

当然,你肯定会问:Phase1 即提交的情况下,Phase2 如何回滚呢?首先,应用需要使用 Fescar的 JDBC 数据源代理,也就是 Fescar 的 RM。

Phase1:

Fescar 的 JDBC 数据源代理通过对业务 SQL 的解析,把业务数据在更新前后的数据镜像组织成回滚日志,利用本地事务的ACID 特性,将业务数据的更新和回滚日志的写入在同一个本地事务中提交。

这样,可以保证:任何提交的业务数据的更新一定有相应的回滚日志存在。

基于这样的机制,分支的本地事务便可以在全局事务的 Phase1 提交,马上释放本地事务锁定的资源。

Phase2:

如果决议是全局提交,此时分支事务此时已经完成提交,不需要同步协调处理(只需要异步清理回滚日志),Phase2 可以非常快速地完成。

如果决议是全局回滚,RM 收到协调器发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新SQL 并执行,以完成分支的回滚。

 

由此可知,Fescar的核心原理是,对业务SQL进行解析,把业务数据在更新前后的数据镜像组织成回滚日志,利用本地事务的ACID特性,将业务数据的更新和回滚日志的写入在同一个本地事务中提交。除此之外,为了保证分布式事务的隔离性,在事务协调器侧还增加了一把全局锁,以保证回滚日志得以顺利执行(可以回过头再看看Saga方案中列举的回滚失败的示例)。

小结:以ACID来衡量Fescar可知,该方案能保证AID特性,以及准实时的最终一致性。实际上,对于分布式系统,如果分布式方案能同时保证AID特性以和准实时的最终一致性,就等价于能保证增删改操作的ACID特性,而至于查询操作,可能会读取到事务中间状态的数据,这在绝大多数业务场景中都是能接受的。而且前面也讲了,对于像银行业务等对一致性有极致要求的极端场景,也可以通过在业务系统中使用分布式锁或者分布式队列来保证。

此外,对比TCC和Fescar可知,TCC无论事务最终是提交还是回滚,本质上都需要对同一个资源执行两次操作,一次是try,另一次是confirm或者cancel;而对于Fescar来说,大多数情况下,分布式事务都不需要回滚,而对于不需要回滚的分布式事务,每个资源只需要执行一次操作。从这个角度来说,Fescar的平均性能将比TCC更高。

总结

基于可靠消息中间件的分布式方案的核心原理是对发送到消息中间件的消息进行“两阶段提交”,即先提交,执行完本地事务后再确认消息。通过这样的机制,给事务的回滚提供了可能。该方案能保证事务的最终原子性和持久性,但无法保证一致性和隔离性。基于可靠消息服务的分布式方案适用于对业务的实时一致性以及事务的隔离性要求都不高的系统。

最大努力尝试方案的核心原理是依靠额外的校对系统或者报警系统来保证分布式事务。该方案能保证事务的最终原子性和持久性,但无法保证一致性和隔离性。基于可靠消息服务的分布式方案适用于对业务的实时一致性以及事务的隔离性要求都不高的系统。

TX-LCN方案的核心原理是通过协调本地事务来实现分布式事务,分布式事务的实现依赖于本地事务。一般来说,如果本地事务都能保证ACID,那么基于LCN的分布式事务也能满足AID,而不能满足一致性。TX-LCN实现相对简单,但事务对资源的锁定时间长,因而适用于对并发性能要求不高的场景。

X/Open DTP的核心原理是基于两阶段提交(XA规范),通过在整个提交过程中对资源进行锁定来实现分布式事务,能很好地满足AID特性,以及准实时的最终一致性。由于该方案对资源的锁定时间长,因而适用于对并发性能要求不高的场景。

TCC的核心原理是,在分布式事务操作中,先将所需资源预占,然后将锁释放,最后再根据资源预占的情况来决定使用资源还是退回资源。相比于XA规范,TCC方案采用预留资源的方式,将两阶段提交过程中的全局锁分成了两段本地事务锁,缩短了分布式资源锁定的时间,从而提高了事务的并发度。

saga模式的核心原理是,将一个全局事务分成若干个能独立提交的本地事务,每个本地事务都对应一个反向补偿操作,当本地事务提交失败后,通过反向补偿操作来取消本地事务的影响。相比于TCC,Saga缺少预留动作,导致某些业务的补偿动作的实现比较麻烦,比如业务是发送邮件,但对于另外一些简单业务来说,Saga没有预留动作的特性降低了老系统接入Saga方案的成本。

Fescar的核心原理是,对业务SQL进行解析,把业务数据在更新前后的数据镜像组织成回滚日志,利用本地事务的ACID特性,将业务数据的更新和回滚日志的写入在同一个本地事务中提交。此外,为了保证分布式事务的隔离性,在事务协调器侧还增加了一把全局锁,以保证回滚日志得以顺利执行。

如果觉得本文对你有帮助,可以点赞关注支持一下,也可以关注我公众号,上面有更多技术干货文章以及相关资料共享,大家一起学习进步!

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 用户运营看这里就够了

    用户运营的核心运营指标包括了引流、活跃、留存和转化四个部分,而在具体的用户运营操作上,有广义的用户运营和微观的用户运营两个层面。 广义层面上,用户运营就是主要围绕上述四个操作指标进行的,就是说用户各个维度都是最重要的&…...

    2024/4/15 18:08:53
  2. 吹爆!阿里新产Spring源码高级笔记,原来看懂源码如此简单

    Spring的影响力想必无需与大家多说,如果你用spring,那么读读源码有助于对你最重要的工具的理解,好的框架源码也可以帮助我们理解什么是好代码。 刚参加工作那会,没想过去读源码,更没想过去改框架的源码;甚…...

    2024/5/8 17:28:12
  3. 每日一个知识点:Volatile 和 CAS 的弊端之总线风暴

    每日一个知识点系列的目的是针对某一个知识点进行概括性总结,可在一分钟内完成知识点的阅读理解,此处不涉及详细的原理性解读。 一、什么是总线风暴 总线风暴,听着真是一个帅气的词语,但如果发生在你的系统上那就不是很美丽了&am…...

    2024/5/8 12:51:56
  4. NodeJs实战第三章之简单实现增删改查接口

    具体demo如下: const express require(express); const bodyParser require("body-parser") const app express(); const articles [{title:这是一篇文章}] const port process.env.PORT || 3000;app.use(bodyParser.json()); //支持编码为JSON的…...

    2024/4/21 8:52:36
  5. 抛砖引玉系列之gradle文件配置差异化打包

    在项目开发的过程中,总能碰到这样的需求,打包的时候发布两个相同版本的包,但是服务器地址不同,这时候就不想打两个包的时候只想运行一句打包命令打出两个服务器地址的包,这个时候就想到可以根据gradle配置打出差异化版…...

    2024/4/21 20:33:28
  6. RTSP网络摄像头网页无插件直播视频平台EasyNVR自定义标题和CopyRight步骤

    由于EasyNVR视频平台能够直接集成到其他的平台定制专属于自己企业的视频监控方案,所以很多项目团队都会选择变更EasyNVR的标题以及CopyRight,换成项目相关的内容,这个需求EasyNVR也是可以实现的,下面就来讲一下实现方法。 之前的方…...

    2024/5/4 21:57:17
  7. 解读华为云原生数据库设计原则,打破传统数据库上云瓶颈

    摘要:一个优秀的自研数据库产品应该要具备哪些特性呢?在云计算技术不断成熟的背景之下,云数据库开始崛起,并因为按需扩展、按需付费等优异特性获得中小企业及互联网客户的青睐。 虽然数据库上云是必然,但并不是万能的…...

    2024/4/28 23:57:44
  8. 搭档之家|独立面对人生的态度

    搭档之家:才知道一个人是常态 搭档之家也见过很多年轻人,在学校里,在家庭里,不知何为一个人。 一个人住宿是常态,一个人看病是常态,一个人吃饭是常态,一个人解决问题是常态,一个人是…...

    2024/4/15 9:11:30
  9. 下订单溢出模拟并发

    我用sql server 做了 一个模拟 一张订单表 一张产品表 逻辑是准备一个存储过程 产品数量>0就可以 往 订单表insert 一条记录 产品数量-- ; 这个 存储过程 没添加 事务 没指定 会话隔离级别 也没有 加锁 ALTER PROCEDURE [dbo].[pro_createorder_auto] errormsg n…...

    2024/4/27 14:41:20
  10. 记录java的多次线程

    线程的优先级 每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。 Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。 默认情况下…...

    2024/4/25 23:26:49
  11. 微信公众号链接自定义分享总结

    微信H5自定义分享页面总结 微信公众号中默认的分页页面很难看,默认的缩略图。工作需要将他自定义为想要的形式。 具体详情查看微信开发者文档:微信开发者文档 第一步、公众号需要配置 1、需要一个公众号的 appId、appSecret 只要有公众号,…...

    2024/4/24 18:46:50
  12. 面对疾风吧!io_uring 优化 nginx 实战演练

    作者:玖一(云巅论剑) 引言 io_uring是Linux内核在v5.1引入的一套异步IO接口,随着其迅速发展,现在的io_uring已经远远超过了纯IO的范畴。从Linux v5.3版本开始,io_uring陆续添加了网络编程相关的API&#…...

    2024/4/17 22:38:56
  13. Linux下处理时间同步相关问题汇总

    问题1 :时间同步时提示28 Sep 11:43:42 ntpdate[19730]: the NTP socket is in use, exiting 同步失败 您收到此错误消息的原因是由于 xntpd 已经绑定到了该 Socket。运行 ntpdate 时,它会首先进行广播,然后侦听端口 123。如果 xntpd 正在运…...

    2024/4/23 17:59:46
  14. 并查集——(三)C++ 使用 STL 的 map 实现查并集功能

    综述 我们接上一节,https://blog.csdn.net/justidle/article/details/108846236,继续讨论并查集问题。我们发现使用 C 数组实现并查集主要问题有以下几个: 1、元素中不能支持负数。因为 C 规定数组的下标不能是负数。 2、代码量相对比较大…...

    2024/5/6 1:07:53
  15. springboot+rabbitmq整合五种模式,所遇到的问题,搞了半天,结果就是因为声明的Binding中有个routingKey设置了null,最后我的绑定硬是没有绑定到rabbitmq中;

    由于笔者粗心大意在做Topic模式时,发现自己建立的Binding一直没有映射到RabbitMq中,明明都写了好了Queue、Exchange、Binding,结果在rabbitmq的管理界面没有绑定关系,抓狂,以下是自己的分析。 不废话直接上错误代码 /…...

    2024/4/26 5:01:15
  16. xcx-地图位置偏移解决

    //引入转换地图经纬度js var WSCoordinate require(./../../WSCoordinate.js); var QQMapWX require(../../qqmap-wx-jssdk.js),qqmap new QQMapWX({ key: O77BZ-2KXKO-7RIWS-SHI7I-LLSK7-OEBKZ });1.获取自动定位时:将获取的腾讯地图经纬度转换成百度地图经纬度…...

    2024/4/22 19:54:06
  17. 小白Python笔记(五)带你了解——算数运算符

    小白Python笔记(五)带你了解——算数运算符 计算机,顾名思义就是负责进行 数学计算 并且 存储计算结果 的电子设备 目标 算术运算符的基本使用 01. 算数运算符 算数运算符是 运算符的一种是完成基本的算术运算使用的符号,用来…...

    2024/4/22 14:47:04
  18. leetcode 刷题 1480题 一维数组的动态和

    leetcode 1480题 一维数组的动态和 给你一个数组 nums 。数组「动态和」的计算公式为:runningSum[i] sum(nums[0]…nums[i]) 。 请返回 nums 的动态和。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems…...

    2024/4/29 3:18:57
  19. 织梦友情链接标签

    {dede:flink titlelen60 row30 typetext} [field:link /] {/dede:flink} 直接用就可以...

    2024/4/17 5:57:44
  20. Java面试经历记录

    1zookeeper作为注册中心是双向绑定的吗? 当时没明白双向绑定什么意思,就介绍了下自己使用zookeeper作为注册中心的使用方式,包括注册和调用服务。面试官说这不就是双向绑定吗,先订阅,再通知调用。 2StringBuilder和S…...

    2024/4/30 19:10:01

最新文章

  1. 记一次DNS故障导致用户无法充值的问题(上)

    背景: 刚刚过去了五一劳动节,回来后一上班接到客服运营团队反馈的节日期间的问题,反馈有部分用户无法充值。拿到的反馈资料有: 无法充值操作视频、问题时间、手机机型、手机网络情况。 1、从视频中看到用户点击支付后没有任何反…...

    2024/5/8 23:58:13
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/7 10:36:02
  3. Linux mount用法

    在Linux系统中,系统自动挂载了以下挂载点: /: xfs文件系统,根文件系统, 所有其他文件系统的挂载点。 /sys: sysfs文件系统,提供内核对象的信息和接口。 /proc: proc文件系统,提供进程和系统信息。 /dev: devtmpfs文件系…...

    2024/5/5 8:38:45
  4. 鹅厂实习offer

    #转眼已经银四了,你收到offer了吗# 本来都打算四月再投实习了,突然三月初被wxg捞了(一年前找日常实习投的简历就更新了下),直接冲了,流程持续二十多天,结果是运气还不错,应该是部门比…...

    2024/5/1 13:19:09
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义:dp[i][j]表示当背包容量为j,用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/8 19:32:33
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/7 22:31:36
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon,直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件,我们讨论Spring负载均衡以Spring Cloud2020之后版本为主,学习Spring Cloud LoadBalance,暂不讨论Ribbon…...

    2024/5/8 1:37:40
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中,周界防范意义重大,对园区的安全起到重要的作用。常规的安防方式是采用人员巡查,人力投入成本大而且效率低。周界一旦被破坏或入侵,会影响园区人员和资产安全,…...

    2024/5/8 20:33:13
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时,常要分析网页Html,例如网页在加载数据时,常会显示“系统处理中,请稍候..”,我们需要在数据加载完成后才能继续下一步操作,如何抓取这个信息的网页html元素变化&…...

    2024/5/8 1:37:39
  10. 【Objective-C】Objective-C汇总

    方法定义 参考:https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/7 16:57:02
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    👨‍💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...

    2024/5/7 14:58:59
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/8 20:58:56
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕,各大品牌纷纷晒出优异的成绩单,摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称,在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁,多个平台数据都表现出极度异常…...

    2024/5/7 21:15:55
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令,这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/8 1:37:35
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b,我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边, b b b 同理,则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/7 16:05:05
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息,并安装一些有助于配置官方 NGINX 软件包仓库的软件包: apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/8 18:06:50
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限(ROW FORMAT)配置标准HQL为: ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/8 1:37:32
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中,传感器和控制器产生大量周…...

    2024/5/7 16:05:05
  19. --max-old-space-size=8192报错

    vue项目运行时,如果经常运行慢,崩溃停止服务,报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中,通过JavaScript使用内存时只能使用部分内存(64位系统&…...

    2024/5/8 1:37:31
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞,例如可以被劫持的合法软件(例如浏览器或 Web 应用程序插件)中的错误。 恶意软件渗透可能会造成灾难性的后果,包括数据被盗、勒索或网…...

    2024/5/8 1:37:31
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧! 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象…...

    2024/5/8 12:44:41
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错,但存在一个缺陷:无法禁止通过实例化多个对象来创建多名总统: President One, Two, Three; 由于复制构造函数是私有的,其中每个对象都是不可复制的,但您的目…...

    2024/5/8 9:51:44
  23. python django 小程序图书借阅源码

    开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 用户端: 登录注册(含授权登录) 首页显示搜索图书,轮播图&#xff0…...

    2024/5/8 1:37:29
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/7 17:09:45
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57