開篇閑話:好幾個月沒寫文章了,從9月15號發布新浪“微博粉絲精靈”V1.0後,持續的幾個月都在折騰它,現在都折騰到V3.4版本了。因此,本篇遲來了三個月了,同時,本篇也是本系列的最後一篇了,也是秋色園最後殺手鐧,霸氣總該是要外露的。 上節回顧:上節 秋色園QBlog技術原理解析:效能最佳化篇:讀寫分離與文本資料庫(十八),秋色園 QBlog 將一些簡單頻繁的資料,借用文本外儲,來分減一些壓力,從而為並發降溫,保障網站的順利運行。 本節概要:文本外儲,在一定程式上解決了問題,但是,由於當時技術的薄弱,文本儲存無法處理查詢排序等問題,導致主體文章表依舊存在access黃金4K問題。在壓力之下,又要處理查詢排序等複雜動作,於是苦冥三日,終得一招。最後的招數:Access與SQLite合體,最後的AOP策略。 本節內容[AOP+資料庫組合+策略分析+最終實現]: 一:CYQ.Data 資料架構中的AOP思路簡述 1:關於最早期CYQ.Data資料架構實現AOP的思想文章,見:AOP 你想幹什麼 IOC 你服務什麼2:簡單的再描述一下:CYQ.Data資料架構通過在內部所有資料庫的操作方法中,內建2兩個AOP方法,來實現方法的攔截調整,簡單的方法體如下:public bool Fill(object where, params object[] aopInfo)
{
_Aop.Begin(Aop.AopEnum.Fill,_TableName, aopInfo);//AOP開始時的攔截
bool result = 正常的方法體代碼及操作結果
_Aop.End(Aop.AopEnum.Fill, result, aopInfo);//AOP在方法結束時再一個調用
return result;
}通過這樣的簡單的攔截,可以輕鬆的在資料庫操作前,先處理事情,在資料庫操作後,再處理事情。詳情代碼可下載:CYQ.Data V3.0 免費開源版本。 二:QBlog資料庫的決擇 首先:秋色園主體資料庫是Access,當然是近乎每個表1個資料庫,因此,是多個access資料庫。然後:秋色園再伴隨著“文本資料庫”,來分壓一些簡單讀寫的資料。最後:決擇是SQLite資料庫,以分壓使用者的文章壓力沒事多體驗下其它資料庫)。目前秋色園的記憶體情況是:VPS總體是512M記憶體。秋色園QBlog佔用200M以下記憶體。微博粉絲精靈佔用200M以下記憶體。系統預設開銷也得佔用200M左右。剩下渣都沒的剩了,連“愛說說”也因記憶體不足,暫時停掉了,當然不可能選用其它大型資料庫了。 三:實際情境的考慮 秋色園是一個多使用者部落格,而部落格系統,每一個使用者的資料,基本上是相互獨立的,簡單的說:多使用者可以化整為0,變成無數個單使用者部落格,然後無數個單使用者部落格,組合起來,就變成多使用者部落格。曾經有這麼一種設想:1:有那麼一個資料掛靠平台,部落格只要有一份即可。2:當我來到其它平台交流時,我只要選擇授權掛靠就好了。是不是有點像微博?部落格園發展為資料平台,像51cto,csdn等,只要變成API開發人員平台就行了,授權後資料直接對接過去,也省的兩邊發文章,是不?因此,如果讓我重新設計一個新的部落格系統,我可能會考慮[單]使用者組裝形式,這樣方便資料獨立[進行外掛、內接、或私人成獨立單使用者部落格系統]。想的有點多,回到正常的思路上考慮:基於“文本資料庫”減壓方案的延申,如果,把每個使用者的文章獨立分散,而每個使用者的文章又能自由的查詢排序,最終的效果就是:為每個使用者建一個sqlite資料庫檔案儲存資料。這樣的話,等於每個使用者產生一個1個獨立資料庫,因此,除了首頁,其它訪問都變成了單使用者部落格系統,基本上也就沒什麼壓力了。 想歸這麼想,總會帶來一些疑問的:1:資料庫檔案會不會產生太多?其實也不多,十萬個檔案不算啥,按下日期、使用者ID、哈唏、使用者名稱等多種方式分布到不同檔案夾下,一個檔案夾也頂不了多少個檔案。再說,有10萬使用者你都超越部落格園了,估計開始偷笑了。2:彙總內容怎麼辦?如網站首頁彙總多個使用者的文章顯示?這個沒啥,因為除了每個使用者獨立的資料庫檔案,還有總的access資料庫,彙總時讀access即可。3:這麼說資料變成一式兩份?這個沒錯,是成兩份了,不過目前策略,文章的內容(資料比較多)獨立僅1份,因此占不了多少空間。4:兩個資料庫,如何同步?同時寫兩份?寫兩份是要,當然就不可能同時寫了,因為同時寫,對原來的access還是存在多使用者並行作業,具體看下面的詳情。5:這樣系統不會變的很亂吧?“最後的AOP策略”以外掛程式的方式處理這種問題,一插,搞定,一拔,還是正常的,所以對系統完全不影響。 四:最後的AOP策略的實現 1:建立新的項目,開始AOP切換項目。由於AOP內建以反射調用DLL外掛程式式注入,因此原有邏輯代碼不改變,只要開新的項目處理即可。650) this.width=650;" alt="" src="http://www.bkjia.com/uploads/allimg/131228/135249CM-0.jpg" align="absMiddle" border="0" />然後設定檔配置一下相關的調用即可,各家實現不一,僅供參考說明:<add key="Aop" value="Web.Aop,Web.Aop.AopAction"/>2:為每個使用者建立SQLite資料庫主要為三步:1:建立SQLite資料庫;2:建立文章表結構;3:將主表的原有的使用者文章複製一份到新資料庫去。以下為代碼節選:650) this.width=650;" alt="" src="http://www.bkjia.com/uploads/allimg/131228/13524930M-1.jpg" align="absMiddle" border="0" />再接下來,就是處理各種“增刪改查”的資料庫同步問題:3:增加資料的處理流程:先看一個插入代碼AOP的偽方法:public bool Insert(params object[] aopInfo)
{
_Aop.Begin(Aop.AopEnum.Insert,_TableName, aopInfo);//AOP開始時的攔截,寫SQLite資料庫
bool result = 正常的方法體代碼及操作結果// 正常的寫Access資料庫
_Aop.End(Aop.AopEnum.Insert, result, aopInfo);//AOP在方法結束時再一個調用SQLite資料庫
return result;
}這果按這原有的AOP邏輯,將造成一種情況,寫完SQLite資料後,同時又將繼續寫Access資料庫,這明顯是有問題的,假設多個使用者發布文章,雖然SQLite是寫在不同的資料庫,可是同時寫主要資料庫Access,必然又出現並發4K問題。為此,對於主Access,必須使用新的方式來實現,再借文本,定時插入:實現原理:A:當寫完SQLite資料庫後,將文章內容寫成json輸入到臨時文本中。B:寫完直接跳過寫Access資料庫,直接返回。C:定時器,定時從文本中按順序執行插入或修改的內容。簡單的說:把並發寫Access資料庫,變成隊列式,1條接1條的插入,如此一來,並發寫就解決了。為了適應這種變化,原有的AOP必須稍的改進,AOP.Begin方法需要增加傳回值,以便作為條件,可以跳過下面的執行,為此,增加了傳回值的枚舉: /// <summary>
/// Aop函數的處理結果
/// </summary>
public enum AopResult
{
/// <summary>
/// 本結果將執行原有事件,但跳過Aop.End事件
/// </summary>
Default,
/// <summary>
/// 本結果將繼續執行原有事件和Aop.End事件
/// </summary>
Continue,
/// <summary>
/// 本結果將跳過原有事件,但會執行Aop End事件
/// </summary>
Break,
/// <summary>
/// 本結果將直接跳出原有函數的執行
/// </summary>
Return,
有了傳回值,插入後,跳過Access的插入執行,返回成功即可。參考代碼:650) this.width=650;" alt="" src="http://www.bkjia.com/uploads/allimg/131228/13524941R-2.jpg" align="absMiddle" border="0" />4:刪除資料的處理流程:當使用者操作刪除文章時,預設Begin不執行,先走原來流程,刪除主表,再從End事件刪除SQLite表。參考代碼:650) this.width=650;" alt="" src="http://www.bkjia.com/uploads/allimg/131228/13524a242-3.jpg" align="absMiddle" border="0" />5:修改資料的處理流程:由於Access已改裝成隊列式執行,因此更新流程需比插入多了一步要考慮的:如:使用者更新了A欄位,這時隊列還沒更新進資料庫,然後使用者又更新了B欄位。這時候,只能產生2個更新檔案到隊列中,後者B不能直接複蓋A,不然會造成A的修改丟失。參考代碼:650) this.width=650;" alt="" src="http://www.bkjia.com/uploads/allimg/131228/1352496419-4.jpg" align="absMiddle" border="0" />6:資料的查詢功能:根據條件判斷,如果是單使用者的資料,直接Begin方法查完SQLite後返回即可。樣本的查詢代碼:650) this.width=650;" alt="" src="http://www.bkjia.com/uploads/allimg/131228/1352492Q9-5.jpg" align="absMiddle" border="0" />至此,整體的最後的AOP策略處理就基本結束了。 總結:通過AOP策略,將使用者部落格變成單資料庫查詢,直接跳過主要資料庫Access查詢,基本滅掉了Access被並發的機率,同時新的策略,將Access資料庫的並發寫,變更成隊列式寫,因此不再有並發鎖庫出現,對於需要綜合資料查詢的,仍然返回Access資料庫查詢綜合資料,由於整體是外掛程式式操作,如果有一天access升級換成其它資料庫,不需要SQLite配合時,只要注釋設定檔代碼將外掛程式去掉,依舊是正常的運行,如果使用者想獨立出去弄個網域名稱,直接把sqlite資料庫下載回去即可。 到此,秋色園技術原理系列估計就寫到這裡了,本系統的技術內幕,基本也外露完了。 感謝網友對本系列的支援!!! 曆史文章回顧:1: 秋色園QBlog技術原理解析:開篇:整體認識(一) --介紹整體檔案夾和檔案的作用2: 秋色園QBlog技術原理解析:認識整站處理流程(二) --介紹秋色園業務處理流程3: 秋色園QBlog技術原理解析:UrlRewrite之無尾碼URL原理(三) --介紹如何?無尾碼URL4: 秋色園QBlog技術原理解析:UrlRewrite之URL重新導向體系(四) --介紹URL如何定位到處理常式5: 秋色園QBlog技術原理解析:Module之頁面基類設計(五) --介紹建立基類和自訂生命週期6: 秋色園QBlog技術原理解析:Module之頁面基類-生命週期流程(六) --介紹基類生命週期內部業務7: 秋色園QBlog技術原理解析:Module之基類生命週期-頁面載入(七) --介紹介面html載入原理8: 秋色園QBlog技術原理解析:Web之頁面處理-內容填充(八) --介紹html的內容是如何填充9: 秋色園QBlog技術原理解析:獨創的多語言翻譯機制(九) --介紹html多語言翻譯原理10:秋色園QBlog技術原理解析:頁面內容填充及多語言翻譯流程示範樣本(十) --總結示範範例程式碼11:秋色園QBlog技術原理解析:頁面Post提交機制(十一) --介紹如果Post提交資料12:秋色園QBlog技術原理解析:效能最佳化篇:位元組與緩衝與並發(十二) --介紹效能最佳化:位元組,並發及緩衝13:秋色園QBlog技術原理解析:效能最佳化篇:全域的SQL語句最佳化(十三) --介紹全域掌握SQL,進行針對性最佳化14 :秋色園QBlog技術原理解析:效能最佳化篇:緩衝總有失效時,構造持續的緩衝方案(十四) --介紹二次緩衝方案15:秋色園QBlog技術原理解析:效能最佳化篇:資料庫文章表分表及分庫減壓方案(十五) --介紹內容分庫減壓16:秋色園QBlog技術原理解析:效能最佳化篇:access的並發極限及分庫分散並發方案(十六) --介紹access並發上限17:秋色園QBlog技術原理解析:效能最佳化篇:使用者和文章計數器方案(十七) --介紹使用者和文章訪問的計數最佳化方案18:秋色園QBlog技術原理解析:效能最佳化篇:讀寫分離與文本資料庫(十八)--介紹簡單的文本分壓策略附章:1:秋色園QBlog技術原理解析:部落格一鍵安裝工具技術實現[附源碼下載] --開源秋色園安裝工具原理2:如何安裝部署秋色園CYQBlog網站3:Windows7下如何安裝部署秋色園CYQBlog網站 PS:秋色園QBlog:http://www.cyqdata.com/download/article-detail-427
本文出自 “路過秋天” 部落格,請務必保留此出處http://cyq1162.blog.51cto.com/2127378/739559