NewLife.XCode是一個有10多年歷史的開源數據中間件,支持nfx/netcore,由新生命團隊(2002~2019)開發完成並維護至今,以下簡稱XCode。
整個系列教程會大量結合示例代碼和運行日志來進行深入分析,蘊含多年開發經驗於其中,代表作有百億級大數據實時計算項目。
開源地址:https://github.com/NewLifeX/X (求star, 765+)
全表緩存
在實際項目開發中,經常遇到有一些表數據很少(1000行以內),不會頻繁修改(平均每行幾個小時才會修改一次),例如配置表、分類表等。
這樣的表,往往可以接受三五秒甚至更長的延遲,正是最適合使用緩存的地方。
實體緩存:一次性加載全表數據進入內存,供上層多維度查詢!
來看一個例程:
根據查詢日志可以看到,雖然執行了1000萬次查詢,實際上只有一行select日志輸出,也就是只查了一次數據庫,其它9,999,999次從緩存中查找。
實體緩存的查詢速度只取決於 CPU主頻,在這台AMD古董機上也可以輕松得到百萬級速度。
最后一行是實體緩存統計日志,10秒輸出第一次,然后每10分鍾輸出一次,統計了緩存數、請求數、命中率。
如上,7億多次查詢,命中率在99%以上。
使用實體緩存
實體緩存本質上就是一個實體列表 IList<TEntity>,可通過 Meta.Cache 快速訪問。
該列表位於 Meta.Cache.Entities,在 Meta.Cache 上提供了 Find/FindAll 方法。
因為是 IList<TEntity>,所以適用所有Linq方法,如上面例子可以改為:Meta.Cache.Entities.FirstOrDefault(e => e.Name.EqualIgnoreCase(name))
XCode在生成實體類擴展查詢代碼時,默認都會帶有實體緩存用法,當表行數小於1000時,走實體緩存:
if (Meta.Count < 1000) return Meta.Cache.Find(e => e.Name.EqualIgnoreCase(name));
如果不想使用實體緩存,注釋這一行即可。除此之外,XCode內部任何地方不會主動使用實體緩存。
使用緩存的閾值
1000是一個大量實踐得到的值:
小於1000時,內存搜索遠勝於數據庫,畢竟數據庫還有網絡開銷和序列化為實體對象的開銷;
大於10000時,內存搜索就不如數據庫了;
1000到10000之間,內存搜索速度逐步下降,可根據場景決定閾值大小,例如數據極少修改且又需要進行范圍搜索時甚至可以設為大於10000;
擴展屬性優化
在前面《擴展屬性》中提到過,XCode不支持多表關聯,而是建議拆分為多次單表查詢。查詢簡單化以后,就可以更容易的實現緩存優化。
還是學生班級的例子,為了在學生列表頁展示班級名稱,而學生表student只有班級編號classid字段,當時的做法是建立Class擴展屬性,借助Class.FindByID查詢。
因為班級數量不會特別多,更是極少修改,因此我們可以在Class.FindByID內部使用實體緩存,把所有班級都緩存起來。
至此,學生班級的多表關聯查詢,借助擴展屬性和列表緩存,成功轉化成為學生表單表查詢,班級名稱的匹配幾乎毫無壓力!
過期策略
所有緩存都必須有過期策略。實體緩存的過期策略有以下:
- 初始化。首次訪問緩存時,加鎖阻塞所有訪問線程,直到加載完全表數據。
- 定時過期。緩存過期后,開異步線程更新並同時返回舊數據,確保應用層性能。設置文件的 EntityCacheExpire, 默認10秒
- 添刪改過期。對實體類的添刪改操作完成后,都會直接修改實體緩存對應項,而不會清空整個列表。
顯然,首次加載以后,將來訪問的永遠是定時更新的緩存數據,應用層可以得到非常好的性能!
由於實體緩存的添刪改過期跟實體操作綁定在一起,因此,越過實體類直接DAL執行更新操作,或者其它服務器修改數據,此時無法影響實體緩存,導致數據更新不及時。
早期版本XCode實體緩存默認過期時間60秒,隨着數據庫性能提升,默認值修改為10秒,可根據實際場景設置。
系列教程
NewLife.XCode教程系列[2019版]
- 增刪改查入門。快速展現用法,代碼配置連接字符串
- 數據模型文件。建立表格字段和索引,名字以及數據類型規范,推薦字段(時間,用戶,IP)
- 實體類詳解。數據類業務類,泛型基類,接口
- 功能設置。連接字符串,調試開關,SQL日志,慢日志,參數化,執行超時。代碼與配置文件設置,連接字符串局部設置
- 反向工程。自動建立數據庫數據表
- 數據初始化。InitData寫入初始化數據
- 高級增刪改。重載攔截,自增字段,Valid驗證,實體模型(時間,用戶,IP)
- 臟數據。如何產生,怎么利用
- 增量累加。高並發統計
- 事務處理。單表和多表,不同連接,多種寫法
- 擴展屬性。多表關聯,Map映射
- 高級查詢。復雜條件,分頁,自定義擴展FieldItem,查總記錄數,查匯總統計
- 數據層緩存。Sql緩存,更新機制
- 實體緩存。全表整理緩存,更新機制
- 對象緩存。字典緩存,適用用戶等數據較多場景。
- 百億級性能。字段精煉,索引完備,合理查詢,充分利用緩存
- 實體工廠。元數據,通用處理程序
- 角色權限。Membership
- 導入導出。Xml,Json,二進制,網絡或文件
- 分表分庫。常見拆分邏輯
- 高級統計。聚合統計,分組統計
- 批量寫入。批量插入,批量Upsert,異步保存
- 實體隊列。寫入級緩存,提升性能。
- 備份同步。備份數據,恢復數據,同步數據
- 數據服務。提供RPC接口服務,遠程執行查詢,例如SQLite網絡版
- 大數據分析。ETL抽取,調度計算處理,結果持久化