分库/分表的扩展模式
- 中间层可以将数据拆解成,对不同数据库进行访问,然后将访问结果在中间层进行汇总。
- 局限性:一个事务的访问在不同的数据库中,如:转账,一个account在数据库A,另一个在数据库B,会将一个事务拆解成两个事务,就很难保证事物的原子性,以及其他的一些性质。 此时,需要将中间层再加一些性质,来保证事物的性质ACID;如:mysql中在数据库中都会提供一些接口给中间件,去做分布式数据库的处理。
- 优点:将数据库之间的通讯降到最低,因为会在意如何拆分业务使负载均衡,在意逻辑;基本大部分都是用这样的扩展方式,这种扩展方式更强。
并行/分布式数据库
- 在数据库内部拆分数据,分到不同节点上执行。此时应用访问数据库就向访问单机数据库一样,对应用友好。
- 优点:不需要将一个查询拆分为子查询,可以分给不同节点不同的东西。不存在对数据库访问受到局限性。
- 局限性:数据库并行/分布式的方式不能做到对应用透明;会采取直接的方式分数据,会导致扩展性上不去,应用和数据库协调的不好
分布式事务
- 有多个节点,其中有一个节点接受到请求,会分发任务到其他节点去执行,那么该节点为主节点(coordinator),其他节点为从节点(participant)
- 认为主节点就做组织工作,不做其他事物;主节点要满足ACID,主节点可以是APP/DB
分布式并发控制 —— ACID
- 问题:将T,T’拆分,分发给下面的其他节点,当主节点不做任务时,是否能保障事务的可串行化。即T在T’前 ,或者,T’在T前。
- 不能,在其他的节点上分别为T1,T1’; T2,T2’; T3,T3’; 在每个数据库上都能保证各自的可串行化,但每个子节点出来的结果可以先后不一定,整体而言就不可串行化啦。
- 怎么保证可串行化?
-
要保证在子节点上执行的次序是一致的。怎么保证?
- 避免形成环
- 保证每个单节点的调度是可串行化的
- 保证全局事务的所有每个子事务在每个节点上都是同样的顺序进行
- 避免形成环,即T1——> T2 on site X,T2——> T1 on site Y ;两者可以相互通信去避免环。
- 避免形成环
-
加个全局锁(两种方法)
- Centralized 2PL:在分布式中选择一个节点,让它做锁管理;那么不可串行化的结果就不会出现了。在X,Y上加锁,可能会出现死锁问题;要先结束掉事务,即T1,T2都希望自己快点结束掉。如果两者都先访问x时,就是可以的;如果两者串行访问的话,会导致死锁。(事务结束掉就解锁)
-
锁管理的那个节点,可能负载过高;性能上不去,每个节点都要去加锁解锁。
- 因此提出了distributed 2PL
-
但两段锁并不要求事务必须一次性将所有要使用的数据全部加锁,这一点与一次性封锁不同,这就是遵守两段锁协议仍可能发生死锁的原因所在。
-
集中式的是将所用数据的全部副本都封锁,然后操作
- 再这个节点上有什么样的数据,那就管理什么样的锁
- 将锁分布到每个节点上,也能达到前者的效果
- 缺点:查死锁的话,需要结合多个节点的;此种情况下,认为时间长了就是死锁了,但很难去把握时间大小(有可能有的事务时间很长)
- 再这个节点上有什么样的数据,那就管理什么样的锁
-
- Centralized 2PL:在分布式中选择一个节点,让它做锁管理;那么不可串行化的结果就不会出现了。在X,Y上加锁,可能会出现死锁问题;要先结束掉事务,即T1,T2都希望自己快点结束掉。如果两者都先访问x时,就是可以的;如果两者串行访问的话,会导致死锁。(事务结束掉就解锁)
-
分布式数据库基本封锁算法
- 分布式封锁方法:
- 主站点封锁法:
- 定义一个站点为主站点,负责系统全部封锁管理
- 所有站点都向主站点提出封锁和解锁请求,由它去处理
- 缺点:
- 所有封锁请求都送往单个站点,容易由于超负荷造成“瓶颈”
- 主站点故障造成会使系统瘫痪,封锁消息都在这里,制约了系统可用性和可靠性
- 主站点封锁法:
分布式数据库的 A 和 D
- 每个节点都有自己的日志,能保证各自的原子性和持久性,但不能保证整个事务的原子性;因此什么策略可以保证要么都提交,要么都撤销?
- 两阶段提交(2PC):在commit之前,主节点询问子节点是否可以提交;若是都可以提交,就提交;如果其中一个不能提交,就撤销任务。由cooertor决定是否可以提交。
- 系统故障问题:(在两阶段提交中,不响应的后果)
- 当在prepared过程中,一个从节点timeout,那么主节点撤销该任务。
- 在commit过程中,一个从节点timeout,主节点不断给这个从节点发commit
- 在所有的从节点都已经prepared好了,主节点timeout了,此时有可能有部分从节点接收到了主节点的消息;从节点之间相互广播,协商,如是否有人收到主节点消息,如果有一个从节点说主节点已经让它提交;那么这个时候从节点都能提交啦;如果没有从节点收到主节点的消息,