自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

分布式高并發(fā)下Actor模型如此優(yōu)秀

開發(fā) 前端 分布式
一般來說有兩種策略用來在并發(fā)線程中進行通信:共享數(shù)據(jù)和消息傳遞。使用共享數(shù)據(jù)方式的并發(fā)編程面臨的最大的一個問題就是數(shù)據(jù)條件競爭。處理各種鎖的問題是讓人十分頭痛的一件事。

寫在開始

一般來說有兩種策略用來在并發(fā)線程中進行通信:共享數(shù)據(jù)和消息傳遞。使用共享數(shù)據(jù)方式的并發(fā)編程面臨的最大的一個問題就是數(shù)據(jù)條件競爭。處理各種鎖的問題是讓人十分頭痛的一件事。

傳統(tǒng)多數(shù)流行的語言并發(fā)是基于多線程之間的共享內(nèi)存,使用同步方法防止寫爭奪,Actors使用消息模型,每個Actor在同一時間處理最多一個消息,可以發(fā)送消息給其他Actor,保證了單獨寫原則。從而巧妙避免了多線程寫爭奪。和共享數(shù)據(jù)方式相比,消息傳遞機制最大的優(yōu)點就是不會產(chǎn)生數(shù)據(jù)競爭狀態(tài)。實現(xiàn)消息傳遞有兩種常見的類型:基于channel(golang為典型代表)的消息傳遞和基于Actor(erlang為代表)的消息傳遞。

Actor簡介

Actor模型=數(shù)據(jù)+行為+消息。

Actor模型是一個通用的并發(fā)編程模型,而非某個語言或框架所有,幾乎可以用在任何一門編程語言中,其中最典型的是erlang,在語言層面就提供了Actor模型的支持,殺手锏應用RabbitMQ 就是基于erlang開發(fā)的。

更加面向?qū)ο?/strong>

Actor類似面向?qū)ο缶幊蹋∣O)中的對象,每個Actor實例封裝了自己相關(guān)的狀態(tài),并且和其他Actor處于物理隔離狀態(tài)。舉個游戲玩家的例子,每個玩家在Actor系統(tǒng)中是Player 這個Actor的一個實例,每個player都有自己的屬性,比如Id,昵稱,攻擊力等,體現(xiàn)到代碼級別其實和我們OO的代碼并無多大區(qū)別,在系統(tǒng)內(nèi)存級別也是出現(xiàn)了多個OO的實例

  1. class PlayerActor 
  2.     {        public int Id { get; set; } 
  3.         public string Name { get; set; } 
  4.     } 

無鎖

在使用Java/C# 等語言進行并發(fā)編程時需要特別的關(guān)注鎖和內(nèi)存原子性等一系列線程問題,而Actor模型內(nèi)部的狀態(tài)由它自己維護即它內(nèi)部數(shù)據(jù)只能由它自己修改(通過消息傳遞來進行狀態(tài)修改),所以使用Actors模型進行并發(fā)編程可以很好地避免這些問題。Actor內(nèi)部是以單線程的模式來執(zhí)行的,類似于redis,所以Actor完全可以實現(xiàn)分布式鎖類似的應用。

異步

每個Actor都有一個專用的MailBox來接收消息,這也是Actor實現(xiàn)異步的基礎(chǔ)。當一個Actor實例向另外一個Actor發(fā)消息的時候,并非直接調(diào)用Actor的方法,而是把消息傳遞到對應的MailBox里,就好像郵遞員,并不是把郵件直接送到收信人手里,而是放進每家的郵箱,這樣郵遞員就可以快速的進行下一項工作。所以在Actor系統(tǒng)里,Actor發(fā)送一條消息是非??斓?。

分布式高并發(fā)下Actor模型如此優(yōu)秀

這樣的設(shè)計主要優(yōu)勢就是解耦了Actor,數(shù)萬個Actor并發(fā)的運行,每個actor都以自己的步調(diào)運行,且發(fā)送消息,接收消息都不會被阻塞。

隔離

每個Actor的實例都維護這自己的狀態(tài),與其他Actor實例處于物理隔離狀態(tài),并非像 多線程+鎖 模式那樣基于共享數(shù)據(jù)。Actor通過消息的模式與其他Actor進行通信,與OO式的消息傳遞方式不同,Actor之間消息的傳遞是真正物理上的消息傳遞。

天生分布式

每個Actor實例的位置透明,無論Actor地址是在本地還是在遠程機器上對于代碼來說都是一樣的。每個Actor的實例非常小,最多幾百字節(jié),所以單機幾十萬的Actor的實例很輕松。如果你寫過golang代碼,就會發(fā)現(xiàn)其實Actor在重量級上很像Goroutine。由于位置透明性,所以Actor系統(tǒng)可以隨意的橫向擴展來應對并發(fā),對于調(diào)用者來說,調(diào)用的Actor的位置就在本地,當然這也得益于Actor系統(tǒng)強大的路由系統(tǒng)。

分布式高并發(fā)下Actor模型如此優(yōu)秀

生命周期

每個Actor實例都有自己的生命周期,就像C# java 中的GC機制一樣,對于需要淘汰的Actor,系統(tǒng)會銷毀然后釋放內(nèi)存等資源來保證系統(tǒng)的持續(xù)性。其實在Actor系統(tǒng)中,Actor的銷毀完全可以手動干預,或者做到系統(tǒng)自動化銷毀。

容錯

說到Actor的容錯,不得不說還是挺令人意外的。傳統(tǒng)的編程方式都是在將來可能出現(xiàn)異常的地方去捕獲異常來保證系統(tǒng)的穩(wěn)定性,這就是所謂的防御式編程。但是防御式編程也有自己的缺點,類似于現(xiàn)實,防御的一方永遠不能100%的防御住所有將來可能出現(xiàn)代碼缺陷的地方。比如在java代碼中很多地方充斥著判斷變量是否為nil,這些就屬于防御式編碼最典型的案例。但是Actor模型的程序并不進行防御式編程,而是遵循“任其崩潰”的哲學,讓Actor的管理者們來處理這些崩潰問題。比如一個Actor崩潰之后,管理者可以選擇創(chuàng)建新的實例或者記錄日志。每個Actor的崩潰或者異常信息都可以反饋到管理者那里,這就保證了Actor系統(tǒng)在管理每個Actor實例的靈活性。

劣勢

天下無完美的語言,框架/模型亦是如此。Actor作為分布式下并發(fā)模型的一種,也有其劣勢。

  1. 由于同一類型的Actor對象是分散在多個宿主之中,所以取多個Actor的集合是個軟肋。比如在電商系統(tǒng)中,商品作為一類Actor,查詢一個商品的列表在多數(shù)情況下經(jīng)過以下過程:首先根據(jù)查詢條件篩選出一系列商品id,根據(jù)商品id分別取商品Actor列表(很可能會產(chǎn)生一個商品搜索的服務,無論是用es或者其他搜索引擎)。如果量非常大的話,有產(chǎn)生網(wǎng)絡(luò)風暴的危險(雖然幾率非常?。T趯崟r性要求不是太高的情況下,其實也可以獨立出來商品Actor的列表,利用MQ接收商品信息修改的信號來處理數(shù)據(jù)一致性的問題。
  2. 在很多情況下基于Actor模型的分布式系統(tǒng),緩存很有可能是進程內(nèi)緩存,也就是說每個Actor其實都在進程內(nèi)保存了自己的狀態(tài)信息,業(yè)內(nèi)通常把這種服務成為有狀態(tài)服務。但是每個Actor又有自己的生命周期,會產(chǎn)生問題嗎?呵呵,也許吧。想想一下,還是拿商品作為例子, 如果環(huán)境是非Actor并發(fā)模型,商品的緩存可以利用LRU策略來淘汰非活躍的商品緩存,來保證內(nèi)存不會使用過量,如果是基于Actor模型的進程內(nèi)緩存呢,每個actor其實就是緩存本身,就不那么容易利用LRU策略來保證內(nèi)存使用量了,因為Actor的活躍狀態(tài)對于你來說是未知的。
  3. 分布式事物問題,其實這是所有分布式模型都面臨的問題,非由于Actor而存在。還是以商品Actor為例,添加一個商品的時候,商品Actor和統(tǒng)計商品的Actor(很多情況下確實被設(shè)計為兩類Actor服務)需要保證事物的完整性,數(shù)據(jù)的一致性。在很多的情況下可以犧牲實時一致性用最終一致性來保證。
  4. 每個Actor的mailBox有可能會出現(xiàn)堆積或者滿的情況,當這種情況發(fā)生,新消息的處理方式是被拋棄還是等待呢,所以當設(shè)計一個Actor系統(tǒng)的時候mailBox的設(shè)計需要注意。

升華一下

  1. 通過以上介紹,既然Actor對于位置是透明的,任何Actor對于其他Actor就好像在本地一樣?;谶@個特性我們可以做很多事情了,以前傳統(tǒng)的分布式系統(tǒng),A服務器如果想和B服務器通信,要么RPC的調(diào)用(http調(diào)用不太常用),要么通過MQ系統(tǒng)。但是在Actor系統(tǒng)中,服務器之間的通信都變的很優(yōu)雅了,雖然本質(zhì)上也屬于RPC調(diào)用,但是對于編碼者來說就好像在調(diào)用本地函數(shù)一樣。其實現(xiàn)在比較時興的是Streaming方式。
  2. 由于Actor系統(tǒng)的執(zhí)行模型是單線程,并且異步,所以凡是有資源競爭的類似功能都非常適合Actor模型,比如秒殺活動。
  3. 基于以上的介紹,Actor模型在設(shè)計層面天生就支持了負載均衡,而且對于水平擴容支持的非常好。當然Actor的分布式系統(tǒng)也是需要服務注冊中心的。
  4. 雖然Actor是單線程執(zhí)行模型,并不意味著每個Actor都需要占用一個線程,其實Actor上執(zhí)行的任務就像Golang的goroutine一樣,完全可以是一個輕量級的東西,而且一個宿主上所有的Actor可以共享一個線程池,這就保證了在使用最少線程資源的情況下,最大量化業(yè)務代碼。

 

責任編輯:張燕妮 來源: 今日頭條
相關(guān)推薦

2017-12-12 14:51:15

分布式緩存設(shè)計

2020-10-13 07:44:45

理解分布式

2023-10-26 18:10:43

分布式并行技術(shù)系統(tǒng)

2019-09-25 09:01:53

高并發(fā)架構(gòu)分布式

2019-12-17 11:18:37

高并發(fā)分布式架構(gòu)

2024-10-08 11:21:11

2020-02-10 19:16:52

服務端高并發(fā)架構(gòu)

2013-01-30 10:12:24

NginxNginx優(yōu)化高并發(fā)

2014-08-08 13:30:44

Nginx

2022-01-10 19:45:40

微服務GO系統(tǒng)

2022-03-21 19:44:30

CitusPostgreSQ執(zhí)行器

2018-12-20 09:30:59

分布式高并發(fā)多線程

2022-03-07 08:14:27

并發(fā)分布式

2022-03-11 10:03:40

分布式鎖并發(fā)

2022-06-12 06:45:26

高并發(fā)防重

2025-02-20 00:01:00

2024-11-27 00:20:32

2021-02-01 09:35:53

關(guān)系型數(shù)據(jù)庫模型

2021-07-30 13:35:43

共享內(nèi)存 Actor

2019-10-10 09:16:34

Zookeeper架構(gòu)分布式
點贊
收藏

51CTO技術(shù)棧公眾號