1、关于分布式锁的了解?
原理:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。
具备的条件:
①分布式环境下,一个方法在同一时间只能被一个机器的一个线程执行
②高可用的获取锁和释放锁
③高性能的获取锁和释放锁
④具备可重入特性
⑤具备锁失效机制,防止死锁
分布式锁的三种实现:
A. 基于数据库实现分布式锁;
B. 基于缓存(Redis等)实现分布式锁;
C. 基于Zookeeper实现分布式锁
A.基于数据库的实现:
在数据库中创建一个表,表中包含方法名等字段,并在方法名字段上创建唯一索引,想要执行某个方法,就是用这个方法名向表中插入数据,成功插入则获取锁,执行完成后删除对应的行数据释放锁
B.基于缓存(Redis等)实现分布式锁:
推荐: Redis有很高的性能;
Redis命令对此支持较好,实现起来比较方便
实现:
(1)获取锁的时候,使用setnx加锁,并使用expire 命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。
(2)获取锁的时候设置一个获取的超时时间,若超过这个时间就放弃获取锁。
(3)释放锁的时候,通过UUID判断是不是该锁,若是该锁,就执行delete进行锁释放。
C.基于Zookeeper的实现方式
原因: Zookeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名。
实现:
- 创建一个目录mylock
- 线程A想获取锁就在mylock目录下创建临时顺序节点
- 获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁;
- 线程B获取所有节点,判断自己是不是最小的节点,设置监听比自己次小的节点
- 线程A处理完,删除自己的节点,线程B监听到便跟事件,判断自己是不是最小的节点,如果是则获得锁。
- 使用Apache的开源库Curator,它是一个Zookeeper客户端,Curator提供的InterProcessMutex是分布式锁的实现,acquire方法用于获取锁,release方法用于释放锁。
2、 分布式事务处理机制
在CAP定理中,一致性、可用性、分区容错性是不可能同时存在的。但在实际的应用场景中,数据的一致性是需要保证的。
事务是达到以上目的的最好方法:
即保证执行结果的正确性;保证数据的一致性;ACID
常见的事务处理机制:
Master-Slave 复制:
Slave一般是Master的备份。读写都在Master上,异步同步数据到Slave;Master挂了,Slave只能读。
Master-Master多主复制:
2个以上Master,都提供读写服务。一台挂了,另一台正常读写。
两阶段提交:
第一阶段:准备阶段:
协调者节点向所有参与者节点询问是否可以执行提交操作,并开始等待各参与者节点的响应。参与者节点执行询问发起为止的所有事务操作,并将Undo信息和Redo信息写入日志。各参与者节点响应协调者节点发起的询问。
第二阶段:提交阶段:
如果协调者收到了参与者的失败消息或者超市直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据协调者的指令执行提交或者回滚操作,释放所有事务处理过程中使用的锁资源。
三阶段提交:
CanCommit阶段:协调者向参与者发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。
PreCommit阶段:协调者根据参与者的反应情况来决定是否可以记忆事务的PreCommit操作。
doCommit阶段:进行真正的事务提交。具体为执行提交、终端事务。
3、用分布式和没有用分布式的项目的差异是什么?
- 传统项目:
存在问题:
1:模块之间耦合度太高,其中一个功能升级,其他的模块都得一起升级部署。
2:开发困难,各个团队开发最后都要整合在一起.
3:系统扩展性差
4:不能灵活进行分布式部署
解决方案:
把模块才分成独立的工程,单节点运行,如果某一个节点压力大了可以单独对这个节点进行增加配置,其他节点不受影响。缺点就是系统之间交互需要额外的工作量来进行接口的开发。把系统拆分成多个工程,需要完成系统的工程需要多个工程协作完成,这种形式就叫做分布式。
- 分布式:
把系统拆分成多个子系统.
优点:
1:把模块拆分,使用接口通信,降低模块之间的耦合度.
2:把项目拆分成若干个子项目,不同的团队负责不同的子项目.
3:增加功能时只需要再增加一个子项目,调用其他系统的接口就可以。
4:可以灵活的进行分布式部署.
5:提高代码的复用性,比如service层,如果不采用分布式rest服务方式架构就会在手机wap商城,微信商城,pc,android,ios每个端都要写一个service层逻辑,开发量大,难以维护一起升级,这时候就可以采用分布式rest服务方式,公用一个service层。
1、锁:
单进程的系统中,存在多线程同时操作一个公共变量,此时需要加锁对变量进行同步操作,保证多线程的操作线性执行消除并发修改。解决的是单进程中的多线程并发问题。
2、分布式锁:
只要的应用场景是在集群模式的多个相同服务,可能会部署在不同机器上,解决进程间安全问题,防止多进程同时操作一个变量或者数据库。解决的是多进程的并发问题。
3、事务
解决一个会话过程中,上下文的修改对所有数据库表的操作要么全部成功,要不全部失败。所以应用在service层。解决的是一个会话中的操作的数据一致性。
4、分布式事务
解决一个联动操作,比如一个商品的买卖分为:
(1)添加商品到购物车
(2)修改商品库存-1
此时购物车服务和商品库存服务可能部署在两台电脑,这时候需要保证对两个服务的操作都全部成功或者全部回退。解决的是组合服务的数据操作的一致性问题。
分布式锁是解决并发时资源争抢的问题,分布式事务和本地事务是解决流程化提交问题。
一、其中分布式锁实现:
1.基于数据库锁实现,悲观锁和乐观锁
悲观锁就是采用行锁,for update ,属于排他锁,其他任何写操作都要等当前操作完成,性能差,并发上来都要等操作完成,需要设置setAutoCommit
乐观锁就是通过添加版本号,在update 时比较版本号方式更新 比如version,不被阻塞;
2.基于redis实现
setnx(key,expire),get(key),getset(key,newexpire)实现完整的分布式锁,并且可以通过注解来加锁
3.基于zookeeper
实际是基于paoxy
二、分布式事务实现
原则:优先使用本地事务,将操作优先在一个本地事务中完成,无法使用本地事务的采用分布式事务
1.全局事务(DTP模型),基于2PC、3PC(两段和三段提交)实现,但由于同步阻塞,处理效率低,不适合大型网站分布式场景
原则:ACID,刚性事务
2pc:一阶段预提交,二阶段提交,都成功情况才会成功
2.柔性事务
原则:基本可用,最终一致,即BASE理论
关于柔性事务,最主要的有以下三种类型:异步确保型、补偿型、最大努力通知型
幂等性:参数列表对比,是否重复请求
可补偿:保证原子性
TCC操作:TCC位于业务服务层而非资源层
TCC没有单独的准备(Prepare)阶段,Try操作兼备资源操作与准备能力 Try操作可以灵活选择业务资源的锁定粒度(以业务定粒度)
TCC有较高开发成本