zoukankan      html  css  js  c++  java
  • 分布式系统阅读笔记(十六)-----事务和并发控制

    介绍

    在分布式系统中,事务的运用和共享资源的并发控制是非常常见的。简单的说,事务就是一些原子的操作的集合。原子操作的意思就是要么操作成功要么操作失败,没有其他的选择。并发控制是出现在高并发场景的时候,本篇主要描述3种常见的手段,1、锁的措施。2、乐观并发控制手段。3、时间戳序列方式。在此之前,先回顾一下平时在写程序的时候,常见的用于同步的手段,比如说:

    1、用synchronize关键字,这个字java里用的,保证只有一个线程能执行里面的方法。

    2、wait()和notify()方法用以协调同步使用的,比如在blockingQueue阻塞队列里时用的。

    事务的失败是可以恢复的,通过永久的存储,可以再次恢复,可以通过异地的副本措施。

    事务

    事务有2个特征:1、操作的独立性,与其他的操作时隔离的,不受影响的。2、他的操作要么执行成功,要么就执行失败,且不会对其他的操作有任何影响。因为事务要求操作的原子性,因此要保证操作的同步,这时候服务器的目标就是提高事务的并发程序又不影响他的原子性。

    1、每个事务被一个协调器所创建盒管理的。

    2、在事务并发的情况下会出现2个比较的典型的问题:1、失去更新问题。2、状态不一致问题,典型的就是数据读出的是老的数据,而事实上数据已经被更新了。

    3、事务从中止的情况下恢复,那么服务器必须记录下所有已提交事务的记录或者为事务留存许多的暂存的版本。

    嵌套事务

    嵌套事务(Nested transaction)是从单一事务中扩展而来的。他是由一系列的事务组合而成的,分为the top-level transaction和subtransaction 2种事务,subtransction指的是他的子事务。以这2种事务构成了树状的结构。

    1、嵌套事务相比较于普通事务的优点:1、支持更多的并发度,他的子事务可以在不同的服务器上并行。2、子事务可以独立的提交或者中止事务。

    2、嵌套事务的一些规则:1、一个事务只有等到他的子事务都完成了才能决定提交还是中止。2、当父事务中止时候,所有子事务都将会中止。

    锁是一种非常常见的用于控制资源访问并发的措施,我们一般所说的锁是指排他锁,只能独占式的。当然锁可以进行细粒度化的划分。比如说,可以划分为读锁和写锁的分离,读锁其实是大家共享的,也叫共享锁。

    1、在嵌套事务中,他的锁模式有一点点的不同,当父事务持有锁的事务,他的子事务可以接过父事务的锁执行操作,执行完毕,再归还锁给父事务。

    2、使用锁最讨厌出现的情况就是死锁,简单点说,就是大家都在等对方手中的资源,谁都不肯放手,组后就一直持僵持状态。

    3、预防死锁的办法有:1、把事务中所涉及到事务全部进行锁定。这样其他的事务就不会跟你抢占资源了,但是显然这么做,操作的效率大大降低,只会运行单位时间执行一个操作了。2、进行死锁的监测,通过发现有没有循环的等待图。3、超时的检测也是一种常用的检测,但是这个时间间隔的设定是一个大的问题,因为中间有很多的影响因素。

    4、不同的锁模式可以增加并发度。这里提及2种锁模式:1、Two-version Locking,2版本锁,用到了3种锁,read lock,write lock,和commit lock。2、hierarchic locks,分层级的锁模式。

    乐观并发控制

    上面说的锁是一种悲观的并发控制手段,而这节说的则是一种乐观的并发控制手段,完全不同的方式。先列举几个锁方式的缺点:

    1、不支持对数据的高并发的访问,这期间一般都有Delay的。

    2、会造成死锁,这个问题一直很大。

    3、如果出现随机的失败,那么锁将得不到释放,让等待该锁的对象会陷入无限的等待。

    而这里我们说的乐观并发控制的原理就是通过观察。高并发的情况不就是怕有冲突吗,没事,我们解决就是了。

    1、在乐观并发控制的时候,有3个阶段:1、working phase工作阶段,在这个阶段会有一个对象的多个临时的版本。2、validation phase 验证阶段,就是解决第一阶段的有冲突矛盾的地方。3、update phase 更新阶段,伴随的是事务的提交。

    2、验证阶段的方式有2种:1、backward validation ,向后验证。2、forward validation ,向前验证。

    时间戳序列

    在并发控制的模式中时间戳的方式是基于时间戳的序列。每个操作每个事务会为其他分配一个独立,唯一的时间戳值。每个时间戳的值代表了一个操作的对象的版本。与上一个思想有些类似。核心思想是通过读写事务的时间戳的值,来比较先后顺序,在一定规则的判断下,最后决定是否执行操作。比如你写事务的时间戳的值必须要大于最后一个读事务的时间戳值,这样表明已经没人在读此对象了,你才可以进行操作。


    参考文献:<<Distributed Sysytems Concepts And Design>>原版第五版,author:George Coulouris,Jean Dollimore, Tim Kindberg,Gordon Blair

  • 相关阅读:
    Django学习:博客分类统计(14)
    Django学习:上下篇博客和按日期分类(13)
    Django学习:分页优化(12)
    Django学习:shell命令行模式以及分页(11)
    Django学习:博客页面的响应式布局(10)
    Django学习:响应式导航条(9)
    八、Django学习:使用css美化页面
    七、Django学习:模板嵌套
    js日期使用总结
    Vue 的数据劫持 + 发布订阅
  • 原文地址:https://www.cnblogs.com/bianqi/p/12184049.html
Copyright © 2011-2022 走看看