记一次缓存填坑省市区级联获取的操作

先说缓存是什么?

缓存主要是解决高并发,大数据场景下,热点数据快速访问。缓存的原则首先保证数据的准确和最终数据一致,其次是距离用户越近越好,同步越及时越好。

再说我们遇到的场景:

接手项目后,发现省市区前端调用,后台整合了全国数据进行返回。文件超过了1MB。喊着前端同事进行整改,更改成选择哪个获取下级的级联方式,前端的大爷们不配合。哎!催不动啊!你知道不合理但是优化不了。只能在不合理的基础上进行优化。

指导思想:借鉴nacos的配置中心,通过版本号识别是否产生更改,进行数据同步。

这个方案改动比较小,仅额外增加了一个版本号字段,无特殊逻辑,前端接受了。

数据都存储在哪儿了

第1层:客户端缓存

app缓存了全量的数据。

检测是否需要更新时,根据版本号查询后台数据,响应了具体数据就进行本地数据更新,否则保持原状。

缓存的构建和更改: 根据版本号调用后台服务,返回了非空的数据,进行缓存数据的更新。

第2层:nginx缓存

我们通过nginx配置,控制nginx自动缓存了这个版本号对应的数据,有效期是24小时。nginx缓存我们并没有进行手动清理,因为改动不频繁,并且能容忍24小时的时间差。真的想要立刻生效,就手动去进行nginx的缓存删除。

缓存的构建:数据查询完成,缓存对应的请求网址和响应结果。

缓存内容:

初始化后缓存内容: 老版本号/新版本号=空数据,空版本号=全量数据+新版本号

数据更改后缓存内容:空版本号/老版本号=全量数据+新版本号,新版本号=空数据。(缓存未清理则有延时)

第3层:本地服务的缓存

本地服务采用Ehcache,未配置失效时间。

缓存内容:最新版本号/最新数据。

查询操作:比对传入版本号是否和最新版本号相同,相同则返回空对象,否则返回全量数据

缓存的构建:当前缓存无数据,根据redis查询的结果,进行本地缓存的重建。

缓存的清理:redis数据构建完毕,通过loadBalance读取eureka服务名称对应的所有节点信息,轮询调用所有服务的数据清理接口。

第4层:分布式缓存redis

本地服务采用redis缓存,未配置失效时间。

缓存内容:最新版本号/最新数据。

业务操作:比对传入版本号是否和最新版本号相同,相同则返回空对象,否则返回全量数据。

缓存的构建:当查询redis无数据时,双重检查锁防击穿,查询数据库,进行redis缓存的构建。

缓存的清理:产生数据库更新操作时,进行redis缓存的清理动作。

第5层:真实的数据库

更新操作:进行数据库的数据更新,调用redis的重新构建方法,集群轮询调用本地缓存清理方法。

查询操作:查询数据库,组装前端期望的对象。

这样搭建的效果:

当客户端进行请求时, 调用nginx, nginx检测自己的缓存, 根据缓存返回数据。

nginx缓存失效(1天失效一次),服务器本地缓存查询并返回。

服务器本地缓存失效(服务重启),通过redis查询并返回。

redis数据失效(redis被清理),根据数据库进行缓存的构建,并返回。

数据没有产生变更,用户持有的是最新的版本号,大部分场景下返回的都是空对象,减少了海量的io和网络资源的消耗。

同时这个模型像是一个倒置的漏斗, 无论nginx接受了多少请求,相同的请求地址,一天最多放行了1个,撑住了绝大部分的请求流量,nginx每天放行的一个,也被本地缓存命中,减少了redis的查询。

相关推荐
迎風吹頭髮9 分钟前
Linux内核架构浅谈49-Linux per-CPU页面缓存:热页与冷页的管理与调度优化
linux·缓存·架构
码农多耕地呗1 小时前
力扣146.LRU缓存(哈希表缓存.映射+双向链表数据结构手搓.维护使用状况顺序)(java)
数据结构·leetcode·缓存
洲覆9 小时前
Redis 内存淘汰策略
开发语言·数据库·redis·缓存
此心光明事上练13 小时前
大厂级企业后端:配置变更与缓存失效的自动化处理方案
运维·缓存·自动化
不良人天码星14 小时前
redis的事务,以及watch的原理
数据库·redis·缓存
doris820415 小时前
使用Yum安装Redis
数据库·redis·缓存
Boilermaker199215 小时前
【Redis】哨兵与对脑裂的情况分析
数据库·redis·缓存
摇滚侠15 小时前
Spring Boot 3零基础教程,WEB 开发 内容协商机制 笔记34
java·spring boot·笔记·缓存
2401_837088501 天前
Redis通用命令
数据库·redis·缓存
来旺2 天前
互联网大厂Java面试全解析及三轮问答专项
java·数据库·spring boot·安全·缓存·微服务·面试