缓存架构设计
核心原则:读多写少的数据,缓存起来,减少数据库访问,提升性能
实体缓存
实体缓存就是整表缓存那些读取很多修改极少的数据
,用于系统参数表、栏目分类表等。
实体类内使用'Meta.Cache.Entities'即可触发使用实体缓存,内部将执行一次查询('Select * From Table')加载整表数据为实体列表。
Meta.Cache.Entities
就是这个实体列表,使用缓存实际上就是在这个列表上执行Find
/FindAll
操作。
基于性能考虑,建议单表数据小于1000行时使用,大于10000时坚决不要使用。
工具生成的实体业务类代码经常可以看到如下代码:
public Student FindByID(Int32 id)
{
if (id <= 0) return null;
if (Meta.Count >= 1000)
return Find(__.ID, id);
else // 实体缓存
return Meta.Cache.Entities.Find(__.ID, id);
}
因此,FindByID
在该表数据小于1000时,其实是使用实体缓存。
缓存默认过期时间60秒
,过期后使用仍然是马上返回旧数据,同时开启异步查询更新缓存。
任何添删改等改动数据库的操作,都将会让缓存马上过期,并启动异步更新。
任何添删改操作,都将实时修改缓存,即使在异步更新完成之前,从缓存拿到的也是最新数据。除非有其它进程更新了数据表,此时需要等缓存的异步更新操作完成才能得到最新数据。
缓存更新策略
在没有使用事务时,对数据表的任何添删改,将会让该表的实体缓存马上过期,以及清空单对象缓存。
使用事务时,每一个添删改操作仅修改缓存,直到事务提交或回滚才清空缓存。
特别优化
SQLite
没有索引表供快速查询表行数,而直接Select Count
又慢,因此框架针对SQLite
进行特别优化。
获取表行数时,如果有自增字段,首先获取其最大值临时充当表行数,然后启动异步查询Select Count
以获取精确的表行数。
因此,SQLite
使用Meta.Count
时,第一次得到的数据可能有偏差,一会后即可得到精确数据。时间的长度主要由数据表大小决定,一百万数据大概需要几百毫秒。该偏差完全可以通过系统启动时进行系统预热来对冲掉。