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

发布于:2025-05-17 ⋅ 阅读:(14) ⋅ 点赞:(0)

先说缓存是什么?

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

再说我们遇到的场景:

接手项目后,发现省市区前端调用,后台整合了全国数据进行返回。文件超过了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的查询。