首先看看道友提出的一个问题:
用户甲的操作
1.开始事务
2.访问表A
3.访问表B
4.提交事务
乙用户在操作
1.开始事务
2.访问表B
3.访问表A
4.提交事务

如果甲用户和乙用户的两个事务同时发生,甲事务锁住了表A未释放(因为整个事务未完成),正在准备访问B表,而乙事务锁住了表B未释放(因为整个事务未完成),正在准备访问A表,可是A表被甲事务锁住了,等甲事务释放,而甲事务真正等待乙事务释放B表,陷入了无限等待,也就是死锁Dead Lock。

也有道友使用多线程来模拟存储过程:http://www.jdon.com/45727,每个线程里开启一个事务,类似上述问题也会出现死锁。

问题出在哪里?

是我们的思路方向出现问题:

其实无论是使用数据库锁 还是多线程,这里有一个共同思路,就是将数据喂给线程,就如同计算机是一套加工流水线,数据作为原材料投入这个流水线的开始,流水线出来后就是成品,这套模式的前提是数据是被动的,自身不复杂,没有自身业务逻辑要求。适合大数据处理或互联网网站应用等等。

但是如果数据自身要求有严格的一致性,也就是事务机制,数据就不能被动被加工,要让数据自己有行为能力保护实现自己的一致性,就像孩子小的时候可以任由爸妈怎么照顾关心都可以,但是如果孩子长大有自己的思想和要求,他就可能不喜欢被爸妈照顾,他要求自己通过行动实现自己的要求。

数据也是如此。

只有我们改变思路,让数据自己有行为维护自己的一致性,才能真正安全实现真正的事务。

数据+行为=对象,有人问了,对象不是也要被线程调用吗?

例如下述代码,因为对象的行为要被线程调用,我们要使用同步锁synchronized :

public class A { private volatile int lower, upper; //两个状态值public int getLower() { return lower; } public int getUpper() { return upper; }public synchronized void setAUpper(int value){if (value < a.getUpper()) a.setLower(value);}public asynchronization void setALower(int value){if (value > a.getLower()) a.setUpper(value);}}

上面这段代码业务逻辑是想实现lower<upper:

1. lower和upper的初始值是(0, 5),
2.一个客户端请求线程A: setLower(4) 
一个客户端请求线程B: setUpper(3) 
3. lower和upper是 (4, 3)

这个结果破坏了lower<upper这个逻辑一致性,所以,用锁并不能保证逻辑一致性,而且还带来了堵塞。锁用错了地方,不但没有得到想要的,而且还失去更多。

下图展示了锁带来堵塞,每个时刻只能允许一个线程工作,如同只能允许一个人蹲马桶一样。

从历史上看,锁的问题如鬼魂一直伴随着我们:
1.用数据表一个字段来表示状态,比如1表示已付款未发货,2表示已付款已发货,然后用户来一个请求用SQL或存储过程修改,这时使用的数据库锁。

2.用ORM实现,比如Hibernate JPA来修改状态,虽然不用SQL了,但是Hibernate的悲观锁和乐观锁也让人抓狂。

3.彻底抛弃数据库,直接在内存缓存中进行修改,使用Java的同步锁,性能还是不够,吞吐量上不去。如上图提示,只能一个厕所蹲位一个人用,其他人必须排队。

4.Actor模型。

Actor模型原理
Actor模型=数据+行为+消息。

Actor模型内部的状态由自己的行为维护,外部线程不能直接调用对象的行为,必须通过消息才能激发行为,这样就保证Actor内部数据只有被自己修改。

Actor模型如何实现?

Scala或ErLang的进程信箱都是一种Actor模型,也有Java的专门的Actor模型,这里是几种Actor模型比较

明白了Actor模型原理,使用Disruptor这样无锁队列也可以自己实现Actor模型,让一个普通对象与外界的交互调用通过Disruptor消息队列实现,比如LMAX架构就是这样实现高频交易,从2009年成功运行至今,被Martin Fowler推崇。

回到本帖最初问题,如何使用Actor模型解决高并发事务呢?

转账是典型的符合该问题的案例,转账是将A帐号到B帐号转账,使用Actor模型解决如下:

发出是否可转出消息--->消息队列--->A

A作为一个对象,注意不是数据表,对象是有行为的,检查自己余额是否可转账,如果可以,冻结这部分金额,比如转账100元,冻结100元,从余额中扣除。因为外部命令是通过消息顺序进来的,所以下一个消息如果也是扣除,再次检查余额是否足够......

具体详细流程可见:REST和DDD

那么,既然Actor模型如此巧妙,而解决方向与我们习惯的数据喂机器的方式如此不同,那么如何在实战中能明显发现某个数据修改应该用Actor模型解决呢?因为我们习惯将数据喂机器的思路啊?

使用DDD领域驱动设计或CQRS架构就能明显发现这些特殊情况,CQRS是读写分离,其中写操作是应领域专家要求编写的功能,在这类方向,我们都有必要使用Actor模型实现,因为在这个方向上,领域专家的要求都表达为聚合根实体,聚合根就是用Actor模型实现最合适不过了。而读方向,比如大数据处理,报表查询,OLTP等等都是数据喂机器的方式。

有的道友会疑问,我们经常使用SSH,也就是Spring + Hibernate架构,这个默认是哪种方向呢?很显然,默认是数据喂机器的方向,所以在实现写操作时,特别警惕高并发发生死锁等影响性能问题,当然也包括EJB架构。

有一种togaf架构,将企业软件架构分为数据架构和应用架构等,实际是EJB或SSH的变相描述,这种架构的问题我们已经一目了然了,特别这样的系统如果从面向内部管理转向到SaaS模型时,这类高并发死锁问题就特别容易发生,几乎不具备可用性。前期12306火车票系统是这类问题的典型体现。

为什么Actor模型是高并发事务的终极解决方案?相关推荐

  1. 高并发事务问题以及解决方案

    事务的概念 事务 可以理解为一个 独立的工作单元, 在这个独立的工作单元中, 有一组操作; 放在事务(独立工作单元)中的多个操作, 要么全部执行成功, 要么全部执行失败. 不免俗套, 这还是通过最经典 ...

  2. MySQL高并发事务问题

    事务的概念 事务 可以理解为一个 独立的工作单元, 在这个独立的工作单元中, 有一组操作; 放在事务(独立工作单元)中的多个操作, 要么全部执行成功, 要么全部执行失败. 不免俗套, 这还是通过最经典 ...

  3. java actor模型实例,详解Theron通过Actor模型解决C++并发编程的一种思维

    现今,单台机器拥有多个独立的计算单元已经太常见了,这点在服务器的处理器上表现尤为明显,据AMD的一张2012-2013服务器路线图显示,服务器处理器的核心数将在2013年达到20颗之多,合理的利用CP ...

  4. MySQL - 并发事务问题及解决方案

    文章目录 生猛干货 Pre 脏读 不可重复读 幻读 Solutions 搞定MySQL 生猛干货 带你搞定MySQL实战,轻松对应海量业务处理及高并发需求,从容应对大场面试 Pre MySQL - 多 ...

  5. 高并发系统设计——分布式锁解决方案

    摘要 分布式应用进行逻辑处理时经常会遇到并发问题.比如一个操作要修改用户的状态,修改状态需要先读出用户的状态, 在内存里进行修改,改完了再存回去.如果这样的操作同时进行了,就会出现并发问题, 因为读取 ...

  6. 海量数据高并发的访问技术解决方案

    如今数据增长远远超过机器的计算性能,    ORACL RAC能满足百万千万的业务系统,  硬件成本太高, 垂直方向的发展不太现实,追求水平方向的发展, 使用普通商业服务器,多台协调完成计算 如今,能 ...

  7. mysql高并发和大流量_高并发-高并发和大流量解决方案

    高并发架构相关概念 并发 并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,并且这几个程序都是在同一个处理机上运行,担任一个时刻点上只有一个程序在处理机上运行. 我们所说的 ...

  8. 高并发和大流量解决方案

    #高并发架构相关概念# 并发: 在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任意一个时刻上只有一个程序在处理机上运行. 我们说的高并 ...

  9. 高并发与大流量解决方案

    1.相关概念 1.1.并发与并行 1.1.1.并发(Concurrent) 在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行 就想前面提到的 ...

最新文章

  1. 03-NSPredicate谓词
  2. 施工日志管理软件app_康智颐app下载-康智颐客户端下载v1.4.9 安卓官方版
  3. 来看看几篇Nature上的GNN吧~
  4. hdu 1046 完数
  5. 旅游自助系统可行性分析
  6. 四面体的表面积_JACS:武汉大学汪成课题组利用从平面至四面体的扭曲单体来合成COFs材料...
  7. python交互式和文件式_使用Python创建和自动化交互式仪表盘
  8. CentOS7.4中搭建lnmp环境
  9. 整数倒转问题的算法实现
  10. Tensorflow学习笔记-第二节程序结构
  11. Hadoop作业性能指标及參数调优实例 (二)Hadoop作业性能调优7个建议
  12. 详细解说“黑客”们热衷的热门抓鸡技术
  13. 邻接表拓扑排序算法【C/C++】
  14. 读养生四要有感《慎动篇》
  15. 手把手教你如何在Innovus中解决local congestion问题
  16. 下单后,订单拆单能怎拆?
  17. E-Prime2.0安装问题
  18. java毕业生设计忆居民宿管理计算机源码+系统+mysql+调试部署+lw
  19. 无线传感网的MAC层协议
  20. 使用R语言对S&P500股票指数进行ARIMA + GARCH交易策略

热门文章

  1. 基于java的搜索引擎系统设计与实现(项目报告+开题报告+答辩PPT+源代码+数据库+部署视频)
  2. Node.js毕业设计——基于Node.js+JavaScript+MongoDB的供求信息网站设计与实现(毕业论文+程序源码)——供求信息网站
  3. 二进制与八进制十进制十六进制之间的转换
  4. OpenCvSharp 学习笔记7 --绘制图形和文字
  5. pwnable 题目解析:[Toddler's Bottle]-lotto 逻辑漏洞
  6. 利用有限元法求解一维热传导问题
  7. 恶魔之魂重制版登陆服务器未响应,数毛社分析《恶魔之魂:重制版》 60帧运行,加载超快...
  8. win8默认使用IE浏览器打开QQ空间,通过如下设置可以更改浏览器
  9. Linux目录结构——树形目录结构
  10. 抽象类和接口有什么区别