事务是指由一组操作组成的一个工作单元
一、ACID:
原子性(Atomicity),可以理解为一个事务内的所有操作要么都执行,要么都不执行。
一致性(Consistency),不会存在中间状态的数据,数据库从一个状态到另一个状态的变更。
隔离性(Isolation),事物执行时是不会互相干扰的,内部数据时隔离开的。
持久性(Durability),指的是一个事务完成了之后数据就被永远保存下来,之后的其他操作或故障都不会对事务的结果产生影响。
二、本地事务,分布式事务
本地事务就是用关系数据库来控制事务,关系数据库通常都具有ACID特性,从而完成事务控制。
在分布式系统中一次操作由多个系统协同完成,这种一次事务操作涉及多个系统通过网络协同完成的过程称为分布式事务。强调的是多个系统通过网络协同完成一个事务的过程,并不强调多个系统访问了不同的数据库,即使多个系统访问的是同一个数据库也是分布式事务
三、CAP理论
一致性(Consistency):分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
可用性(Availability):保证每个请求不管成功或者失败都有响应。
分区容忍性(Partition tolerance):系统中任意信息的丢失或失败不会影响系统的继续运作。
四、解决方案
1、了解 2pc 3pc tcc
(Java微服务下的分布式事务介绍及其解决方案_oldshaui的博客-CSDN博客_java分布式事务解决方案)2、消息队列实现
spring的事务本质上是利用数据库事务来实现,事务的实现方式:锁协议、MVCC、时间戳排序协议、有效性检查协议,锁协议是事务的一种实现方式,事务是粗粒度的概念、乐观锁悲观锁可以更细粒度的控制;
悲观锁,乐观锁
通过本地事务控制并发,理解为数据库层面加锁,从而控制数据准确性。
1、悲观锁(PCC): 先取锁再访问,是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度。因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。(数据库的行锁,表锁,写锁,读锁等)
场景:写多 读少
实现:共享锁:共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改
排它锁:排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁。获取排他锁的事务可以对数据行读取和修改。
2、乐观锁(OCL):业务层面实现,常会以CAS实现,但多线程访问时难以避免ABA问题,所以通常以加版本号来规避。数据库层面实现可以利用时间戳,或指定字段。
不过在高并发下,需要考虑锁的粒度,
例:扣库存,但不影响其他用户下单
如果用户下单数为 1,则通过库存- 1 > 0的方式进行乐观锁控制。在执行过程中,会在一次原子操作中查询一遍 quantity 的值,并将其扣减掉 1。
Synchronized (理解为对象锁,用来保证数据的一致性)
作用于应用服务上的锁,区别于数据库中的锁
同步代码块: 锁的粒度仅限于当前代码块;
同步方法: synchronized锁不能被继承,子类重新加锁 或super.method();
静态同步方法: 静态方法属于类而不是对象,因此锁的粒度在当前类对象;
修饰类: 等同于修饰静态方法,不是加在类上,而是在内部方法中获取类对象,sunchronized(类名.class){...};
注: 底层原理 :https://blog.csdn.net/javazejian/article/details/72828483https://blog.csdn.net/weixin_38481963/article/details/88384493https://blog.csdn.net/weixin_43213517/article/details/89713899
synchronized属于本地锁,分布式环境下可能会失效(多进程 无法共享内存),
分布式锁的实现:https://blog.csdn.net/jiandanokok/article/details/114296755