如何实现多级缓存以及缓存之间数据的一致性

文章目录

  • [神领物流 -- 如何实现多级缓存以及缓存之间数据的一致性](#神领物流 -- 如何实现多级缓存以及缓存之间数据的一致性)
    • [一. 为什么要使用多级缓存?](#一. 为什么要使用多级缓存?)
    • [二. 为什么要选择MongoDB作为数据库](#二. 为什么要选择MongoDB作为数据库)
    • [三. 如何缓存之间的一致性](#三. 如何缓存之间的一致性)
      • [1. 如何同步更新Redis缓存](#1. 如何同步更新Redis缓存)
      • [2. 如何同步更新CaffeineCache缓存](#2. 如何同步更新CaffeineCache缓存)

神领物流 -- 如何实现多级缓存以及缓存之间数据的一致性

采用用到的技术:

  • MongoDB
  • Redis
  • CaffeineCache

一. 为什么要使用多级缓存?

在我们的项目当中 ,特别是在电商大促期间,快件数量非常庞大,也就意味着查询人的量也是很大的 , 因此读查询接口造成的并发压力也会非常大 . 因此为了处理高并发问题在这采用了多级缓存

二. 为什么要选择MongoDB作为数据库

首先对于物流的订单流转信息其主体由一个运单号作为标识以及一个列表用来保存所有的运输信息 , 比如某货物在运输过程中从A送往B , 某货物已送达B点

这里如果使用mysql作为数据源我们就不可避免的需要将所有的运输信息保存在另一张表中 , 然后通过运单号进行查询 , 这对MySQL的性能开销会非常大

因此在这里采取了MongoDB作为数据库 , MongoDB的嵌套保存天然支持我们的业务需求 , 同时MongoDB在处理高并发上其性能也会优于MySQL

三. 如何缓存之间的一致性

在项目当中采用CaffeineCache作为一级缓存Redis作为二 级缓存 , MongoDB作为数据源

CaffeineCache --> Redis --> MongoDB

基于这个模型 , 也就是说的哪个MongoDB数据库中的数据被修改 , 那么我们就要对缓存进行同步更新

1. 如何同步更新Redis缓存

复制代码
/**
     * 如果运单数据不存在,就创建,否则更新数据
     *
     * @param transportOrderId 运单id
     * @param infoDetail       信息详情
     * @return 运输信息数据
     */
    @CachePut(value = "transport-info", key = "#p0")
    @Override
    public TransportInfoEntity saveOrUpdate(String transportOrderId, TransportInfoDetail infoDetail) {
        TransportInfoEntity mongoTemplateOne = mongoTemplate.findOne(Query.query(Criteria.where("transportOrderId").is(transportOrderId)), TransportInfoEntity.class);
        if (ObjectUtil.isEmpty(mongoTemplateOne)){
            mongoTemplateOne.setId(new ObjectId());
            mongoTemplateOne.setTransportOrderId(transportOrderId);
            mongoTemplateOne.setInfoList(ListUtil.toList(infoDetail));
            mongoTemplateOne.setUpdated(System.currentTimeMillis());
        }else {
            mongoTemplateOne.getInfoList().add(infoDetail);
        }
        //无论新增还是更新都要设置更新时间
        mongoTemplateOne.setUpdated(System.currentTimeMillis());
        //保存/更新到MongoDB
        return this.mongoTemplate.save(mongoTemplateOne);
    }

在对数据的更新同时我们使用SpringCache集成redis , 并使用其更新注解 @CachePut(value = "transport-info", key = "#p0")对redis数据同步更新 , 这样就解决了数据库与redis之间的缓存更新问题

2. 如何同步更新CaffeineCache缓存

对于CaffeineCache来说它是基于JVM级别的缓存 , 也就是说在搭建了集群后如果不对其同步很有可能导致不同机器上的CaffeineCache缓存数据不同

为了解决这个问题 , 我们通过使用redis内部的发布订阅来实现 , 也就是说每当Redis的数据被更新 , 我们就会向指定的key发生一个消息

其原理就是redis支持对key的订阅 , 同时可以进行监听 , 当该key发生变化时就会调用CaffeineCache删除指定运单的缓存

复制代码
/**
 * redis消息监听,解决Caffeine一致性的问题
 */
@Component
public class RedisMessageListener extends MessageListenerAdapter {
    @Resource
    private Cache<String, TransportInfoDTO> transportInfoCache;
    @Override
    public void onMessage(Message message, byte[] pattern) {
        //获取到消息中的运单id
        String transportOrderId = Convert.toStr(message);
        //将本jvm中的缓存删除掉
        this.transportInfoCache.invalidate(transportOrderId);
    }
}
相关推荐
码哥DFS2 小时前
LRU缓存
前端·javascript·缓存
进击的_鹏18 小时前
从零开始的 Redis 学习
服务器·数据库·c++·redis·缓存
摇曳的精灵20 小时前
前端缓存优化
前端·缓存·缓存优化
见山是山-见水是水1 天前
拆解网络缓存策略设计:原生鸿蒙页面的实现路径与调试方法
http·缓存·华为·harmonyos
T01156181 天前
艺培场馆课时预约小程序用户端 & 后台联动踩坑上篇(预约、课时、缓存、消息、学员端自身问题)
java·缓存·小程序·bug·全栈项目实战手记·艺培课时系统‘’
北漂燕郊杨哥1 天前
npm 缓存占满 C 盘?三步把它迁到 D 盘(附验证与避坑)
缓存·npm·node
克里斯蒂亚诺更新1 天前
win下如何将redis自启动
数据库·redis·缓存
晓晓_za8986682 天前
Geo 优化服务 CI/CD 流水线搭建:源码自动构建、测试与灰度发布
运维·服务器·tcp/ip·spring·缓存·ci/cd
nvd112 天前
LiteLLM 与 Redis 响应缓存机制:从精确哈希匹配到模型底层 KV-Cache 边界
redis·缓存·哈希算法