常用的分布式事务都有哪些-我该用哪个 (常用的分布式数据库)

教程大全 2025-07-16 01:21:59 浏览

常用的分布式事务都有哪些?我该用哪个?

2021-10-11 19:30:02分布式的CAP理论应该是人尽皆知了,它描述了一致性(C)、可用性(A)、分区容错性(P)的一系列权衡。很多时候,我们要在一致性和可用性之间权衡,而分布式事务,就是在这个大的前提下,尽可能的达成一致性的要求。

分布式的CAP理论应该是人尽皆知了,它描述了一致性(C)、可用性(A)、分区容错性(P)的一系列权衡。很多时候,我们要在一致性和可用性之间权衡,而分布式事务,就是在这个大的前提下,尽可能的达成一致性的要求。

目标很小,问题很大,做法也各有不同。

“如何在微服务中实现分布式事务?”一般在被问到这样的问题时,我都会回答“要尽量避免使用分布式事务”,这也是Martin Fowler所推荐的。但现实总是残酷的,拆分了微服务之后,分布式事务是非常硬核的需求,是绕不开的,我们依然要想办法搞定它。但分布式环境错综复杂,还伴随着网络状况产生的超时,如何让事务达到一致性的状态,难度很大。

分布式事务,由一系列小的子事务组成。这些子事务,同大的分布式事务一样,同样要遵循ACID的原则。在一致性这个属性上,根据达到一致性之前所存在的时间,又分为强一致性和最终一致性(BASE)。

注意,对于子事务,这里有个小小的误解。并不是只有和数据库打交道的操作,才叫做事务。在微服务环境下,如果你通过RPC调用了另外一个远程接口,并造成了相关数据状态的变化,这个RPC接口,也叫做事务。

所以,在分布式事务中,我们把这些子事务涉及到的操作,叫做资源。当操作能正常完成的时候,根本不需要什么额外处理。事务主要处理的是发生异常之后的流程。

下面,我们就来看一下常见的分布式事务解决方案。

1. 一阶段提交(1PC)

先来看一下最简单的事务提交情况。

如果你的业务,只有一个资源需要协调,那么它可以直接提交。比如,你使用了一个数据库,那么就可以直接使用begin,commit等指令完成事务提交。

在Spring中,通过注解,就可以完成这样的事务。如果发生了嵌套事务,它的实现方式,本质上,是通过ThreadLocal向下传递的。所以如果你的应用中有子线程相关的事务需要管理,它办不到。

我们再来看分布式事务。所谓的分布式事务,就是协调2个或者多个资源,达到共同提交或者共同失败的效果,也就是分布式的ACID。

2. 两阶段提交(2PC)

在一阶段提交的概念扩展下,最简单的分布式事务解决方案,就是二阶段提交。二阶段提交不是指有两个参与资源,而是说有两个分布式的协调阶段,它可能有多个资源需要协调。

2.1 重要参与者

协调者(coordinator),也就是我们需要自建事务管理器,通常在整个系统中只有一个。

事务参与者(participants),就是指的我们所说的资源,通常情况下会有多个,否则也称不上分布式事务了。

2.2 过程

广义上的2PC(two phase commit),有哪两阶段呢?

准备阶段,也叫做voting阶段。所谓的voting,就是参与者告知协调者,自己的资源到底是能够提交(代表它准备好了),还是取消本次事务(比如发生异常)。

这个投票比较有意思,只要有一个参与者返回了false,本次事务就需要终止,然后执行rollback。只有全票通过,才会正常commit。协调者将这个结果,周知所有参与者的这个过程,就是二阶段。

二阶段提交其实非常容易理解。你可以把每个参与者的执行,想象成正常的SQL更新语句。它们一直挂在那里等待,直到协调者给出确切的commit或者rollback消息,才会正常往下执行。

2.3 问题

对于第三点,我们举个例子。比如你的commit-request阶段全部返回了yes,然后协调者发送了commit指令。但这时候,有一台 服务器 A宕机了,无法执行这个commit。这时候,我们的client也会收到成功的消息。A机器重启之后,要有能力来恢复、继续执行commit指令,这些都是工程上必须要处理的。

2.4 框架

2PC也叫做XA事务,大多数数据库如MySQL,都支持XA协议。在Java中,JTA(不是什么JPA哦)是XA协议的实现。Spring也有JTA的事务管理器。

Atomikos、bitronix实现了JTA,它们只需要提供jar包就可以了。实现了XA协议的数据库或者消息队列,已经能够具备了准备、提交、回滚的各种能力。

使用在seata等框架,需要启动一个独立的seata服务协调者节点。seata使用的AT,借助于外部事务管理器,概念与XA类似。

3. 三阶段提交(3PC)

相比较二阶段提交,三阶段提交最典型的特点是加入了超时机制。当然,3阶段证明了它有三个阶段,这个差别更显著。它本质上只是2PC的一些改进,所以身上完全充满了2PC的影子。

3.1 重要参与者

3PC和2PC是一样的。

3.2 过程

3PC比2PC多了一个步骤,那就是询问阶段。

提交阶段,无非就是发送个commit或者rollback指令,重要的处理还是在准备阶段,3PC把它一拆为2。

注意下面这个对应关系哦,2PC和3PC都有一个准备阶段,但它们的作用是不同的。

3PC的询问阶段,对应的才是2PC的准备阶段,都是ask一下参与者是否准备好了,但执行过程会有一些区别。

为什么要这么做?因为2PC有效率问题。2PC的执行过程是阻塞的,一个资源在进入准备阶段之后,必须等待所有的资源准备完毕才能进行下一步,在这个过程中,它们对全局一无所知。

比如,有ABCDE等5个参与者,E其实是一个有问题的参与者资源。但2PC每次都会执行ABCD的预提交,当询问到E的时候,发现是有问题的,再依次执行ABCD等参与者的rollback。在这种情况下,ABCD执行了无用的事务预处理和rollback,是非常浪费资源的。

3PC通过拆分这个询问阶段,在确保所有参与者建康良好的情况下,才会发起真正的事务处理,在效率和容错性上更胜一筹。从概率上来讲,由于commit之前粒度变小了,commit阶段出问题的几率就变小,能省下不少事。

另外,3PC引入了超时机制。在PreCommit阶段,如果超时,就认为失败;而在DoCommit阶段,如果超时还会继续执行下去。但不论怎样,整个事务并不会一直等待下去。

3.3 问题

3PC理论上是比较优秀的,还能够避免阻塞问题,但它多了一次网络通信。如果参与者的数量比较多,网络质量比较差的情况下,这个开销非常可观。它的实现也比较复杂,在实际应用中,是不太多的。

3PC也并不是完美的,因为PreCommit阶段和DoCommit也并不是原子的,和2PC类似,依然存在一致性问题。

TCC是柔性事务,而上面介绍的都是刚性事务。有时候,一个技术问题,可以通过业务建模来实现。

2PC和3PC在概念上看起来虽然简单,但放在分布式环境中,考虑各种超时和宕机问题,如果考虑的周全,那可真是要了老命。

我该用哪个

2PC的框架还是比较多的,但3PC全网找了个遍,发现有名的实现几乎没有。

不要伤心,我们有更容易理解,更加直观的分布式事务。那就是TCC,2007年的老古董。

TCC就是大名鼎鼎的补偿事务,是互联网环境最常用的分布式事务。它的核心思想是:为每一个操作,都准备一个确认动作和相应的补偿动作,一共3个方法。

与其靠数据库,不如靠自己的代码!2PC,3PC,都和数据库绑的死死的,TCC才是码农的最爱(意思就是说,你要多写代码)。

image-20210914162640227.png

如图,TCC同样分为三个阶段,但非常的粗暴!

看起来这三个阶段,是2阶段提交的一种?完全不是。但它们的过程可以比较一下。

从上面可以看出来,2PC是一种对事务过程的划分,而TCC是对正常情况的提交和异常情况的补偿。相对于传统的代码,try和CONfirm两者加起来,才是真正的业务逻辑。

TCC是非常容易理解的,但它有一个大的前提,就是这三个动作必须都是幂等的,对业务有一定的要求。拿资金转账来说,try就是冻结金额;confirm就是完成扣减;cancel就是解冻,只要对应的订单号是一直的,多次执行也不会有任何问题。

由于TCC事务的发起方,直接在业务节点即可完成,和TCC的代码在同一个地方。所以,TCC并不需要一个额外的协调者和事务处理器,它存放在本地表或者资源中即可。

是的,它也要记录一些信息,哪怕是HashMap里,否则它根据啥回滚呢?

4.1 问题

TCC事务,需要较多的编码,以及正确的try和confirm划分。由于没有中心协调器,不需要阻塞,TCC的并发量较高,被互联网业务广泛应用。

团队要有能力设计TCC接口,将其拆分成正确的Try和Confirm阶段,实现业务逻辑的分级。

4.2 框架

ByteTCC、tcc-transaction、seata等。

SAGA也是一个柔性事务。

saga的历史更久远,要追溯到1987年的一篇论文,可以说是瓶旧酒。它主要处理的是长活事务,但它不保证ACID,只保证最终一致性。

所谓长活事务,可以被分解成交错运行的子事务,它通过消息,来协调一系列的本地子事务,来达到最终的一致性。

我们可以把SAGA编排器,想象成一个状态机。每当处理完一条消息,它就能够知道要执行的下一条消息(子事务)。

比如,我们把事务T,拆分成了T1,T2,T3,T4。那么我们就必须为这些子事务,提供相应的执行逻辑和补偿逻辑。没错,和TCC一样,不过比TCC少了一步Try动作,同样要求这些操作是幂等的。

你瞧瞧,其实SAGA的概念很好理解,你就按照正常的业务逻辑去执行就行了。只不过如果在任何一步发生了异常,就要把前面所提交的数据全部回滚(补偿)。唯一特殊的是,它通常是通过消息驱动来完成事务运转的。

如果你非要追求它的本质,那就是SAGA和TCC一样,都是先记录执行轨迹,然后通过不断地重试达到最终状态。

上图是rob vettor所绘制的一个典型的SAGA事务拆分图。在图中,黑色的线为正常业务流程,红色的线为补偿业务流程。这是一个简单的电子商务结账流程,整个交易跨了5个微服务,可以说是非常大的长事务了。

可以看到,这样的事务流转,靠文字描述已经是不好理解了,所以SAGA通常会配备一个流程编辑器,直接来把事务编排的过程可视化。

5.1 问题

那问题就有意思多了。

5.2 框架

在《微服务架构设计模式》的第四章中,说明了SAGA的具体使用示例,现在网络上的大多数文章都来自于此。但据我所知,使用SAGA的互联网公司并不是很多,倒是使用TCC的比较多一些(可能是遇到的分布式事务都不是长事务)。

seata同样提供了SAGA的方式,主要使用的是状态机驱动的编排模式。为了支持事务的编排,seata提供了一个专用的流程编辑器(在线)。

设计完毕之后,就可以导出为JSON文件,解析之后可以写入到数据库中。

bytetcc虽然叫tcc,它也支持SAGA。

5.3 SAGA vs TCC

上面也提到,我在平常工作中,用到TCC比SAGA更多一些,也是由于业务场景确定的。下面简单的对比一下。

6. 本地消息表

本地消息表的使用场景比较局限,它要靠MQ去实现,它解决的是数据库事务和MQ之间的事务问题。

如图,有一个分布式事务,在正常落库之后,需要通过MQ来协调后续业务的执行。但是,写DB和写MQ,是无法达成一致性的,就需要加入一个本地消息表来缓存发送到MQ的状态。下面我来描述一下这个过程。

通过这样的循环,就可以达到本地DB和MQ消费者状态的一致性,完成最终一致性的分布式事务。

可以看到,我们有重发MQ的过程,所以这种模式要求消费者也要实现幂等的功能,避免重复对业务产生影响。

6.1 问题

使用本地消息表方案的系统还是挺多的,但它的弊端也显而易见。

需要开发专用的代码,与业务耦合在一起,无法完成抽象的框架

本地消息表需要写数据库,如果数据库本身的I/O已经比较高了,它会增加数据库的压力

7. 最大努力补偿

最大努力补偿,是一种衰减式的补偿机制。

拿个最简单的例子来说吧。如果你是微信支付的接入方,微信支付成功之后,它会将支付结果推送到你指定的接口。

微信支付+你的支付结果处理,就可以算是一个大的分布式事务。涉及到微信的系统还有你的自有系统。

如果你的系统一直处理不成功,那么微信支付就会一直不停的重试。这就叫最大努力补偿,用在系统内和系统间都是可以的。

但也不能无限的重试,重试的间隔通常会随着时间衰减。常用的衰减策略有。

上面的公式,意味着如果一直无法处理成功,将在1s…,最大2小时后重试。如果还不成功,就只能进入人工处理通道。

最大努力补偿只是一种思想,实际的应用有多种方式。比如,我首先将事务落地到消息队列,然后依靠消息队列的重试机制,来达到最大努力补偿的效果,这些都是可行的方案。

8. 总结

我们在文中,从本地事务谈起,分别聊到了2PC、3PC、TCC、SAGA、本地消息表、最大努力补偿等,也了解到了各种解决方案的一些应用场景和解决方式。

分布式事务框架,在这些理论基础上,都进行了或多或少的修订,也有不少创新。比如LCN框架(lock,confirm,notify),就抽象出了控制方和发起方的概念,感兴趣的可以自行了解。

在互联网公司中,由于高并发量的诉求,在实际应用中,相对于强事务,大家普遍选用软事务进行业务处理。使用最多的,就是TCC、SAGA、本地消息表等解决方案。SAGA应对长事务特别拿手,但隔离性稍差;TCC一直性好并发高,但需要较多编码;本地消息表应用场景有限,耦合业务不能复用。各种解决方案都有它的利弊,一定要结合使用场景进行选择。

在框架方面,阿里的seata(早些年叫fescar),已经得到了广泛应用,XA、TCC、SAGA等模式都支持,如果你需要这方面的功能,可以集成尝试一下。

希望看完本文之后,再次碰到“如何在微服务中实现分布式事务?”这种问题,除了回答“要尽量避免使用分布式事务”,你还可以找到确实可行的解决方案。

作者简介:小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。


常用的应用文有哪些

应用文的种类是很多的,可以分为以下三类: 一般性应用文,这类应用文有人认为应包括以下几种:书信、启事、会议记录、读书笔记、说明书等。 公文性应用文,这是以党和国家机关、社会团体、企事业单位的名义发出的文件类应用文。 如布告、通告、批复、指示、决定、命令、请示、公函等。 这类应用文往往庄重严肃,适用于特定的场合。 事务性应用文,事务性应用文一般包括请柬、调查报告、规章制度及各种鉴定等,这是在处理日常事务时所使用的一种应用文。 为了统一安排本书的体例,同时根据各种日常应用文本身的特点,这里将日常应用文分为以下几类。 (一)社交礼仪类 这是一类适用于社交场合的应用文,它的存在完全是为了促进双方之间关系的发展,同时它又是人们文明交流的一种体现。 人与人之间亲疏有别、长幼有序,礼仪就是在社会交往中把握好分寸,恰如其分地把握双方的关系。 礼仪类应用文是人们在互相平等、相互尊重的基础上形成的一种日常应用文。 礼仪类日常应用文主要包括以下一些常用的文体:请柬、欢迎词、祝辞、欢送词、邀请信、题词、慰问信、表扬信、感谢信、贺信、贺电、赠言等。 (二)海报启事类 海报启事类日常应用文是指那些可以公开张贴在公共场合或通过媒介公开播放、刊登的广而告之的一类事务性应用文。 这类应用文人们使用广泛,几乎大街小巷、工厂、学校等公开的场 合,你都可以见到它们。 海报启事类日常应用文一般包括征稿启事、征婚启事、征订启事、婚姻启事、开业启事、寻人启事、寻物启事、招聘启事、招生启事、海报等一些应用文样式。 (三)便条契据类 这是由当事人双方在事务交流中出具给对方的作为凭证或说明某些问题的一种常见应用文。 这类应用文短小精悍,可随时使用。 便条契据类应用文一般又可分为以下几种:借据、欠条、收条、领条、请假条、便条、托 事条、催托条、馈赠条、留言条等。 随着各种正轨票据的推广和使用,这类应用文形式将会逐渐减少。 (四)家书情书类 在人们的各种交往中,人们之间的书信来往应该是最频繁的交流方式。 自古至今,无论朋友之间的互致问候、表达关心,或者情人之间互致相思、表达爱慕均使用书信这种形式。 伟人名士的家书、情书也往往会给别人或后人许多启迪和帮助,所以这类书信为我们留下了丰富的文化遗产,有些同时堪称文学作品的典范。 因此,我们就将家书情书专归为一类,以飨读者。 这类书信主要包括以下几种:写给长辈的信、写给晚辈的信、写给兄弟姐妹的信、写给亲朋的信、初恋情书、求爱情书、热恋情书等。 (五)专用书信类 专用书信类是具有书信的格式,发文的对象或者使用的目的又是特定的一类应用 文。 一般来讲,这类书信可以分许多种,如咨询信、介绍信、证明信、推荐信、求职信、聘书、 履历、说明书、报捷书、保证书、倡议书、建议书、悔过书等。 (六)申请书类 申请书类应用文应属于专用书信类的一个分支,但由于其使用较为特殊,具有其自身非常突出的特点,即请乞性,所以这里专列为一类。 申请书类的日常应用文一般可以包括入学申请书、入党入团申请书、住房申请书、困难补助 申请书、辞职申请书等几种。 (七)对联类 对联是人们在婚丧嫁娶、宴飨寿诞、季节变换时使用的一种具有较浓的文化传统气息的一种应用文样式。 它有较为严格的行文要求,一般来讲,它并不适宜于平民百姓们使用。 但由于每逢一些必要的场合,它又是必不可少的,所以我们也对对联类作了介绍。 对联类常见应用文包括节令联、祝寿联、婚联、喜联、挽联、名胜联等六种。 (八)讣告悼词类 这是有关以致悼死者为主的一类日常应用文。 其中有些文体只适用于特殊的人物特定的场合 ,有些则广泛地应用于民间。 了解其写作的基本格式也十分的必要。 一般来讲,这类应用文可以包括讣告、唁电、追悼会仪式、治丧名单、悼词、碑文等六种。 (九)英文类 随着改革开放的深入,国际间各种交流的加强,常用英文书信也已渗透到我们的日常生活之 中。 因此,本书特意选取了一些最为实用的几类英文日常应用文作一下简单的介绍,虽挂一漏万,但也希望对读者稍有帮助。 这里介绍的英语应用文主要有求职信、介绍信、入学申请书、邀请信、以及作为附件的简历等共五种。

请高手用自己的话描述对 spring 与 EJB 的理解.. (不要复制的!!!)

我希望楼主能够跳出技术的范畴,看我的答案 和 EJB 有什么可比之处? Spring和EJB都是两种Java领域模型(框架),当然有很多不同,其实比不需要关注两者的不同,以及可比之处,如果客户要求你使用EJB,你就用EJB,要你用Spring,你就用Spring。 不用不需要知道,因为知道了没好处。 如果客户没有要求,建议你用Spring,更加敏捷,它的依赖注入可以让它跟其它任何框架无耦合的组合。 所谓轻量级,就是它对容器(如sevlet容器或Ejb容器)的依赖更小,并不表示它的性能和功能比重量级的差,很多服务器中没有包含Ejb容器。 2. spring 能支持分布式吗? 分布式很大一部分依赖的是容器。 Java本身就有支持分布式的特性。 与具体框架无关。 所以如果你的程序设计成分布式的,那就是分布式的,不管你用srping,还是Ejb,或者两个都用 3.分布式具体怎么描述的? 所谓分布式,就是一个系统的多个服务在不同的域上。 举个例子,你登录了sohu之后,可以访问chinaren而不需要重新登录,但sohu和chianren是两个不同的域,你把这一整个看成一个大系统,那么两个域中的子系统就是分布式的服务。 有一种叫单点登录的技术能够让你跨域访问多个子应用,而不需要从新登录。 还有一种分布式是为了控制大量的并发访问,你访问sohu,其实有可能访问的并非总是同一个服务器,它可能是多个服务器提供完全相同内容的系统,在这些系统的前端,有个提供负载均衡的系统引导你去访问当前负荷较小的服务器。 到底有什么好处 这个问题很奇怪,每个框架都要它的特点。 但你需要什么,当它能满足你,你就去用它嘛。 你当然有权利决定使用其它的事务管理机制来替代EJB的,比如spring的申明式事务。 你要做的就是把系统做出来,老板不会关心你的技术细节。 如果实在不知道是要用EJB或者Spring(如果两者的了解程度相当),就抓阄决定吧,o(∩_∩)o...。 和事务管理,什么时候才用得上? 我开发了那么多系统.从来没碰过! JMS没用过有可能,因为大部分J2EE都是单服务的web应用。 不需要通过JMS提供底层系统内部通信。 但事务!!!,任何一个有CURD的系统都该有的呀,否则如何保证数据的安全呢? 比如你有两个操作,先添加一条记录,紧接着修改这条记录,当你第一个操作执行完了,第二个操作出异常了,这两个操作是一件事,把它套在一个事务里,第一个操作就算成功了,也会被回滚,因为它整体是失败的。 没有事务,事情就只做了一半,就会多出一条错误数据。 我想我写的这些文字要比上面两位精彩一些吧

PHP高级程序员要懂什么?

程序员可以分为很多种,像UNIX程序员、windows程序员,或是C++程序员、Delphi程序员,等等。 今天我想谈的是Web程序员,一名真正的Web程序员应该懂得那些方面的知识,应该注意学习哪些东西。 也许有些朋友会说,我知道Asp、Jsp,会做网站、会做bbs,这应该叫Web程序员了吧。 确实,我承认,这些技术是一名Web程序员应该具备的;但是,你如果仅懂得这些,却只能叫做Asp程序员、Jsp程序员,而不是真正意义上的Web程序员。 现在的世界是属于Internet的,大部分的应用基于Internet,大家可以想想,像Yahoo、Microsoft、Amazon那样的网站,其访问量之大、应用之复杂,需要什么样的技术才可以支撑,难道仅仅是硬件的功劳么。 我想在Windows平台下来谈谈Web程序员应该掌握的技术 1. 首先,就是上面提到的各种脚本,asp、jsp、php等等,这些东西大同小异,基本可以举一反三。 2. 数据库, 相信做Web的人肯定用过,像Access、Sql Server、Oracle。 很多人会用各种数据库,但是仅限于写一些sql,select、update、insert,用ADO来操作,如果这样,就算会用100种数据库又有什么用呢? 你应该考虑用户量、访问速度、内存消耗,这些东西和你的sql密切相关,我经常见到很多分页程序根本不去考虑数据库中有多少条数据,统统select出来,很明显,当你从数据库中查出1万条数据和100条数据,占用的内存是不同的。 另外,数据库连接池和事务机制是非常重要的,应该知道数据库用什么来保证事务,连接池如何实现,这些都是商务应用的关键。 譬如,目前很多的应用服务,像webLogic、MTS,都包含事务处理,可以说好的事务处理决定了他们的竞争力。 3. 组件技术 我想是现在的Web应用推动了组件技术的发展。 以前,从老式的静态库、动态库(dll),到现在的COM/DCOM,再到正在兴起中的Web Service;从单机调用,到基于内部网的分布式调用,到现在基于Internet的分布式计算。 现在的应用都是基于组件的n层结构,最明显的就是COM和JavaBean。 这些东西体现了软件架构的发展,以前是基于单机的应用,然后是C/S结构,到现在的B/S结构。 我记得李维曾经说过,程序员一定要注意软件技术的发展趋势,只有这样,才不至于被淹没在技术的洪流中。 我想,作为Web程序员,一定要明白COM的原理,如何实现这种调用、如何进行分布式调用。 说实话,我觉得COM还是比较复杂的,否则微软为什么要提供ATL和VB呢,要搞明白,应该学学C++,因为VC中提供的ATL库可以很明显的说明COM的内部运行机制。 4. 网络技术 这可以说是Web程序员最应该懂得东西。 起码,应该知道Web服务器的机制,要明白Http协议。 就拿IIS来说,要懂得web应用程序运行的进程安全和IIS的关系,懂得ISApi的作用。 如果有时间,就看看TCP/IP,看看winsock,这些都是底层的网络的东西。 我所说的这些都是基于微软技术下的东西,其他的像Java方面的东西都可以对照参考,就不多说了,这也是我这几年来的一些心得。 总之,学海无涯,每当接触一些新的东西,就会发现自己的不足,同时也就觉得基础知识的重要。 说实话,像我们做应用开发,用别人的东西,在现在这种情况下,新的技术层出不穷,稍不注意就会被甩开,这也是没有办法的事情。

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐