您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 
 订阅
如何优雅地编写缓存代码
 
作者 :巧凡
   次浏览      
 2024-5-23
 
编辑推荐:
本文主要介绍了编码过程中,如何将缓存代码从业务代码中剥离出来,促使代码更简洁,更便于阅读。希望对你的学习有帮助。
本文来自于微信公众号阿里技术,由火龙果软件Linda编辑、推荐。

01 前言

在日常的编码实践中,经常会用到缓存来解决高并发问题,缓存可以说是解决流量洪峰的不二利器。虽然集团中间件团队已经构建了缓存的基础设施,已经帮助我们解决了绝大部分问题,但是在实际的编码使用过程中,应用端调用缓存API时还是存在下述几类问题:

使用缓存的逻辑非常通用,基本都是先查缓存,有直接返回,没有查DB,再放入缓存中。这段通用逻辑散落在系统的各个地方,违反了高内聚低耦合的原则。

缓存代码和业务逻辑代码深度耦合在一起,不仅降低了代码的可读性,还额外增加了系统复杂度。

如果要切换缓存(MDB->LDB)或者API升级时,所有涉及代码都需要改动。

如果要解决缓存击穿、缓存穿透、级联缓存等类似通用问题时,都需要通过框架去解决。

因此,缓存是什么,如何选择某一种缓存,都不是本文重点,今天就写写实际编码过程中,如何将缓存代码从业务代码中剥离出来,促使代码更简洁,更便于阅读。

02 实践分析

先读取缓存数据,如果有数据则直接返回,如果没有读取到数据,则读取DB数据,等数据返回后,再更新缓存。

这种场景,在日常编码中,很常见,太简单,但是实际的代码确实很不一样,列举如下几种:

2.1 传统写法

使用什么缓存,就直接使用,嵌入到业务代码中。这种代码不管是code review,还是后人学习业务代码时,都不想看,道理很简单,跟实际的业务功能无关,我不想知道你用什么缓存,你是怎么编码缓存代码的。

2.2 高级一点的写法

相比传统的写法,为了解决缓存各种数据格式(List、Map等),各种对象序列化问题(java、json),团队内可以针对缓存这块,封装成简单的API,方便大家使用。使用简单了,但代码依然嵌入在业务代码中,没有剥离出来。

2.3 注解写法

最后是注解写法,相对前两种写法,代码已从业务代码中剥离出来,阅读代码的人,只会关心业务功能是如何实现的,使用哪个缓存,如何实现的,完全可以忽略。

03 spring cache方案分析

spring cache利用动态代理的方式,在代理类中处理缓存的相关操作,同时调用被代理类中的方法,从而可以使操作缓存的代码和业务代码分离,并且后期需要强化缓存能力时,也只需要修改代理类中的方法即可。

以上就是Spring Cache的原理。Spring Cache是Spring提供的通用缓存框架。它利用了AOP,实现了基于注解的缓存功能,使开发者不用关心底层使用了什么缓存框架,只需要在方法上简单地加一个注解,就能实现缓存功能了。用户使用Spring Cache,可以快速开发一个很不错的缓存功能。

3.1 代码目录

3.2 注解导图

3.3 注解使用示例


@Cacheable(value = "user_cache", unless = "#result == null")
public User getUserById(Long id) {
   return userMapper.getUserById(id);
}
@CachePut(value = "user_cache", key = "#user.id", unless = "#result == null")
public User updateUser(User user) {
   userMapper.updateUser(user);
    return user;
}
@CacheEvict(value = "user_cache", key = "#id")
public void deleteUserById(Long id) {
   userMapper.deleteUserById(id);
}

 

3.4 方案分析

Spring Cache的功能很强大,设计也非常优雅。特别适合缓存控制没有那么细致的场景,比如偏静态展示页面,点赞数、排名等等,这些场景的特点是对数据实时性没有那么严格的要求,只需要将数据源缓存下来,过期之后自动刷新即可。这些场景下,Spring Cache就是神器,能大幅度提升研发效率。

但在高并发大数据量的场景下,精细的缓存颗粒度的控制上,还是需要做功能扩展。

多级缓存;

缓存定期刷新;

列表缓存;

缓存cpp保护机制;

缓存计数。



例如:Spring Cache并没有二级缓存的实现

04 自定义cache方案

学习spring cache框架方案,实现自定义cache框架,不仅保留spring cache框架的优点,同时实现spring cache很多缺失的能力,例如缓存击穿、缓存穿透保护,多级缓存等。

4.1 注解代码示例

4.2 方案架构

05 在最后面

借助spring cache实现方式,构建自定义缓存框架,扩展了很多注解,例如计数、缓存刷新、列表缓存、分布式锁、多级缓存等,不仅实现了缓存代码和业务代码的分离,同时拓展了spring缓存的能力,极大的提升了代码的可读性,降低了缓存代码维护的效率。

 

 

   
次浏览       
相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程


最新活动计划
C++高级编程 12-25 [线上]
白盒测试技术与工具实践 12-24[线上]
LLM大模型应用与项目构建 12-26[特惠]
需求分析最佳实践与沙盘演练 1-6[线上]
SysML建模专家 1-16[北京]
UAF架构体系与实践 1-22[北京]
 
 
最新文章
代码整洁 vs 代码肮脏
代码审计--源代码审计思路
代码审计思路
代码重构之道
clean code代码整洁
最新课程
设计模式原理与应用
从需求过渡到设计
软件设计原理与实践
如何编写高质量代码
单元测试、重构及持续集成
更多...   
成功案例
某企业 基于IPD的嵌入式软件开发
某企业 自我认知、情绪管理和沟通
某企业 思维导图方法与实践
中盛益华 卓越管理者必须具备的五项能
世纪高通 创新创造突破性产品——体系
更多...