经常面试被问到缓存和 db 数据一致性的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
noble4cc
V2EX    Java

经常面试被问到缓存和 db 数据一致性的问题

  •  
  •   noble4cc 2020-07-29 11:42:57 +08:00 5813 次点击
    这是一个创建于 1900 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如说缓存和数据库保持数据一致性,感觉只要是用缓存,这个一致性永远无法保证实时一致性

    还有问先更新数据库再更新缓存,更新缓存失败了怎么办,感觉使用缓存永远无法保证缓存永远的一致性呀,总会有时间差,要要求强一致性就别用缓存了

    27 条回复    2023-10-31 13:57:38 +08:00
    594duck
        1
    594duck  
       2020-07-29 12:19:44 +08:00
    用 MQ
    gantleman
        2
    gantleman  
       2020-07-29 12:46:58 +08:00
    强一致很简单,在缓存外加把锁把所有请求都挡在外面就强一致了。什么外面的请求不能等需要立即返回,哪就再加个缓存。什么第二个缓存也要强一致!!哪就再加个锁,什么第二个锁外面的请求也不能等???要加第三个缓存!!!有时候我觉得我在做开发,有时候我觉得我在做套娃。套娃就是开发,摸鱼就是真理。
    noble4cc
        3
    noble4cc  
    OP
       2020-07-29 14:01:21 +08:00
    @594duck 只要异步就有时差,无法做到实时一模一样
    Octopvs
        4
    Octopvs  
       2020-07-29 16:10:16 +08:00
    更新完数据库,就删掉缓存,下次访问的时候从数据库获取再更新到缓存
    xkeyideal
        5
    xkeyideal  
       2020-07-29 16:22:07 +08:00
    @Octopvs 也要考虑缓存击穿场景
    DoctorCat
        6
    DoctorCat  
       2020-07-29 16:28:23 +08:00   1
    CAP 到底牺牲哪个,根据业务场景来定了。优先看最终一致性能不能行
    xkeyideal
        7
    xkeyideal  
       2020-07-29 16:34:53 +08:00
    缓存与数据库之间的实时一致性或强一致性应该是无法实现的。
    既然用到了缓存,说明数据的变化不是频繁的或者可以容忍一段时间内的数据不一致,否则缓存就失去了使用的价值。
    缓存数据不应该是永久存在的,应该设置一个过期时间,这样能比较好的解决数据不一致的问题。
    个人理解缓存分为两种,一种是内存级缓存,一种是外部缓存,如 redis 。
    内存级缓存应该不会存在更新失败这么一说。
    外部缓存,更失败的大部分情况是由于网络问题,但又涉及到多个客户端更新同一份缓存的情况,使用外部缓存尤其要考虑数据的变化频繁程度,否则即使更新成功也会出现缓存是脏数据的情况。

    要不要使用缓存,如何使用缓存,是需要根据业务场景具体对待,有些时候,内存级缓存简单高效,而且不易出错,使用上外部缓存就需要考虑多读多写的场景了。
    8355
        8
    8355  
       2020-07-29 17:10:33 +08:00
    不管是内存 io 还是硬盘 io 都需要时间
    如果是同步要求一致性, 那么为什么要存 db 直接存缓存不就好了吗?
    db 存在的意义就没有了.
    因为要强一致那么就是这个场景和结果.

    你这个问题要么就是没描述清楚条件和约束 要么就是面试官提的伪需求.
    tabris17
        9
    tabris17  
       2020-07-29 17:11:05 +08:00   1
    别问,问就是“最终一致性”
    ZehaiZhang
        10
    ZehaiZhang  
       2020-07-29 17:12:23 +08:00
    加钱升数据库配置吧
    Jooooooooo
        11
    Jooooooooo  
       2020-07-29 17:14:03 +08:00
    保持不了就最终一致

    那最终一致怎么做方案就来了
    eaglewangl37670
        12
    eaglewangl37670  
       2020-07-29 17:28:32 +08:00
    我记得我面试的时候也有很多面试官喜欢问这个问题,我也确实没有给出一个较好的解决方案- -
    lihongming
        13
    lihongming  
       2020-07-29 17:38:06 +08:00 via iPhone
    有些云数据库自带缓存服务,并提供 write-through 缓存模式,可以保证数据更新时缓存也更新。

    不过我觉得这可能就是加了个 trigger
    xupefei
        14
    xupefei  
       2020-07-29 18:04:24 +08:00 via iPhone
    用数据库的 trigger 改缓存,失败就回滚啊,一定能保证一致性。
    CoderGeek
        15
    CoderGeek  
       2020-07-29 18:23:39 +08:00
    要么降低性能做强一致 要么老实的接受 BASE
    keshawnvan
        16
    keshawnvan  
       2020-07-29 19:10:20 +08:00
    不在一个事务,隔离级别也不一样,自然保证不了强一致性。
    realpg
        17
    realpg  
    PRO
       2020-07-29 23:18:59 +08:00
    最简单的,性能可能渣点
    读锁,然后删缓存,然后更新数据库行,提交释放锁。
    jones2000
        18
    jones2000  
       2020-07-30 00:36:32 +08:00
    这和一台 mysql (这台看成是缓存) 同步到另外一台 mysql 一样, 一般都基于日志同步的, 你增加缓存日志,最后根据缓存日志来同步,基本可以一致的。
    noble4cc
        19
    noble4cc  
    OP
       2020-07-30 11:48:07 +08:00
    @Octopvs 对,这样也行,或者直接更新缓存也行,但是对方会问你更新缓存失败或者淘汰缓存失败怎么办,当然我知道,平时他开发也就是更新缓存
    noble4cc
        20
    noble4cc  
    OP
       2020-07-30 11:58:07 +08:00
    @tabris17 最终一致性还是要查 db,当然缓存在有些业务场景下可以过滤掉大部分流量
    huobazi
        21
    huobazi  
       2020-07-30 16:32:06 +08:00
    号称 9999999 想想为什么涅?
    zichen
        22
    zichen  
       2020-07-30 18:21:48 +08:00
    最稳妥的方式就是写进程写数据库然后删缓存,读进程读缓存失败再读数据库再回写缓存。
    zichen
        23
    zichen  
       2020-07-30 18:24:37 +08:00
    @noble4cc 淘汰缓存失败可以放入消息队列,用定时任务做补偿。
    Octopvs
        24
    Octopvs  
       2020-07-30 20:26:53 +08:00
    @xkeyideal 用布隆过滤器解决击穿
    xkeyideal
        25
    xkeyideal  
       2020-07-31 08:55:23 +08:00
    @Octopvs 这是什么骚操作,从来没听过,能解释一下,请教如何使用
    noble4cc
        26
    noble4cc  
    OP
       2020-07-31 14:25:47 +08:00
    @zichen 对,更新缓存和淘汰缓存都可以,淘汰缓存更方便,但是对方肯定会问你淘汰缓存失败了不就 db 和缓存不一致了吗
    vanpeisi7
        27
    vanpeisi7  
       2023-10-31 13:57:38 +08:00
    @Octopvs 多个线程同时更新,A 和 B 都更新这种问题也不行。1.A 获取缓存 ; 2.B 获取缓存; 3.B 更新数据库、删除缓存; 4.A 更新数据库(用的数据是早先从缓存获取的),删除缓存
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     866 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 20:26 PVG 04:26 LAX 13:26 JFK 16:26
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86