1. 程式人生 > >ENode框架單臺機器在處理Command時的設計思路

ENode框架單臺機器在處理Command時的設計思路

設計目標

  1. 儘量快的處理命令和事件,保證吞吐量;
  2. 處理完一個命令後不需要等待命令產生的事件持久化完成就能處理下一個命令,從而保證領域內的業務邏輯處理不依賴於持久化IO,實現真正的in-memory;
  3. 保證命令、事件處理的順序性,先來的先處理,先產生的先處理;
  4. 保證一個聚合根的事件只有一個執行緒在持久化,並按事件產生的順序持久化;
  5. 持久化事件時如果遇到併發衝突時(聚合根ID+事件版本號出現重複)的處理代價要輕;
  6. 要能利用多核的優勢;

總體設計思路

  1. 先將命令根據聚合根ID路由到CommandMailBox裡;
  2. 單執行緒處理CommandMailBox中的命令,由於聚合根在in-memory本地記憶體,所以處理非常快;
  3. 處理成功後更新聚合根的in-memory記憶體;
  4. 記憶體更新後將聚合根產生的事件同樣原理路由到EventMailBox裡;
  5. 單執行緒批量處理EventMailBox中的事件;由於是批量,所以持久化的吞吐量也可以保證;
  6. 處理完成一批事件後,把這一批事件對應的命令從CommandMailBox中移除;

詳細設計思路

  1. 設計N個存放命令的CommandMailBox,命令首先按聚合根ID的hashcode取摸路由到對應的CommandMailBox;
  2. 每個CommandMailBox都有一個maxOffset, consumeOffset,以及一個CommandProcessor(單執行緒)在不停的處理;maxOffset表示最後一個命令的位置;consumeOffset表示當前正在處理的命令的位置;
  3. CommandProcessor的處理邏輯;
    • 建立、修改聚合根;
    • 更新聚合根的in-memory快取;
    • 將聚合根產生的事件按聚合根ID的hashcode取摸路由到對應的EventMailBox;EventMailBox的個數也是程式啟動時配置;
  4. 每個EventMailBox都有一個maxOffset, consumeOffset,以及一個EventProcessor(單執行緒)在不停的處理;maxOffset表示最後一個事件的位置;consumeOffset表示當前正在處理的事件的位置;
  5. EventProcessor的處理邏輯:
    • 按次序批量獲取一批要處理的事件;
    • 批量持久化事件到EventStore,採用SqlBulkCopy;
    • 如果持久化一切順利,則publish這一批事件(publish如果遇到網路IO異常,則重試,直到成功為止),然後繼續持久化下一批,並同時將當前這一批事件對應的命令從CommandMailBox中刪除;.
    • 如果持久化遇到併發衝突(事件的aggregateRootId+Version重複),則對當前這一批事件一個個按順序持久化。如果當前事件持久化成功,則同樣publish該事件,當然遇到IO異常時也要不斷重試,直到成功為止;成功後通知CommandMailBox移除當前事件對應的命令;如果當前事件持久化出現併發衝突,就做如下處理:
    1. 先通知當前事件對應聚合根暫停處理後續的命令;
    2. 用Event Sourcing技術將in-memory中的聚合根的狀態還原到最新狀態,確保下次執行command時基於的聚合根的狀態是最新的;
    3. 把這一批裡該聚合根的所有事件移除,把EventMailBox中的該聚合根的所有事件移除;
    4. 將CommandMailBox的處理位置重置為當前事件對應的命令的offset;從而可以確保產生併發衝突的事件對應的命令以及後續的命令能再重新被處理一遍;
    5. 通知當前事件對應聚合根繼續處理後續的命令(從哪個位置開始處理,在上面第4步已經重置過了);
    6. 這一批的所有事件都一個個處理完之後,按同樣的邏輯繼續處理下一批事件;

其他說明

  1. 上面的設計基於一個前提,就是一個聚合根幾乎不會同時在兩臺伺服器上同時存在並處理命令,否則就會出現併發衝突,而併發衝突的處理的代價還是比較複雜的,應該儘量避免;這點可以通過EQueue保證;
  2. 當聚合根處理了命令,嘗試更新in-memory記憶體時,可能有一種情況會失敗。就是如果這個命令是建立聚合根的,而有可能併發的時候這個聚合根可能在記憶體中已經有了,則建立完聚合根新增到記憶體時,應該能檢測出來並記錄錯誤日誌,然後該命令產生的事件也不必放入EventMailBox,然後認為該命令處理成功即可。
  3. 上面的設計中沒有談到當遇到命令重複執行時的設計思路,大家可以自己想想:)

相關推薦

ENode框架機器處理Command設計思路

設計目標 儘量快的處理命令和事件,保證吞吐量; 處理完一個命令後不需要等待命令產生的事件持久化完成就能處理下一個命令,從而保證領域內的業務邏輯處理不依賴於持久化IO,實現真正的in-memory; 保證命令、事件處理的順序性,先來的先處理,先產生的先處理; 保證一個聚合根的事件只有一個執行緒在持久

CentOS6.5源碼搭建LAMP--基於module方式實現php(機器

centos6.5 源碼搭建lamp 基於module方式實現php 單臺機器源碼搭建LAMP軟件包下載源:搜狐鏡像源:http://mirrors.sohu.com/apache下載網:http://mirror.bit.edu.cn/apache/pcre官網:http://www.pcre.org/a

一行 Shell 通過 Nginx access 日誌實時統計機器QPS

log else 一行 實時 %d == nbsp qps 機器 # 實時統計 ## 方式一 tail -f access.log | awk -F ‘[‘ ‘{print $2}‘ | awk ‘BEGIN{key="";count=0}{if(key==$1)

機器多mysql例項修改埠號

配置my.cnf檔案即可: [client]     port    = 3307     socket    = /usr/local/mysql5.6/mysql.so

關於機器配置本地yum後其他機器通過httpd訪問的有關問題

.com 客戶 拷貝 pos spa cdrom 主機名 本地yum 宋體 今天跑通了三臺機器和yum本地倉庫的連接,linux小白很開心,特此記錄一下。 首先: 先挑選一臺機器min2(我的主機器),掛載一個系統光盤到本地目錄/mnt/cdrom,然後啟動一個httpd服

redis叢集實戰(機器Windows環境下搭建3主3從redis叢集)

本文主要展示在單臺win10機器上搭建三主三從redis叢集。 搭建過程 主要參考作者: 每天都在變得更好的阿飛  的兩篇部落格 《Redis叢集主從複製(一主兩從)搭建配置教程【Windows環境】》https://blog.csdn.net/u010648555/

Linux機器配置多IP的squid3 http代理

網路爬蟲最終要的資源就是IP地址,尤其是在各大網站紛紛把自家資料當初看家寶貝的“大資料時代”。即使IP地址多了,爬蟲改成分散式,管理那麼多伺服器上的爬蟲也是夠頭疼的。一種方法就是配置代理伺服器,爬蟲只在幾臺機器是跑就可以啦。 配置多IP地址 Linux(以Ubuntu為例)配置單機多IP地址還是很簡

1000個併發執行緒,10機器,每機器4核,設計執行緒池大小

這是why哥的第 71 篇原創文章 一道面試題 兄弟們,怎麼說? 我覺得如果你工作了兩年左右的時間,或者是突擊準備了面試,這題回答個八成上來,應該是手到擒來的事情。這題中規中矩,考點清晰,可以說的東西不是很多。 但是這都上血書了,那不得分析一波? 先把這個面試題拿出來一下: 1000 多個併發執行緒,10

論UDX併發,伺服器1.5w聯接,每條聯接傳送1KB資料,10秒內沒處理,斷開聯接--之改進過程

      對於併發這個話題已經討論很多,特別是在TCP大量聯接的成功案例很多。這裡不例舉,少說幾W多則上10W都有。      但是作為UDP可靠傳輸協議來說,每個事務處理都需要我們的CPU完成,而且我們要維護心跳,保證條條連線能正常收發,不讓洞給關掉了,使聯接斷開。所

idea ssm專案遷移到另一機器出現不能正常啟動專案的解決方案

    首先右下角提示關聯spring檔案,關聯之,然後啟動,發現專案無法啟動,然後開始排錯    首先從這個日誌裡發現了這麼一條提示資訊   然後百度了一下,答案都是說 web.xml 之類的 spring攔截器

(五)SSO之CAS框架點登入, session超時, ajax連結處理

1 錯誤場景                                   部署問題:用nginx封裝,service攜帶不過來。  2 cas 針對session超時設定                cas對於session超時設定,可以設定檔案cas\WEB

Vue框架整理:vue.js內建指令 v-if、v-for 、處理載入閃動未處理的資料

vue 基本指令: v-cloak : 一般被用在網速較慢,Vue還沒有載入完成時,不過當Vue建立例項後內容就會被替換掉, 並且螢幕會有一點閃動, 使用時最好配合的加一句CSS : [v-cloak]{ display:none;} 這個指令在小

發現一機器中同時執行多個Oracle例項。。。

發現一臺機器中同時執行多個Oracle例項時,最好保證 [OracleHome]/network/admin/listener.ora 檔案的 SID_LIST_LISTENER 段中 要對應每個例項都有一段宣告 其實這是個很簡單的問題,呵呵,只是偶以前一直沒留意過,今天剛剛

使用mysqldump匯出資料對欄位中包含的引號的處理

最近在做一個日誌統計專案,有一個輔助表是在MySQL資料庫的,現在要將其遷移到Postgresql,自然是先用mysqldump將MySQL裡面的資料匯出,然後再匯入到Postgresql即可。但在實際操作過程中,發現一些欄位中本身就含有單引號,在匯出的sql語

centos7在服務器上安裝FastDFS的方法

centos7 fastdfs 儲存服務器 安裝方法準備環境:#安裝依賴包yum -y install gcc gcc-c++ libtool pcre* zlib openssl openssl-develmkdir /FastDFS/#上傳下載工具yum -y install lrzsz yum -y i

JEESZ分布式框架點登錄集成方案

配置 拷貝 get lis request cat principal hosts secure 第一節:單點登錄簡介 第一步:了解單點登錄 SSO主要特點是: SSO應用之間使用Web協議(如HTTPS) ,並且只有一個登錄入口. SSO的體系中有下面三種角色: 1) U

JEESZ分布式框架--點登錄集成方案

rest服務 spring redis dubbo+zookeeper springmvc+mybatis java分布式架構 JEESZ分布式框架單點登錄集成方案第一節:單點登錄簡介第一步:了解單點登錄SSO主要特點是: SSO應用之間使用Web協議(如HTTPS) ,並且只有一個

git 在一機器上配置多個賬戶

rac ssh xxxxxx pla 必須 account ack entity 設置 前提: 必須知道怎樣配置git賬戶,請參考git官方教程:https://help.github.com/articles/generating-ssh-keys 這個教程能教你怎

Centos7服務器搭建FastDFS+Nginx

服務器 下載安裝 Fastdfs+Nginx配置操作單臺配置安裝包下載:wget https://github.com/happyfish100/libfastcommon/archive/V1.0.7.tar.gzwget http://jaist.dl.sourceforge.net/projec

Tomcat環境部署以及tomcat多實例搭建(同一機器

java 軟件 服務器 local profile 先搭建部署一臺Tomcat服務器:yum install -y gcc*本次需要的軟件安裝包:apache-tomcat-7.0.42.tar.gzjdk-7u25-linux-x64.tar.gznginx-1.2.6.tar.gz(安