V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
luxinfl
V2EX  ›  程序员

不考虑多线程的话,缓存是不是应该这样写

  •  
  •   luxinfl · 2020-07-22 14:16:50 +08:00 · 2637 次点击
    这是一个创建于 1576 天前的主题,其中的信息可能已经有所发展或是发生改变。

    更新操作:先更新 A 信息,然后再从库里查询 A 所有字段,然后放入 redis 缓存??有没有更好的做法?

    public void updateMerchantInfo(TbUserInfo tbUserInfo) {
    
            //更新商户信息
            tbUserInfoMapper.updateByPrimaryKeySelective(tbUserInfo);
    
            //缓存更新后的数据
            TbUserInfo merchantInfo = tbUserInfoMapper.getOneByCondition(tbUserInfo);
            String redisKey = ZbpsConstant.RedisConstants.STORE_INFO + merchantInfo.getPlatformCode() + merchantInfo.getPlatformUserCode();
            if(merchantInfo != null){
                RedisUtils.set(redisKey,GsonUtils.objectToJson(merchantInfo),24*3600);
            }
    }
    
    19 条回复    2020-07-23 22:04:15 +08:00
    wangltfwow
        1
    wangltfwow  
       2020-07-22 14:26:24 +08:00
    这样也可以其实,但缓存的操作都统一放到注解上会优雅点
    luxinfl
        2
    luxinfl  
    OP
       2020-07-22 14:34:18 +08:00
    @wangltfwow 用 spring 自带的注解吗?我看了那几个常用的,没有那种更新后自动加载的吧。
    dallaslu
        3
    dallaslu  
       2020-07-22 14:36:12 +08:00
    @luxinfl CachePut 了解一下
    luxinfl
        4
    luxinfl  
    OP
       2020-07-22 14:47:54 +08:00
    @dallaslu CachePut 放在 update 方法上面吗?这个也只能缓存入参吧
    myCupOfTea
        5
    myCupOfTea  
       2020-07-22 15:24:08 +08:00
    我们是自己写的注解 也不难,,
    yidinghe
        6
    yidinghe  
       2020-07-22 15:33:09 +08:00
    缓存 API 的两种封装方式:

    1. 注解封装,自己实现难度很高,一般直接使用 Spring 的 @Cacheable 注解 https://www.baeldung.com/spring-cache-tutorial

    2. LoadingCache 方式,将 if-else 判断封装为参数。下面是一个例子:

    TbUserInfoCache cache = new TbUserInfoCache();
    TbUserInfo info = cache.get(key, (_key) -> tbUserInfoMapper.query(_key));

    这个 get() 方法接受两个参数,如果缓存中存在则直接根据 key 返回缓存内容,否则调用第二个参数查询数据,放入缓存再返回。
    JasonLaw
        7
    JasonLaw  
       2020-07-22 15:37:42 +08:00
    我们是使用 canal 统一管理缓存的清除,在调用方法前判断是否存在缓存,没有就获取 MySQL 的数据,然后缓存起来。在方法里面处理缓存相关的逻辑,个人觉得不太好,就像 AOP 一样,不要污染业务逻辑。
    luxinfl
        8
    luxinfl  
    OP
       2020-07-22 16:37:45 +08:00
    @myCupOfTea 是不难,这不过这样不封装写起来确实挺难看的。
    RedBeanIce
        9
    RedBeanIce  
       2020-07-22 16:39:54 +08:00
    Spring 的 @Cacheable 个人是不使用的。

    除非很简单,但是没有那个习惯。
    daimubai
        10
    daimubai  
       2020-07-22 16:43:55 +08:00
    我也是不用 Spring 注解的。
    删除缓存 -> 更新数据库 -> 刷新到缓存,这种解决方法适合并发量不高的情况
    yiyi11
        11
    yiyi11  
       2020-07-22 17:06:41 +08:00 via Android   ❤️ 3
    更新操作只删除缓存,更新缓存由读操作完成。
    dallaslu
        12
    dallaslu  
       2020-07-22 17:59:26 +08:00
    @luxinfl 用 CachePut 的话,可以在方法里 return 要返回的值,然后把 result 写入缓存。或者在 update 方法上用 CacheEvict 注解,另有查询方法用 Cacheable 注解
    312ybj
        13
    312ybj  
       2020-07-22 18:25:43 +08:00
    redis 跟 Spring 有集成, 使用注解就行,楼上的方法就行
    wysnylc
        14
    wysnylc  
       2020-07-22 18:53:09 +08:00
    Sping Cache 有 jdkpoxy 的 this 问题和单 key 无法设置过期时间问题,其他的很不错
    DixCouleur
        15
    DixCouleur  
       2020-07-22 18:54:41 +08:00
    歪个楼,问一下,TbUserInfo 这个变量名的 Tb 前缀是什么意思,在好多地方看见过
    iweisi
        16
    iweisi  
       2020-07-23 08:53:47 +08:00
    @DixCouleur table 的缩写
    luxinfl
        17
    luxinfl  
    OP
       2020-07-23 09:03:39 +08:00
    @yiyi11 那读操作每次都要去查数据库?这不合理吧。
    MeowOvO
        18
    MeowOvO  
       2020-07-23 12:08:21 +08:00
    @luxinfl 读操作读到缓存就不查数据库了- -
    yiyi11
        19
    yiyi11  
       2020-07-23 22:04:15 +08:00
    @luxinfl 为什么会每次查数据库?第一次读操作产生了缓存,后面就一直读缓存。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1509 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 17:21 · PVG 01:21 · LAX 09:21 · JFK 12:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.