分布式锁
-
控制分布式系统之间同步访问共享资源的一种方式
-
解决方案
-
Redis分布式锁
- 命令:加锁加过期时间set key value nx ex 10s,释放del key
- setNx 加锁,如果为空就set值,并返回1,如果存在(不为空)不进行操作,并返回0
- setNx 是redis命令中的方法,setIfAbsent 是java中的方法
- Redisson 通过lock,unlock方法加锁解锁,后台维持一个watchDog线程,每10s判断锁是否存在,存在自动续期
-
Zookeeper分布式锁,通过顺序,临时节点去做
-
排他锁(独占锁):在获取锁的时候,所有客户端尝试去创建临时子节点,最终只有一个能创建成功,获得锁,然后那些没抢到锁的节点注册监听,进入等待(羊群效应)
-
共享锁(读锁):所有客户端去创建临时顺序节点,然后调用getChildren接口来获取所有的子节点列表,去判断是否拿到锁,编号最小的获取锁,其他的注册监听,监听的是比他序号小的那一个节点,进入等待 还可以用封装好的Curator去做,锁方案:排他锁,读写锁,可重入排他锁(acquire加锁,release释放)
-
CountDownLatch:让一些线程阻塞直到另一些线程完成一系列操作后才被唤醒,做减法(共享锁)
-
CyclicBarrier:与CountDownLatch相反,也就是做加法,开始是0,加到某个值的时候就执行
-
-
基于数据库
- 悲观锁:就是修改数据的时候先加锁,依靠数据库提供的锁机制 "For Update"
- 乐观锁:可以基于Version机制来实现,操作数据的时候先给表加一个版本,每操作一次,版本+1,更新之前先查询版本号,更新的时候再去比对一次,相等更新,不相等,就不更新,是一种无锁化修改值的操作,CAS就是乐观锁
-
分布式事务
事务是访问数据库的一个操作序列,CURD满足ACID原则
-
ACID原则
- 原子性:不可分割
- 一致性:数据一致
- 隔离性:互不影响
- 持久性:数据持久
-
CAP理论
- Consistency:一致性,当数据分布在多个节点上,从任意结点读取到的数据都是最新的状态
- Availability:可用性,所有请求都有响应,不会出现响应超时或响应错误
- Partition tolerance:分区容错性,一个节点挂了不影响其他节点提供服务
-
BASE理论
- Basically Available:基本可用
- Soft state:软状态
- Eventually consistent:最终一致性
-
解决方案
- 通过@Transactional注解来做事务控制,他是基于SpringAOP来实现的,实质上就是拦截对象方法,对方法进行改造,增强,将具体的逻辑与事务处理解耦,默认情况下,只有来自外部的方法调用才会被AOP代理捕获,类内部方法之间调用不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰
// 场景:充值,退款 @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)-
Propagation:事务传播行为
- 默认required 如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务
- requires_new 创建一个新的事务,如果当前存在,则把当前事务挂起
-
Isolation:事务隔离级别
- 读未提交: 脏读
- 读已提交: 不可重复读
- 重复读: 幻读
- 序列化,隔离级别越高,并发能力越低
- Isolation.DEFAULT:使用底层数据库默认的隔离级别,mysql默认 重复读
-
RollbackFor :事务回滚的异常类型,默认只有RuntimeException才会回滚