实体列表缓存(最土的办法实现百万级性能)

简介: 在实际项目开发中,经常遇到有一些表数据很少(1000行以内),不会频繁修改(平均每行几个小时才会修改一次),例如配置表、分类表等。这样的表,往往可以接受三五秒甚至更长的延迟,正是最适合使用缓存的地方。实体缓存:一次性加载全表数据进入内存,供上层多维度查询!

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秒,可根据实际场景设置。

相关文章
|
19天前
|
存储 缓存 自然语言处理
深入PHP内核:理解Opcode缓存对性能的影响
【4月更文挑战第25天】 在提升PHP应用性能的众多策略中,Opcode缓存技术因其显著的效果和较低的复杂度而备受开发者青睐。本文将深入探讨Opcode缓存机制,解析其对PHP执行效率的提升原理,并通过实验数据展示启用Opcode缓存前后的性能差异。我们还将讨论几种流行的Opcode缓存工具,如APC、OpCache与APCu,并评估它们的优劣及适用场景,帮助开发者根据不同的项目需求做出合适的选择。通过本文,读者不仅能够了解Opcode缓存的工作原理,还能学会如何在实际项目中应用这一技术以优化PHP应用程序的性能。
|
2月前
|
缓存 数据库 索引
如何优化Python Web应用的性能,包括静态资源加载、缓存策略等?
```markdown 提升Python Web应用性能的关键点:压缩合并静态资源,使用CDN,设置缓存头;应用和HTTP缓存,ETag配合If-None-Match;优化数据库索引和查询,利用数据库缓存;性能分析优化代码,避免冗余计算,使用异步处理;选择合适Web服务器并调整参数;部署负载均衡器进行横向扩展。每一步都影响整体性能,需按需调整。 ```
21 4
|
2月前
|
存储 缓存 算法
【C/C++ 性能优化】提高C++程序的缓存命中率以优化性能
【C/C++ 性能优化】提高C++程序的缓存命中率以优化性能
134 0
|
3月前
|
SQL 缓存 关系型数据库
MySQL技能完整学习列表6、查询优化——3、查询缓存——4、SQL优化技巧
MySQL技能完整学习列表6、查询优化——3、查询缓存——4、SQL优化技巧
65 0
|
3月前
|
存储 缓存 UED
缓存策略与Apollo:优化网络请求性能
缓存策略与Apollo:优化网络请求性能
|
8月前
|
存储 缓存 数据库
优化性能与减少资源浪费:深入了解缓存策略
缓存策略是现代Web开发中关键的优化技术之一,它可以显著提高网站性能,降低服务器负载,并减少用户等待时间。在本博客中,我们将深入研究缓存策略的概念、不同类型的缓存和如何在项目中实施它们。
79 0
|
19天前
|
SQL 缓存 数据库
在Python Web开发过程中:数据库与缓存,如何使用ORM(例如Django ORM)执行查询并优化查询性能?
在Python Web开发中,使用ORM如Django ORM能简化数据库操作。为了优化查询性能,可以:选择合适索引,避免N+1查询(利用`select_related`和`prefetch_related`),批量读取数据(`iterator()`),使用缓存,分页查询,适时使用原生SQL,优化数据库配置,定期优化数据库并监控性能。这些策略能提升响应速度和用户体验。
18 0
|
1月前
|
存储 缓存 自动驾驶
缓存策略与Apollo:优化网络请求性能
缓存策略与Apollo:优化网络请求性能
|
2月前
|
存储 缓存 监控
【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(场景问题分析+性能影响因素)
【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(场景问题分析+性能影响因素)
47 0
|
2月前
|
缓存 NoSQL Java
手撸的 SpringBoot缓存系统,性能杠杠的
手撸的 SpringBoot缓存系统,性能杠杠的
29 0