[NewLife.XCode]增量累加

NewLife.XCode是一個有10多年曆史的開源數據中間件,支持nfx/netstandard,由新生命團隊(2002~2019)開發完成並維護至今,以下簡稱XCode。

整個系列教程會大量結合示例代碼和運行日誌來進行深入分析,蘊含多年開發經驗於其中,代表作有百億級大數據實時計算項目。

開源地址:https://github.com/NewLifeX/X (求star, 729+)

 

累加的需求背景

一個網站,部署了兩臺應用服務器,共用數據庫,其中文章表有個訪問次數的字段。

現在需要記錄訪問次數,需要怎麼做?

var entity = Article.FindByID(9527);
entity.Views++;
entity.Update();

如果兩臺服務器都有用戶訪問了9527這篇文章,訪問前Views是1000,訪問後是多少?1002?大部分情況下是1002,少數情況下可能是1001。

如果每臺服務器都有100個用戶同時訪問這篇文章呢?那可就精彩了,最後訪問數可能是1001到1200之間的某個數。

 

按照教科書做法,我們似乎應該開個事務加個鎖,確保同時只能有一個用戶(線程)修改這一行數據。

且不說加鎖和事務成本有多高,光是爲了一個字段就鎖住這一行導致用戶無法更新這一行其它字段,就讓人覺得挺不地道的。再者,訪問次數對於其它字段來說,也許並沒有那麼重要。

 

聰明如你,可以想到這麼一個辦法:

update article set views=views+1 where id=9527

哈,這就是XCode增量累加的出發點,每個用戶(線程)執行自己的那一次,不管排隊先後,最終結果都將會是1200。

 

設置增量累加

在實體類靜態構造函數中,可以設置需要增量累加的字段

Meta.Factory.AdditionalFields 添加需要採用增量累加的字段,執行update時才生成 x=x+123 樣子的語句。

測試代碼:

Update VisitStat Set Times=Times+123,Users=Users+1,IPs=IPs+1,UpdateTime='2019-03-26 22:36:14' Where ID=1

從輸出效果看到,產生了累加效果。並且,這段代碼不管執行多少次,都是這樣的累加效果,而不管實際值是多少。

 

累加原理

從數據庫查出來一個對象時,如果發現有設置累加字段,XCode會把此時的數據“備份” 下來

在執行update保存的時候,拿累加字段的最後值減去原始備份值,得到差值(可能是負數),生成 x=x+123 或 x=x-456 的語句。

不光整數,小數也可以設置累加字段。

 

需要注意的是,如果字段x允許空,並且要更新行的x字段剛好爲NULL,x=x+123 將會得不到預期效果。

 

高級用法

再看開頭的例子,即使使用了累加,不需要加鎖以及開事務,仍然需要update數據庫200次。

藉助累加以及異步保存功能,可以把這個次數大大降低。 

var entity = Article.FindByID(9527);
entity.Views++;
entity.SaveAsync(5_000);

先把Views設爲累加字段。

Article.FindByID內部可以用對象緩存,然後每臺應用服務器在10秒(默認緩存時間)內多線程查到的都是同一個entity對象。

SaveAsync將把對象entity放入實體隊列,5秒後延遲保存。如果200用戶訪問集中在5秒內,最後每臺服務器只會執行一次update操作。

Update Article Set Viewss=Views+100 Where ID=9527

數據庫寫入次數由200次下降到2次,提升100倍。

 

由此,你能想到什麼更有意思的用法了嗎?

 

系列教程

NewLife.XCode教程系列[2019版]

  1. 增刪改查入門。快速展現用法,代碼配置連接字符串
  2. 數據模型文件。建立表格字段和索引,名字以及數據類型規範,推薦字段(時間,用戶,IP)
  3. 實體類詳解。數據類業務類,泛型基類,接口
  4. 功能設置。連接字符串,調試開關,SQL日誌,慢日誌,參數化,執行超時。代碼與配置文件設置,連接字符串局部設置
  5. 反向工程。自動建立數據庫數據表
  6. 數據初始化。InitData寫入初始化數據
  7. 高級增刪改。重載攔截,自增字段,Valid驗證,實體模型(時間,用戶,IP)
  8. 髒數據。如何產生,怎麼利用
  9. 增量累加。高併發統計
  10. 事務處理。單表和多表,不同連接,多種寫法
  11. 擴展屬性。多表關聯,Map映射
  12. 高級查詢。複雜條件,分頁,自定義擴展FieldItem,查總記錄數,查彙總統計
  13. 數據層緩存。Sql緩存,更新機制
  14. 實體緩存。全表整理緩存,更新機制
  15. 對象緩存。字典緩存,適用用戶等數據較多場景。
  16. 百億級性能。字段精煉,索引完備,合理查詢,充分利用緩存
  17. 實體工廠。元數據,通用處理程序
  18. 角色權限。Membership
  19. 導入導出。Xml,Json,二進制,網絡或文件
  20. 分表分庫。常見拆分邏輯
  21. 高級統計。聚合統計,分組統計
  22. 批量寫入。批量插入,批量Upsert,異步保存
  23. 實體隊列。寫入級緩存,提升性能。
  24. 備份同步。備份數據,恢復數據,同步數據
  25. 數據服務。提供RPC接口服務,遠程執行查詢,例如SQLite網絡版
  26. 大數據分析。ETL抽取,調度計算處理,結果持久化

 

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