[NewLife.XCode]實體列表緩存(最土的方法實現(xiàn)百萬級性能)
NewLife.XCode是一個有10多年歷史的開源數(shù)據(jù)中間件,支持nfx/netcore,由新生命團(tuán)隊(2002~2019)開發(fā)完成并維護(hù)至今,以下簡稱XCode。
整個系列教程會大量結(jié)合示例代碼和運(yùn)行日志來進(jìn)行深入分析,蘊(yùn)含多年開發(fā)經(jīng)驗于其中,代表作有百億級大數(shù)據(jù)實時計算項目。
開源地址:https://github.com/NewLifeX/X (求star, 765+)
全表緩存
在實際項目開發(fā)中,經(jīng)常遇到有一些表數(shù)據(jù)很少(1000行以內(nèi)),不會頻繁修改(平均每行幾個小時才會修改一次),例如配置表、分類表等。
這樣的表,往往可以接受三五秒甚至更長的延遲,正是最適合使用緩存的地方。
實體緩存:一次性加載全表數(shù)據(jù)進(jìn)入內(nèi)存,供上層多維度查詢!
來看一個例程:



根據(jù)查詢?nèi)罩究梢钥吹剑m然執(zhí)行了1000萬次查詢,實際上只有一行select日志輸出,也就是只查了一次數(shù)據(jù)庫,其它9,999,999次從緩存中查找。
實體緩存的查詢速度只取決于 CPU主頻,在這臺AMD古董機(jī)上也可以輕松得到百萬級速度。
最后一行是實體緩存統(tǒng)計日志,10秒輸出第一次,然后每10分鐘輸出一次,統(tǒng)計了緩存數(shù)、請求數(shù)、命中率。

如上,7億多次查詢,命中率在99%以上。
使用實體緩存
實體緩存本質(zhì)上就是一個實體列表 IList<TEntity>,可通過 Meta.Cache 快速訪問。
該列表位于 Meta.Cache.Entities,在 Meta.Cache 上提供了 Find/FindAll 方法。
因為是 IList<TEntity>,所以適用所有Linq方法,如上面例子可以改為:Meta.Cache.Entities.FirstOrDefault(e => e.Name.EqualIgnoreCase(name))
XCode在生成實體類擴(kuò)展查詢代碼時,默認(rèn)都會帶有實體緩存用法,當(dāng)表行數(shù)小于1000時,走實體緩存:
if (Meta.Count < 1000) return Meta.Cache.Find(e => e.Name.EqualIgnoreCase(name));
如果不想使用實體緩存,注釋這一行即可。除此之外,XCode內(nèi)部任何地方不會主動使用實體緩存。
使用緩存的閾值
1000是一個大量實踐得到的值:
小于1000時,內(nèi)存搜索遠(yuǎn)勝于數(shù)據(jù)庫,畢竟數(shù)據(jù)庫還有網(wǎng)絡(luò)開銷和序列化為實體對象的開銷;
大于10000時,內(nèi)存搜索就不如數(shù)據(jù)庫了;
1000到10000之間,內(nèi)存搜索速度逐步下降,可根據(jù)場景決定閾值大小,例如數(shù)據(jù)極少修改且又需要進(jìn)行范圍搜索時甚至可以設(shè)為大于10000;
擴(kuò)展屬性優(yōu)化
在前面《擴(kuò)展屬性》中提到過,XCode不支持多表關(guān)聯(lián),而是建議拆分為多次單表查詢。查詢簡單化以后,就可以更容易的實現(xiàn)緩存優(yōu)化。
還是學(xué)生班級的例子,為了在學(xué)生列表頁展示班級名稱,而學(xué)生表student只有班級編號classid字段,當(dāng)時的做法是建立Class擴(kuò)展屬性,借助Class.FindByID查詢。
因為班級數(shù)量不會特別多,更是極少修改,因此我們可以在Class.FindByID內(nèi)部使用實體緩存,把所有班級都緩存起來。
至此,學(xué)生班級的多表關(guān)聯(lián)查詢,借助擴(kuò)展屬性和列表緩存,成功轉(zhuǎn)化成為學(xué)生表單表查詢,班級名稱的匹配幾乎毫無壓力!
過期策略
所有緩存都必須有過期策略。實體緩存的過期策略有以下:
- 初始化。首次訪問緩存時,加鎖阻塞所有訪問線程,直到加載完全表數(shù)據(jù)。
- 定時過期。緩存過期后,開異步線程更新并同時返回舊數(shù)據(jù),確保應(yīng)用層性能。設(shè)置文件的 EntityCacheExpire, 默認(rèn)10秒
- 添刪改過期。對實體類的添刪改操作完成后,都會直接修改實體緩存對應(yīng)項,而不會清空整個列表。
顯然,首次加載以后,將來訪問的永遠(yuǎn)是定時更新的緩存數(shù)據(jù),應(yīng)用層可以得到非常好的性能!
由于實體緩存的添刪改過期跟實體操作綁定在一起,因此,越過實體類直接DAL執(zhí)行更新操作,或者其它服務(wù)器修改數(shù)據(jù),此時無法影響實體緩存,導(dǎo)致數(shù)據(jù)更新不及時。
早期版本XCode實體緩存默認(rèn)過期時間60秒,隨著數(shù)據(jù)庫性能提升,默認(rèn)值修改為10秒,可根據(jù)實際場景設(shè)置。
系列教程
NewLife.XCode教程系列[2019版]
- 增刪改查入門。快速展現(xiàn)用法,代碼配置連接字符串
- 數(shù)據(jù)模型文件。建立表格字段和索引,名字以及數(shù)據(jù)類型規(guī)范,推薦字段(時間,用戶,IP)
- 實體類詳解。數(shù)據(jù)類業(yè)務(wù)類,泛型基類,接口
- 功能設(shè)置。連接字符串,調(diào)試開關(guān),SQL日志,慢日志,參數(shù)化,執(zhí)行超時。代碼與配置文件設(shè)置,連接字符串局部設(shè)置
- 反向工程。自動建立數(shù)據(jù)庫數(shù)據(jù)表
- 數(shù)據(jù)初始化。InitData寫入初始化數(shù)據(jù)
- 高級增刪改。重載攔截,自增字段,Valid驗證,實體模型(時間,用戶,IP)
- 臟數(shù)據(jù)。如何產(chǎn)生,怎么利用
- 增量累加。高并發(fā)統(tǒng)計
- 事務(wù)處理。單表和多表,不同連接,多種寫法
- 擴(kuò)展屬性。多表關(guān)聯(lián),Map映射
- 高級查詢。復(fù)雜條件,分頁,自定義擴(kuò)展FieldItem,查總記錄數(shù),查匯總統(tǒng)計
- 數(shù)據(jù)層緩存。Sql緩存,更新機(jī)制
- 實體緩存。全表整理緩存,更新機(jī)制
- 對象緩存。字典緩存,適用用戶等數(shù)據(jù)較多場景。
- 百億級性能。字段精煉,索引完備,合理查詢,充分利用緩存
- 實體工廠。元數(shù)據(jù),通用處理程序
- 角色權(quán)限。Membership
- 導(dǎo)入導(dǎo)出。Xml,Json,二進(jìn)制,網(wǎng)絡(luò)或文件
- 分表分庫。常見拆分邏輯
- 高級統(tǒng)計。聚合統(tǒng)計,分組統(tǒng)計
- 批量寫入。批量插入,批量Upsert,異步保存
- 實體隊列。寫入級緩存,提升性能。
- 備份同步。備份數(shù)據(jù),恢復(fù)數(shù)據(jù),同步數(shù)據(jù)
- 數(shù)據(jù)服務(wù)。提供RPC接口服務(wù),遠(yuǎn)程執(zhí)行查詢,例如SQLite網(wǎng)絡(luò)版
- 大數(shù)據(jù)分析。ETL抽取,調(diào)度計算處理,結(jié)果持久化

浙公網(wǎng)安備 33010602011771號