Elixir Part2 : Actor Model 与多核服务器

1. 前言

上一篇文章简单说了一下关于 OOP 在多核环境下的一些开发问题,文章最后引出了 Actor Model 是解决这些问题的一个方法。你们能够经过如下连接查看系列文章:html

1.Elixir Para1: OOP 的局限 git

这篇文章就重点讲解一下,什么是 Actor Model,以及为何 Actor Model 会在目前的多核服务器环境中从新被重视。github

2. 什么是 Actor Model

Actor Model 在 wiki 上的定义是这样的:算法

The actor model in computer science is a mathematical model of concurrent computation that treats actor as the universal primitive of concurrent computation编程

Actor Model 在计算机科学里是一种并行的计算模型,actor 表示一个计算单元。缓存

这样说,可能有点难理解。但事实上,Actor Model 是更加接近咱们所熟悉的世界的。不妨以下想象:安全

  1. 现实世界里的每一个个体,其实都是独立且自驱动的;
  2. 个体都会根据自身的状况,去响应外界的消息(message);
  3. 个体能够建立新的不一样的个体(create)
  4. 个体会经过发送消息到其余个体,进行协做;

2.1 举例子1

在上述的几个规则下,咱们就能够构建一整个业务的解决方案了。咱们设想一个需求:设游戏场景中存在 100 个怪物,他们可以自主进行攻击,也能够被攻击。服务器

采用 OOP 的设计方法,可能会有以下步骤:markdown

  1. 设计一个怪物类,定义他们的方法:attack,beAttack,定义 state,如:hp;
  2. 因为考虑到会有同时攻击,因此这些方法还得是线程安全的,所以都有锁;
  3. 实例化 100 个对象;
  4. 使用线程池对这些对象进行心跳,使之有自主能力;

这样的步骤虽然可以实现功能,但相比之下仍是比较别扭,不够天然。Actor Model 在这种场景下就会显得很是有优点,由于 Actor Model 自己就是自驱动,拥有本身的状态,可以经过消息与外界通讯。因此咱们只须要定义 Actor 的 state 和两个 behavior,剩余就交给怪物本身去运行了。网络

线程池驱动:

image.png

Actor Model:

image.png

2.2 举例子2

上述的例子是一个游戏例子,这个确实比较适合 Actor Model。如今咱们思考一个交易系统,关于里面的用户互相转帐的业务。

采用以往的设计方法,通常会有如下步骤:

  1. 设计用户账号表;
  2. A向B用户转帐,则先为 A、B 上锁,判断 A 金额,完成金额转帐,解锁;
  3. 考虑到用户量比较巨大,咱们可能会使用集群部署这个功能,因此 step 2 的锁会适用分布式锁;

这样其实也不错,但咱们能够尝试适用 Actor Model 来设计这个转帐系统,在设计这个系统前。咱们须要想象一个属于本身帐号“管家”,他知悉个人金额,并每次只会处理一次交易;

适用 Actor Model,咱们的设计以下:

  1. 设计用户账号表;
  2. 消息通知 管家A 向 管家B 转账,管家A 处理自行判断且扣钱,而后向 管家B 发送一条加钱的消息,管家B 处理该消息,完成转帐。因为管家只会串行处理,因此不须要锁;
  3. 管家 A 和 管家B 在部署上只须要可以通讯便可,故是否集群是不须要考虑的;

在这里例子上,这并非说 Actor Model 就更加适合转帐系统,只是向引导你们思考,咱们平时设计的需求,其实换一个想法去作也是能够的,若是这个想法更贴合咱们现实世界,咱们会很是容易理解。(我在学习 lock 这个概念的时候就花了很多时间)

2.3 小结

简单小结一下 Actor Model。Actor Model 是一种并发模型,它的思想在于:一切皆演员。在舞台上,每一个演员是自我驱动的,根据外界的消息,共同协做完成一次次业务上的表演。

一个 Actor 包含如下几个要素:

  1. state 状态
  2. mailbox 邮箱
  3. address 地址
  4. behavior 行为

而用于通讯的,咱们统一适用 message 消息这个抽象。

image.png

3. Actor Model 的优劣

3.1 优点

  1. 易扩展
  2. 容错性
  3. 分布式
  4. 状态无共享

简单解释一下:

  1. 系统须要增长功能时,能够为对应的 Actor 增长 behavior,或者能够直接新增新的 Actor。就像你的公司须要新增业务线,咱们能够直接构建一个部门的组织架构来负责该类工做;
  2. 要解释容错性,还须要使用到监督树的概念。简单来讲,就是为不一样的业务具有多个 Actor,假如一个 Actor 被破坏了,还能用另一个 Actor 代替工做(计算机的冗余原则);
  3. 在咱们讨论 Actor Model 时,咱们都不须要定义 Actor 是存活在哪一个物理主机上,只有他们处于同一个网络,而且知道彼此的 address,就能够通讯了;
  4. 因为数据都是 Actor 本身拥有的,只有经过 message 才能对数据进行访问,因此状态无共享,天然不会有竞争问题;

3.2 劣势

  1. 死锁
  2. mailbox 溢出

Actor 模型是会容易出现死锁的。假如 A 发送消息给 B,B 发送消息给 A,同时彼此在等待回信。就会产生死锁了。

mailbox 是用于通讯的不得不存在的概念,在消息量巨大的时候,mailbox 可能会成为瓶颈。

我认为,缺乏共享内存,必定程度仍是影响性能的。例如一些读多写少的业务上,共享内存是会让性能更加好的。

3.3 多核时代和 Actor Model

最近些年,单核 CPU 的性能物理上限基本上已经达到了,接下来 CPU 的计算能力要进一步提高,只能往多核维度上去发展。如今不少云供应商都提供了多核、大内存的服务器。

咱们知道,多核 CPU 在存储金字塔上,也是存在必定问题的。由于 CPU 有本身的 L一、L二、L3 缓存,在共享内存的环境下,多核 CPU 须要经过一致性算法保证缓存的可见性,这必定程度上是影响性能的,并且这个问题还会由于核数越多,影响越大。

但 Actor Model 自然就会适应这种多核服务器。举 Erlang 的虚拟机为例子,Erlang 的虚拟机就是根据系统的核数定义调度器数量,并且调度器还能自行根据内存局部性,来提升运行的性能。

image.png

4. Actor Model 的编程语言和框架

  1. Erlang/Elixir
  2. Akka

5. 引用

  1. Elang 运行时系统#并发、并行,抢占式多任务
  2. How the Actor Model Meets the Needs of Modern, Distributed Systems
  3. Youtube Actor Model Explained

6. 预告

但愿你们在读完文章后,还能对 Actor Model 产生一些兴趣。有了这些基础,下一篇文章就能够开始尝试正式介绍 Elixir 语言了。喜欢的同窗能够点个赞,有疑问能够留言一块儿讨论一下,说得不对的地方,也但愿诸位大方斧正。

相关文章
相关标签/搜索