• <center id="ye0c0"><u id="ye0c0"></u></center>
  • <optgroup id="ye0c0"><acronym id="ye0c0"></acronym></optgroup>
  • 如何理解Stream processing, Event sourcing, Reactive, CEP?

      流處理Stream processing, 事件溯源Event sourcing, 響應式Reactive, 復雜事件處理CEP, CQRS等等這些概念好像是分離豪不相關的,其實它們內在的邏輯是一致性的。

    來自?talk??/dev/winter 2015對這三個概念進行了深入理解與分析:分布式流處理概念來自于互聯網公司LinkedIn,而CAEP來自于90年代的event simulation research,ES事件溯源則是屬于領域驅動設計社區,用于企業軟件開發的一種方式,這種方式適合復雜的數據模型,同時數據量又小于互聯網應用的場景。

    首先,我們從Google Analytics這個案例開始,這是一段Javascript放在你的網站上,跟蹤每個頁面被哪些訪客訪問,管理員通過時間線或根據URL瀏覽這些統計數據,那么你如何自己實現類似谷歌分析這樣的工具呢?

    每次用戶瀏覽一個頁面,我們需要記錄一個事件,一個page view事件看上去如下下面(偽JSON):

    流處理

    這個page view事件有一個事件類型(PageViewEvent),還有一個顯示事件發生的時間戳,客戶的IP以及會話ID(cookie的唯一標識用來跟蹤同一個用戶的一系列瀏覽行為),頁面的URL,以及從哪上一個頁面到當前頁面的URL,瀏覽器設置等等。

    這個事件很簡單,是不可變的事實,只是記錄某個發生的事情。那么我們如何基于這些事實獲得用戶是如何訪問我的網站的整個情形呢?

    事件分析

    有兩種選項:

    Option (a):?每次將單個事件存儲一次,導入到一個大數據庫,或數據倉庫或一個Hadoop集群等大的數據集中,你可以運行一個大的SELECT 來查詢這個數據集,這種查詢將會掃描所有涉及到的事件,進行聚合分析。

    Option (b):?如果每次都存儲一個事件太浪費了,你可以存儲一個事件匯總的結果,比如,如果你計數,那么每次有事件進來時,就增加一下計數數值,扔掉那些進行來的事件,你也可以設計一種數據表結構,代表多維視角,一維是URL,另外一維是事件的時間,另外一維是瀏覽器,對于每個事件,你只需要增加對應URL在某個時間下的總計數就可以了。這是我們非常常見的關系數據庫數據表結構設計場景。

    使用這種方式,你如果要發現某天某個URL的頁瀏覽量數量,只需要使用URL和時間作為Select查詢參數,直接查詢這個數據表即可。不必每次都要存儲每個事件,從這點來看,方案a顯得非常瘋狂,但是它卻令人驚奇地工作得很好,相信Google Analytics?實際也是如同方案a這么存儲原始事件的,現代分析數據庫非常擅長快速掃描大量數據,因此每次查詢數據時,都會依賴這些現代技術掃描所有有關的事件。

    存儲原始數據的最大好處是你有分析上巨大靈活性,你能跟蹤一個用戶會話階段的所有瀏覽頁面序列,如果你采取方案b就無法實現,因為你事先沒有設計這樣的數據表結構,需求是時刻變化的,今天用戶希望從這些事件上獲得一種匯總結果,明天他們可能需要另外一種匯總結構,如果每種匯總結果都設計一個數據結構,那么數據表數量不但龐大,而且數據冗余,同時新的數據表結構無法對以前的事件數據進行匯總聚合,因為你將以前的原始事件扔掉了,失去了事件真相。

    最好的辦法是你保存這些原始事件,如果技術發展了,還可以使用機器學習系統對這些原始事件進行分析,但是方案b能夠對某個具體匯總查詢有實時響應。因此,原始事件存儲和事件的匯總聚合都是有用處的,只是針對不同的用例情況。

    那么如何結合這兩個方式呢?我們可以使用緩存memcache等存儲事件的匯總聚合,每次進來一個事件,我們只要修改一個匯總聚合的狀態即可,而引入事件流或消息隊列或事件日志來保存原始事件,一個消息包含一個事件,這樣我們能夠以很便宜低廉方式保存原始事件,同時也會消費這些原始事件提供了多種消費可能,只要設計多個消息隊列的消費者即可,

    Event Sourcing也類似方案a,每次保存的都是原始事件,以購物車為案例,每次保存的不是購物車當前有幾個商品,而是保存的是造成當前有幾個商品的原因,也就是用戶進行了那些加入和移除事件后,最后造成當前購物車的這種狀態。我們將AddToCart, UpdateCartQuantity等對購物車的加入和修改操作作為原始事件,類似方案a的用戶瀏覽事件一樣,當你要查詢當前購物車狀態時,只要通過播放這些動作就能獲得最終購物車的狀態。

    事件寫和匯總數據讀

    這種方式可以歸結為:寫入原始事件,讀取出事件的匯總結果。也就是說,只要將原始操作事件保存寫入數據庫,我們通過讀取數據庫播放這些事件就能獲得當前狀態,傳統方式是:我們設計一個關系數據表,也就是方案b,用來保存購物車當前狀態,原始事件更改玩狀態后就扔掉了,也就是updateSQL語句每次操作完成就扔掉了,而沒有記錄哪些事件觸發這個update SQL的發生。

    這樣我們就可以使用一個數據庫進行寫,一個數據庫專門用來讀,這些讀寫方式分離分擔了系統的負載,寫數據庫專門寫入原始事件,讀數據庫專門用來進行事件的匯總聚合結果的讀取。

    下面我們再以Twitter為案例說明這種方式。

    下篇

    Twitter的分布式日志DistributedLog

    替代傳統事務的并發建議

    微服務的最終一致性與事件流

    日志是每個軟件工程師關心的統一數據抽象

    Reactive編程

    Event Sourcing

     

     

    美女漫画大全