先看看io模型
Reactor模型:
1 向事件分發器注冊事件回調
2 事件發生
4 事件分發器調用之前注冊的函數
4 在回調函數中讀取數據,對數據進行后續處理
Reactor模型實例:libevent,Redis、ACE
Proactor模型:
1 向事件分發器注冊事件回調
2 事件發生
3 操作系統讀取數據,並放入應用緩沖區,然后通知事件分發器
4 事件分發器調用之前注冊的函數
5 在回調函數中對數據進行后續處理
Preactor模型實例:ASIO
reactor和proactor的主要區別:
主動和被動
以主動寫為例:
Reactor將handle放到select(),等待可寫就緒,然后調用write()寫入數據;寫完處理后續邏輯;
Proactor調用aoi_write后立刻返回,由內核負責寫操作,寫完后調用相應的回調函數處理后續邏輯;
可以看出,Reactor被動的等待指示事件的到來並做出反應;它有一個等待的過程,做什么都要先放入到監聽事件集合中等待handler可用時再進行操作;
Proactor直接調用異步讀寫操作,調用完后立刻返回;
實現
Reactor實現了一個被動的事件分離和分發模型,服務等待請求事件的到來,再通過不受間斷的同步處理事件,從而做出反應;
Proactor實現了一個主動的事件分離和分發模型;這種設計允許多個任務並發的執行,從而提高吞吐量;並可執行耗時長的任務(各個任務間互不影響)
優點
Reactor實現相對簡單,對於耗時短的處理場景處理高效;
操作系統可以在多個事件源上等待,並且避免了多線程編程相關的性能開銷和編程復雜性;
事件的串行化對應用是透明的,可以順序的同步執行而不需要加鎖;
事務分離:將與應用無關的多路分解和分配機制和與應用相關的回調函數分離開來,
Proactor性能更高,能夠處理耗時長的並發場景;
缺點
Reactor處理耗時長的操作會造成事件分發的阻塞,影響到后續事件的處理;
Proactor實現邏輯復雜;依賴操作系統對異步的支持,目前實現了純異步操作的操作系統少,實現優秀的如windows IOCP,但由於其windows系統用於服務器的局限性,目前應用范圍較小;而Unix/Linux系統對純異步的支持有限,應用事件驅動的主流還是通過select/epoll來實現;
適用場景
Reactor:同時接收多個服務請求,並且依次同步的處理它們的事件驅動程序;
Proactor:異步接收和同時處理多個服務請求的事件驅動程序;
再說Actor模型:
Actor模型被稱為高並發事務的終極解決方案,
實體之通過消息通訊,各自處理自己的數據,能夠實現這並行。
actor模型實例:skynet,Erlang
Actor模型是一個概念模型,用於處理並發計算。它定義了一系列系統組件應該如何動作和交互的通用規則,最著名的使用這套規則的編程語言是Erlang。
一個Actor指的是一個最基本的計算單元。它能接收一個消息並且基於其執行計算。
這個理念很像面向對象語言,一個對象接收一條消息(方法調用),然后根據接收的消息做事(調用了哪個方法)。
Actors一大重要特征在於actors之間相互隔離,它們並不互相共享內存。這點區別於上述的對象。也就是說,一個actor能維持一個私有的狀態,並且這個狀態不可能被另一個actor所改變。
思路方向:
其實無論是使用數據庫鎖 還是多線程,這里有一個共同思路,就是將數據喂給線程,就如同計算機是一套加工流水線,數據作為原材料投入這個流水線的開始,流水線出來后就是成品,這套模式的前提是數據是被動的,自身不復雜,沒有自身業務邏輯要求。適合大數據處理或互聯網網站應用等等。
但是如果數據自身要求有嚴格的一致性,也就是事務機制,數據就不能被動被加工,要讓數據自己有行為能力保護實現自己的一致性,就像孩子小的時候可以任由爸媽怎么照顧關心都可以,但是如果孩子長大有自己的思想和要求,他就可能不喜歡被爸媽照顧,他要求自己通過行動實現自己的要求。
數據也是如此。
只有我們改變思路,讓數據自己有行為維護自己的一致性,才能真正安全實現真正的事務。
我們可以看到
Actor模型=數據+行為+消息。
Actor模型內部的狀態由自己的行為維護,外部線程不能直接調用對象的行為,必須通過消息才能激發行為,這樣就保證Actor內部數據只有被自己修改。
參考:
reactor和proactor模式(epoll和iocp)