工作流引擎數據緩存的應用

Domino 平臺上,現有的工作流引擎都有一個比較大的缺點,就是每次工作流的運轉都需要從配置庫讀取配置信息。這好像沒什麼錯誤!的確每次流轉都要讀取配置信息,可以保證每次的流程配置改動都能即時反映到流程引擎中,但是我們可以想想,流程配置修改的頻率會有多高那?而工作流引擎將大量的運算用於讀取數據、構建工作流引擎對象上,是不是一種資源的浪費那?對於修改並不頻繁的流程配置數據來說,能不能將這些數據裝入緩存中,然後供流程引擎調用那?

答案是可行的。我們都知道 Domino 數據庫是一種文檔型數據庫,它對數據的檢索有多種途徑,但是哪種方法似乎都不是特別完美。咱們就這幾種方法探討一下。

第一種,視圖檢索。

       通過視圖檢索數據,應該還是非常普遍的。但是用視圖有個比較大的缺點,視圖是靜態的,不能在程序中動態指定視圖的選擇條件。雖然可以用視圖的 GetDocumentByKey() 或者 GetAllDocumentsByKey() 方法,但是查詢的條件只能限定在某個字段或某幾個字段的組合。而且搜索結果受視圖索引的制約,有時也不是那麼準確。

第二種,公式檢索。

       這個方法是通過調用 NotesDatabase.dbSearch() 實現的。這個方法較之視圖搜索更靈活,開發人員只需要編寫搜索公式即可。但是這個方法也有個缺點,如果數據庫中文檔數量較多,那麼查詢速度就會讓人抓狂了。

第三種,索引檢索

這個方法是調用 NotesDatabase.ftsearch() 來實現的,調用這個方法的前提是數據庫已經創建了索引。 ftsearch() 的速度是最快的,即使在數據量很大的情況下。但是這個方法仍然有個缺陷,如果索引更新不及時,就查不到最新的數據。而這往往是致命的。

以上三種檢索方法跟本篇的主題似乎是有點遠。其實不然,在 Domino 平臺上,縱觀這三種檢索方法沒有一個完美的。也許這跟文檔型數據庫的工作原理有關係,但這不在我們的討論之列。一直以來 Domino 平臺上的檢索遭人詬病,才逐漸發展出借用關係型數據庫來增強 Domino 平臺的檢索能力,這個問題以後再單起文討論。只所以把檢索的問題提出來,是因爲基於 Domino 平臺的流程引擎,大量使用了視圖檢索和公式檢索。在一個流程配置庫和人員管理庫中需要建立大量的視圖。這些視圖的建立雖然方便了流程引擎的運轉,但同時也拖累了系統的運行速度。至於使用索引檢索,最大的問題是經常檢索不到數據,不用也罷。

現在的問題出現了,爲了保證檢索結果的準確性,一方面使用公式檢索 速度慢,一方面使用視圖檢索 不靈活。而且還有個問題是,想同的數據,每次運行代理都得重複檢索而不管這塊數據有沒有更新。浪費,極大地浪費!一個結論呼之欲出:使用數據緩存。

工作流數據緩存的概念肯定別人也想到了,但是從網上查找相關資料卻少的可憐。也許這個東西根本不值得一提吧。但是我認爲工作流數據緩存還是很有必要的,至少在 Domino 平臺上還是有用武之地的。

從本質上將工作流的數據緩存也不是一個多複雜的東西。無非是將工作流引擎需要的數據現行讀入內存,然後在工作流引擎工作地時候直接從內存中讀取數據。這樣做不但減少了對數據庫訪問次數,而且從內存讀取數據的速度要比從數據庫中讀取數據的速度快太多了。

實現數據緩存我知道的有兩種方式,在這裏先提前說一句。我知識有限寫些東西只是爲拋磚引玉。實現緩存的方法一種是利用 HaspMap 鍵值對的方式在內存中建立映射表,當然關鍵字只有一個。另外一個方式就是通過 JNDI ,利用 JNDI 的查詢機制建立數據映射。我們熟悉的 LDAP 服務其實就是 JNDI 的一個很典型的實例。當然 JNDI 這種方式怎麼樣,我心裏沒譜,還是各位看官發表一下意見吧。

對於工作流引擎來說如何想辦法快速、高效、準確的找到需要的數據是非常重要的。但是現在大多數流程引擎是直接從數據庫中檢索數據,前文中也說了這種方式是效率低下的。大家可能沒有一個感官上的認識,我們先來看看傳統的工作流引擎的工作原理。

圖1

                                                                                                 圖1

如圖1 所示,工作流引擎需要多次從流程配置庫中取數據,而且一般的工作流引擎是通過Web 代理方式調用的。Web 代理方式調用的短板就是每次都得重複打開數據庫的命令。Domino 是對數據庫做了緩存,但是不用打開數據庫是不是更快捷那?

緩存的作用是什麼?工作流引擎的瓶頸一般也就這麼幾個方面。一是,引擎設計的好壞。這是先天因素,任何緩存機制都是無用武之地的。二是,讀取數據庫的次數。次數越少當然越好了。三是,流程配置信息的利用率。每次需要的數據都從數據庫讀取,那肯定是利用率不高的。四是,業務數據的讀寫效率。以上問題未必囊括了全部的問題。但在本文中說明問題已經足夠了。看到這裏我們應該有個原則性的結論,緩存只能是輔助性質的。根本問題還是工作流引擎的設計優劣。當然這不在本文的討論之列。

根據圖 1 所示,將工作流引擎結合緩存機制後會是什麼情況那?看一下下圖 ( 2)

圖2

 

 

                                                                                                                                 圖2

將圖 2 中工作流引擎指向數據庫的連接全部改成指向數據緩存,即工作流引擎從緩存中取數據。而緩存則從數據庫中取數據。一個問題又浮出水面了。從數據庫讀取信息到緩存中有兩種方式。一種是預讀取,一種是後讀取。這個怎麼講那?聽某慢慢道來。

       所謂預讀取就是事先將數據庫中的配置數據讀取到內存中。這樣做的好處是每次工作流引擎訪問緩存,不需要等待。缺點是啓動之初需要取大量的數據。這種方式比較浪費資源。後讀取的方式是工作流引擎第一次訪問緩存時,緩存服務從數據庫中讀取數據,放入緩存,然後返回給工作流引擎。這樣做的好處是沒有資源浪費的現象,所有的緩存數據都是用到的。當然缺點也是明顯的,那就是流程引擎初次訪問的速度會慢一些。   <!-- /* Font Definitions */ @font-face {font-family:宋體; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-1610611985 1107304683 0 0 159 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face {font-family:"/@宋體"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-fareast-font-family:宋體; mso-bidi-font-family:"Times New Roman"; mso-font-kerning:1.0pt;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-size:10.0pt; mso-ansi-font-size:10.0pt; mso-bidi-font-size:10.0pt; mso-ascii-font-family:Calibri; mso-fareast-font-family:宋體; mso-hansi-font-family:Calibri; mso-font-kerning:0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} -->

      對於緩存類程序來說,還有個相當重要的問題 , 那就是緩存的更新。衆所周知,緩存的更新一般都是一個比較難處理的問題。主要原因在於緩存的數據什麼時候更新,更新哪些數據。解決這個問題前,我們先來看看作爲支撐工作流引擎的兩種基礎數據的變化情況。

       第一種,組織機構數據。這些數據的變化頻率應該是比較高的。第二種,流程配置數據。這類數據變化的頻率就沒那麼頻繁了。這兩種數據都有一個共同的特點,數據的修改時沒有任何規律可循的。那麼作爲這兩種數據的緩存,事件觸發的更新機制應該是最合適不過的了。但是事件驅動對 Domino 來說似乎有點難度。我們都知道, Domino 中的代理有個屬性“所有新建及修改過得文檔”,通過這個屬性可以取到所有編輯過的文檔。但是,代理運行的間隔時間是在 30 分鐘,這個時間間隔還是比較長的。除此之外沒有其他途徑允許我們能夠實時監控文檔的事件了。這真是個棘手的問題。

       有一個辦法可以實現類似事件監控。也許這個方法比較笨,沒辦法,笨人用笨方法。那就是在保存、刪除文檔時,都記錄一個事件動作,然後記錄一個 ID 值,這個值需要與緩存中的數據一一對應。然後緩存循環讀取這些個數據,根據事件的動作,採取相應的動作。比如更新數據、刪除數據。具體的字段則在緩存規則配置裏配置好即可。上面這個方法不見得是個好方法,僅爲大家提供一種思路。希望能起到拋磚引玉的作用。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章