-
通过采用 Cache Aside 模式,确保数据库更新后及时失效相关缓存,保证数据库和缓存的一致性
-
**常见缓存 : **
-
JDK 自带的 HashMap 和 ConcurrentHashMap
-
Ehcache、Guava Cache、Spring Cache、Caffeine 等常见的本地缓存框架
Cache Aside 模式优点和局限
优点
- 1. 读取性能高:
- 缓存命中时可以直接从缓存中读取数据,速度非常快,显著减少了数据库的访问压力。
- 2. 实现简单:
- 该模式逻辑清晰,容易理解和实现,只需在读取和写入操作时分别处理缓存和数据库即可。使用的也比较多的一种方案了。
- 3. 灵活性强:
- 程序员可以根据需要灵活地控制缓存的更新和失效策略,适应不同的应用场景和需求。
- 4. 缓存利用率高:
- 只有在缓存未命中时才从数据库读取数据并更新缓存,避免了不必要的数据冗余。
局限
- 1. 写操作较慢:
- 每次写操作都需要更新数据库并使缓存失效,这样的操作过程较长,导致写操作性能较低。
- 2. 数据一致性挑战:
- 缓存和数据库之间可能会出现数据不一致的情况,特别是在高并发环境下,更容易出现缓存失效不及时或者更新顺序问题。
- 3. 缓存预热问题:
- 初始时缓存为空,第一次读取时会有较大的延迟,直到缓存被逐渐填充起来。所以热点数据建议直接放入缓存
- 4. 复杂的失效策略
- 程序员需要设计合理的缓存失效策略,以确保缓存的数据及时更新,这增加了实现和维护的复杂性。具体怎么设置失效策略又体现了经验了。
- 5. 过期数据风险:
- 如果没有合适的失效机制,缓存中可能会存在过期数据,从而返回错误或过时的信息给用户。
PmHub最佳实践
数据读取
- 先查询缓存,如果有就直接返回,没有就去数据库查询,然后再写入缓存。
/**
* 根据键名查询参数配置信息
*
* @param configKey 参数key
* @return 参数键值
*/
@Override
public String selectConfigByKey(String configKey) {
String configValue = Convert.toStr(redisService.getCacheObject(getCacheKey(configKey)));
if (StringUtils.isNotEmpty(configValue)) {
return configValue;
}
SysConfig config = new SysConfig();
config.setConfigKey(configKey);
SysConfig retConfig = configMapper.selectConfig(config);
if (StringUtils.isNotNull(retConfig)) {
redisService.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
return retConfig.getConfigValue();
}
return StringUtils.EMPTY;
}
数据更新
- 更新数据的时候,先去更新数据库信息,然后再删除缓存
/**
* 批量删除参数信息
*
* @param configIds 需要删除的参数ID
*/
@Override
public void deleteConfigByIds(Long[] configIds) {
for (Long configId : configIds) {
SysConfig config = selectConfigById(configId);
if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
}
configMapper.deleteConfigById(configId);
redisService.deleteObject(getCacheKey(config.getConfigKey()));
}
}