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版]

  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抽取,调度计算处理,结果持久化

[NewLife.XCode]实体列表缓存(最土的方法实现百万级性能)的更多相关文章

  1. [NewLife.XCode]数据层缓存(网站性能翻10倍)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  2. [NewLife.XCode]实体类详解

    NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...

  3. [NewLife.XCode]实体工厂(拦截处理实体操作)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  4. [NewLife.XCode]对象字典缓存(百万军中取敌首级)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  5. [NewLife.XCode]高级查询(化繁为简、分页提升性能)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  6. [NewLife.XCode]百亿级性能

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  7. [NewLife.XCode]导入导出(实体对象百变魔君)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

  8. 【原创】Newlife.XCode的常见功能使用(一)查询与数据初始化

            本博客所有文章分类的总目录:http://www.cnblogs.com/asxinyu/p/4288836.html Newlife XCode组件相关文章目录:http://www ...

  9. [NewLife.XCode]增删改查入门

    NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...

随机推荐

  1. INTERVAL YEAR TO MONTH数据类型

    INTERVAL YEAR TO MONTH数据类型 Oracle语法: INTERVAL 'integer [- integer]' {YEAR | MONTH} [(precision)][TO ...

  2. istio实现对外暴露服务

    1.确认istio-ingressgateway是否有对外的IP kubectl get service istio-ingressgateway -n istio-system 如果 EXTERNA ...

  3. mqtt mosquitto 源码安装

    下载地址 ububtu  : wget https://codeload.github.com/eclipse/mosquitto/zip/master 安装依赖 sudo apt-get insta ...

  4. spring BeanWrapperImpl方便的嵌套属性(list)操作

    beans 包主要提供了接口和类用于处理java beans.     其中最主要的接口是BeanWrapper:     Spring 的中心接口,用于访问javabeans 的低层操作.默认实现为 ...

  5. STM32CubeMX+Keil裸机代码风格(1)

    1.打开STM32CubeMX,New project 选好自己要用的芯片 2.选上左侧SYS中的debug Serial Wire(定义烧程序的端口) . 3,选上左侧TIM6,使TIM6可用(TI ...

  6. python网络编程 双人多人聊天

    在学习网路编程时,我们首先要考虑的是其中的逻辑,我们借助打电话的形式来了解网络编程的过程, 我们打电话时属于呼叫方,接电话的属于被呼叫方,那么被呼叫方一直保持在待机状态,等待主呼叫方 呼叫,只有在被呼 ...

  7. hive 日常技巧

    --删除表中重复数据 delete from vitae a where (a.peopleId,a.seq) in (select peopleId,seq from vitae group by ...

  8. 自定义Token的CAS登录

    工作中实际遇到的需求,我们有一个旧系统,用了CAS的单点登录,现在有一个外部系统,准备从它那里单点进来,这个外部系统提供了一个token参数来标记这是哪一个用户,我们用他们提供的方式解析出对应的用户, ...

  9. API网关-Ocelot概述

    这个框架的整体思路其实就是Redirect请求并且附带一个简易的负载均衡机制,完全搭建MVC Core项目下在Ocelot项目启动的时候需要配置所有的ReRoute集合,这里的每一个ReRoute可以 ...

  10. Android JNI 学习(四):接口方法表 & Base Api & Exception Api

    本文我们来总结一下JNI 提供的功能列表及相关的函数表. 注意:请注意使用术语“必须”来描述对JNI程序员的限制.例如,当您看到某个JNI函数必须接收非NULL对象时,您有责任确保不将NULL传递给该 ...