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 語言了。喜歡的同窗能夠點個贊,有疑問能夠留言一塊兒討論一下,說得不對的地方,也但願諸位大方斧正。

相關文章
相關標籤/搜索