高并发分布式事务解决之道-Actor模型

原文:

https://blog.csdn.net/textboy/article/details/51163452 

http://janeky.iteye.com/blog/1504125

简述

Actor模型在并发编程中是比较常见的一种模型。很多开发语言都提供了原生的Actor模型。例如erlang,scala等


 

 

Actor,可以看作是一个个独立的实体,他们之间是毫无关联的。但是,他们可以通过消息来通信。一个Actor收到其他Actor的信息后,它可以根据需要作出各种相应。消息的类型可以是任意的,消息的内容也可以是任意的。这点有点像webservice了。只提供接口服务,你不必了解我是如何实现的。

 

一个Actor如何处理多个Actor的请求呢?它先建立一个消息队列,每次收到消息后,就放入队列,而它每次也从队列中取出消息体来处理。通常我们都使得这个过程是循环的。让Actor可以时刻处理发送来的消息。

 

以Erlang为例子,介绍一下简单的Actor模型

 

1.首先建立一个Actor,在erlang中,起一个进程(这个是erlang虚拟机进程,跟os进程不同),这个进程就是actor了,可以用来接收和发送各种消息了

 

Pid = spawn(Mod,func,Args) %起一个进程

 

2.处理收到的消息

func()->

    receive

{From,Msg}-> %收到一个消息

%%do something

func();

 

3.要对这个actor发送消息,也非常简单

Pid ! {From,Msg}

 

总结:

Actor模型在并发编程中已经得到广泛应用。Java虽然还提供直接的支持,但是一些开源组织已经提供相关的jar包来模拟实现Actor模型,例如:

ActiveJava 等,有兴趣的同学可以去了解一下源码

  

Actor模型

(1) 事务机制来由

为什么大多数互联网软件都是数据喂机器,或函数式即可,比如twitter或facebook,因为他们没有事务要求,一般涉及到钱等重要交易都需要事务,也可以这么说,非结构化的数据一般都没有事务要求,结构化聚合的数据才有事务要求。

(2) 事务例子

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

(3) 高并发事务解决之道

悲观锁 - 数据库表锁或行锁
乐观锁 - 版本控制
同步锁 - 单线程
Actor模型 - 行为消息队列(适用跨节点、分布式、高并发)
* 同步锁是单一JVM内的,对于分布式系统多个 Tomcat容器多个JVM,Actor模型能更好地“锁”好资源。
(4) Actor模型
Actor模型内部的状态由自己的行为维护,外部线程不能直接调用对象的行为,必须通过消息才能激发行为,这样就保证Actor内部数据只有被自己修改。
一个Actor如何处理多个Actor的请求呢?它先建立一个消息队列,每次收到消息后,就放入队列,而它每次也从队列中取出消息体来处理。通常我们都使得这个过程是循环的。让Actor可以时刻处理发送来的消息。

Actor模型解决“一个人一个坑”的性能瓶颈  

 Akka与Reactor比较

两者皆是异步事件驱动框架,都构建自Actor模型;
Akka用 Scala 编写的库,目前更成熟,同时支持Scala和Java API;
Reactor项目始于2012年,由Spring团队研发,但现在还常常大改。
Akka:
http://akka.io
Java代码Sample: http://verran.iteye.com/blog/1942393,
http://www.blogbus.com/dreamhead-logs/235916459.html,
http://www.th7.cn/Program/java/2012/03/29/67015.shtml,
https://github.com/XiaoMi/rose/tree/master/rose-example/src/main/java/sample
Sample
HelloWorld.java
public class HelloWorld extends UntypedActor { @Override public void preStart() { final ActorRef greeter = getContext().actorOf(Props.create(Greeter.class), "greeter"); greeter.tell(Greeter.Msg.GREET, getSelf()); } @Override public void onReceive(Object msg) { if (msg == Greeter.Msg.DONE) { getContext().stop(getSelf()); } else { unhandled(msg); } }}
Greeter.java

import akka.actor.UntypedActor; public class Greeter extends UntypedActor { public static enum Msg { GREET, DONE } @Override public void onReceive(Object msg) { if (msg == Msg.GREET) { System.out.println("Hello World!"); getSender().tell(Msg.DONE, getSelf()); } else { unhandled(msg); } }}
Reactor:
http://projectreactor.io/old/reference/
https://github.com/reactor/reactor
架构
v.s.
http://stackoverflow.com/questions/16595393/akka-or-reactor
---------------------

参考:http://www.jdon.com/45728

http://en.wikipedia.org/wiki/Actor_model

posted @ 2019-01-26 09:30  读喜爱  阅读(767)  评论(0编辑  收藏  举报