Actor模型淺析 一致性和隔離性

一.Actor模型介紹

在單核 CPU 發展已經達到一個瓶頸的今天,要增長硬件的速度更多的是增長 CPU 核的數目。而針對這種狀況,要使咱們的程序運行效率提升,那麼也應該從併發方面入手。傳統的多線程方法又極其容易出現 Bug 而難以維護,不過別擔憂,今天將要介紹另外一種併發的模式能必定程度解決這些問題,那就是 Actor 模型。html

Actor 模型其實就是定義一組規則,這些規則規定了一組系統中各個模塊如何交互及迴應。在一個 Actor 系統中,Actor 是最小的單元模塊,系統由多個 Actor 組成。每一個 Actor 有兩個東西,一個是 mailbox,一個是自身狀態。同時 Actor 有接收和發送的功能。下面代碼給出一個大概的 Actor 樣例:算法

trait Actor {
  //持有一個表示自身狀態的私有變量
  val state:Integer = 0;
  //持有一個mailbox 的隊列
  val mailBox:mutable.Queue[Message] = scala.collection.mutable.Queue[Message]()
  def send(message : Message): Unit ={
      ...
  }
  def recive(): Unit ={
      ...
  }
}

當一個 Actor 接收到消息後,它會執行下面三種操做中的一種:編程

  • 建立其餘 Actor。
  • 向其餘 Actor 發送消息。
  • 修改自身狀態。
    須要注意的是,儘管許多 Actor 同時運行,可是一個actor只能順序地處理消息。也就是說其它 Actor 發送了三條消息給一個 Actor ,這個 Actor 只能一次處理一條。因此若是你要並行處理3條消息,你須要把這條消息發給3個actors。

下面這張圖展現了一個簡單的 Actor 模型系統:多線程

瞭解了 Actor 模型的大概規則後,咱們用兩個具體的例子來看看 Actor 模型的妙處以及不足吧。併發

二. 兩個例子

2.1 素數計算

假設咱們如今有一個任務,須要找出100000之內素數個數,而且使用多線程的方式實現。oop

下圖展現了使用共享內存的方式和以Actor模型的方式進行併發執行。
Actor 素數計算性能

這裏展現了兩種處理併發的不一樣思路,傳統的方式是經過鎖/同步的方式來實現併發,每次同步獲取當前值,並讓一個線程去判斷值是否爲素數,是的話再經過同步的方式對計數器加1(這裏的說明只是做爲提供思路用,這種方法天然有很大的優化空間)。大數據

而使用 Actor 模型則不同,它將這一過程拆分紅幾個模塊,即拆分紅幾個 Actor 。每一個 Actor 負責不一樣的部分,經過消息傳遞的方式讓這幾個 Actor 協同工做,而且其中涉及到主要計算的 Actor 能夠有多個,經過多個 Actor 協同工做實現併發。優化

2.2 銀行轉帳

銀行轉帳的任務描述很簡單,假設有兩個用戶,如今用戶A向用戶B轉帳100元,這個 Actor 模型該如何設計呢?線程

用戶 A 和 用戶 B 明顯是兩個 Actor ,但咱們同時還須要一個能夠控制用戶A Actor 和用戶B Actor 的 Actor ,咱們稱之爲 轉帳管家 Actor。那麼流程圖以下。
Actor 銀行轉帳

能夠看到,當一個轉帳需求過來的時候,Actor 管家會先向 用戶A Actor 發送扣款 100 元的信息,接受到扣款成功消息後再發送消息給用戶B Actor,發送讓其增長 100 元的消息。

一切看起來都很美好是吧,但這裏面有一個問題,那就是在用戶A Actor 扣款期間,用戶B Actor 是不受限制的,此時對用戶B Actor 進行操做是合法的!針對這種狀況單純的Actor模型就顯得比較乏力了,須要加入其餘機制以保證一致性。

看到這你就明白了,Actor 模型並不是萬能的,它有必定的缺點。那就是針對一致性要求比較強的場景比較乏力。

三. 爲何會出現 Actor 模型

接下來咱們來聊聊爲何會有 Actor 模型這種併發編程模型出現。

咱們須要先說說併發性中的一致性隔離性

一致性即讓數據保持一致,好比銀行轉帳例子中,用戶A 轉給 用戶B 100塊錢,沒有其餘干擾的狀況下,轉帳完成時。用戶A 的帳戶必然減小 100 元,用戶B 的帳戶必然增長100 元,這就知足了一致性。不能說用戶A 減小50 或用戶B 增長了 200。

隔離性能夠理解爲犧牲一部分的一致性需求,而得到性能的提升。打個比方,在徹底一致的狀況下,任務都是串行的,這時候也就不存在隔離性了。

明白這些以後,你就直到爲何會有 Actor 模型了。

傳統併發模式,共享內存是傾向於強一致性弱隔離性的。好比悲觀鎖/同步的方式,其實就是使用強一致性的方式控制併發。而 Actor 模型自然是強隔離性且弱一致性,因此 Actor 模型在併發中有良好的性能,且易於控制和管理。

這樣你就明白 Actor 模型適合於什麼樣的併發場景了,當對一致性需求不是很高的狀況下且對性能需求較高時,Actor 模型無疑是一個值得嘗試的方案。


推薦閱讀 :
從分治算法到 MapReduce
Actor併發編程模型淺析
大數據存儲的進化史 --從 RAID 到 Hadoop Hdfs

相關文章
相關標籤/搜索