Java服务_数据服务缓存策略实战梳理与常见分布式缓存实现方案
1.hbase服务缓存策略
1. 将请求参数进行排序
1 | //将请求参数进行排序 |
其中这个将请求参数进行排序方法sortReqToString,本质就是将object类型按key的字典序排序,将array类型按元素的字典序排序。有一个点要注意就是每个请求参数中唯一化的参数注意要去掉,比如请求时间、uuid等。
1 | public static String sortReqToString(JSONObject reqParam){ |
重要:此处根据服务名给请求同一个服务的所有入参打上了统一的后缀,这样方便按照后缀一次性删除一个服务的所有缓存。在设计缓存系统时一定要预留一个清空缓存的方法,有的时候线上方法返回数据时错误的,改正重新上线之后必须要清空缓存才行。
2.缓存中有就直接从缓存中取JSONObject类型的请求结果
1 | // 先从缓存中查询 |
3.缓存中没有走数据服务请求一遍数据库,并将请求结果存入缓存中
1 | CacheUtil.putCache(cacheKey, obj, cacheRule, tags); |
2.ck服务缓存策略
使用公司内部基于方法的服务缓存,原理与spring@Cache类似,就是将一个方法的入参作为缓存key,返回作为缓存value,当有相同的入参请求时直接返回缓存结果,不需要进入方法体内部执行方法代码。是一个适用于分布式服务的缓存。
配置缓存方法
1 | (expiredTimeStr = "0 0 8 * * ?", validator = JudgeBlankValidator.class) |
在这个缓存方法内部和外部分别加一层监控或者日志记录就可以轻松地统计缓存命中率了。
CacheConfiguration
CacheConfiguration中是对缓存redis集群、缓存ttl等参数的初始化配置类,这个是公司组件当中封装好的,直接用即可。
1 | public class CacheConfiguration { |
3.实时离线对比榜单二级缓存
背景:有一个交易&浏览top200sku&spu商品实时榜单,每6s会根据数据情况实时更新一次,同时还需要提供每个商品的同比&环比日期离线数据。对于数据服务来说,top200商品数据是一个方法一次查询直接出的,那么对于方法粒度的缓存命中率非常低,因为每次请求的200个商品只要有任意一个变动都会时缓存不命中。
在上述背景之下考虑添加商品粒度的二级缓存,该二级缓存的存储粒度为单个商品粒度的指标数据,那么方法思路即为一级缓存未命中时,将200个商品轮询请求缓存,命中的商品直接加入返回结果,未命中的放在一起最终再一次性请求数据库,再将返回的数据按商品粒度逐个存入缓存。
1 | //添加二级缓存 |
4.常见分布式缓存实现方案
4.1 缓存重要指标

缓存最重要的两个指标就是缓存命中率和移除策略。
命中率是指从缓存中读取次数与总读取次数的比值,命中率越高越好。
移除策略是指缓存中的数据如果删除的策略,主要有四种:
1)FIFO先进先出
2)LRU最久未使用先出
3)LFU被使用次数最少的先出
4)TTL按指定时间自动过期
4.2 基于Redis实现分布式缓存
4.2.1 搭建环境
添加核心依赖
1 | <dependency> |
配置redis
1 |
|
4.2.2 缓存实现
实现流程非常简单,就是先请求缓存,命中则直接返回,未命中则请求DB并存入缓存。
1 |
|
4.2.3 数据库增删改联动
缓存中数据key对应value需要变动时,需要将缓存中的该数据删除,而且需要使用双删保证,防止在删除缓存与更新数据库的间歇中又有对该数据的请求,导致缓存中仍旧继续存储更新前的数据。
1 | //更新:确保机制:实行双删 |
4.3 基于Spring Cache实现缓存
4.3.1 Spring Cache介绍
Spring Cache是Spring框架提供的辅助缓存快捷实现的封装接口,本身还是需要我们基于它的规则提供和配置redis等缓存集群。它具有:1)基于注解,代码清爽简洁;2)支持多种缓存产品,Guava、EhCache、Redis等;3)可以实现复杂逻辑;4)可以对缓存进行回滚等优点。
Spring Cache支持的常用注解:
- @Cacheable //查询
- @CachePut //增改
- @CacheEvict //删除
- @Caching //组合多个注解
- @CacheConfig //在类上添加,抽取公共配置
4.3.2 Spring Cache使用代码案例
创建配置类
1 |
|
在service层实现类的方法上添加缓存注解
1 |
|
4.3.3 Spring Cache缺点
任何一种技术都不是十全十美的,Spring Cache也不例外,它也有一些缺点:1)不能保证数据的一致性,添加和修改数据时,是先修改数据库,然后再进行更新缓存,如果不满意延迟导致过程中的数据不一致性问题,需要自行实现双删;2)过期时间都是统一配置,需要自行实现个性化过期时间设置。