1.分布式事务了解吗
XA分布式事务协议
两阶段提交( 2PC )
需要一个协调者节点。
第一阶段:协调者让参与者发出prepare,让参与者在本地进行数据更新,但数据未提交(此时的更新记录会记录undo log 和 redo log),当所有参与者的本地更新准备好,告知协调者
第二阶段:如果协调者结点收到的第一阶段反馈都是正向反馈,则向所有事务参与者发送Commit请求,让参与者提交自己的本地事务。提交完毕后返回确认信息。
缺点:1.单点故障(协调者)2.性能(所有的准备好才会提交)3,丢失消息导致不一致问题
解决方式: 3PC
三阶段提交( 3PC )
2.分布式锁
背景
本质:解决JUC无法提供跨JVM的互斥(同步)能力的问题
分布式锁应该具备的条件
1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
2、高可用的获取锁与释放锁;
3、高性能的获取锁与释放锁;
4、具备可重入特性;
5、具备锁失效机制,防止死锁;
6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。
分布式锁的三种实现方式
在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。
基于数据库实现分布式锁;
基于缓存(Redis等)实现分布式锁;
基于Zookeeper实现分布式锁;
基于数据库实现分布式锁
建一个 方法名 的表,方法名 列唯一,线程想要执行这个方法(即获取到锁),必须在表中插入这行数据,并且在执行完毕后删除这条数据(释放锁)
缺点:
1、这把锁强依赖数据库的可用性,`数据库是一个单点`,一旦数据库挂掉,会导致业务系统不可用。
2、这把锁没有失效时间,一旦解锁操作失败,就会导致锁记录一直在数据库中,其他线程无法再获得到锁。
3、这把锁只能是非阻塞的,因为数据的insert操作,一旦插入失败就会直接报错。没有获得锁的线程并不会进入排队队列,要想再次获得锁就要再次触发获得锁操作。
4、这把锁是非重入的,同一个线程在没有释放锁之前无法再次获得该锁。因为数据中数据已经存在了。
解决方案:
1、数据库是单点?搞两个数据库,数据之前双向同步。一旦挂掉快速切换到备库上。
2、没有失效时间?只要做一个定时任务,每隔一定时间把数据库中的超时数据清理一遍。
3、非阻塞的?搞一个while循环,直到insert成功再返回成功。
4、非重入的?在数据库表中加个字段,记录当前获得锁的机器的主机信息和线程信息,那么下次再获取锁的时候先查询数据库,如果当前机器的主机信息和线程信息在数据库可以查到的话,直接把锁分配给他就可以了。