关于 MySQL 和 Redis 一致性问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Dganzh
V2EX    数据库

关于 MySQL 和 Redis 一致性问题

  •  
  •   Dganzh 2022-03-03 21:33:56 +08:00 3341 次点击
    这是一个创建于 1322 天前的主题,其中的信息可能已经有所发展或是发生改变。

    MySQL 作为 DB ,Redis 作为缓存,两个系统会存在一致性问题,最近想到一个方案, 大家说说这种方案有什么优缺点?

    写过程:

    1. 先抢锁( lua 搞):redis.setnx(lock_key)
      1.1 失败则自旋直至抢到成功
      1.2 成功,根据更新数据库所需时间设置过期时间,然后进入 2
    2. 更新数据库:db.update()
    3. redis.set(data_key)
    4. redis.del(lock_key)

    读过程(根据业务下面 3 选 1 ):

    1. 能接受旧数据的业务,则直接读缓存,redis.get(data_key)。
    2. 要求读到最新数据的业务,则先读 redis.get(lock_key ),如果为空则 redis.get(data_key)返回;不为空则直接读数据库,然后再 redis.setnx(data_key),也就是如果这里存在 data_key 则不设置缓存了。
    3. 上面 2 的过程 redis.get(lock_key)和 redis.get(data_key)之间可能存在其他的写过程,且刚好执行到 2 ,这时候仍可能读到旧数据。所以,这里可以同样先抢锁,redis.setnx(lock_key),抢到锁再 redis.get(data_key),为空则回源数据库然后再设到 redis 。
    10 条回复    2022-03-04 14:31:42 +08:00
    fishCatcher
        1
    fishCatcher  
       2022-03-03 22:06:09 +08:00 via iPhone   1
    2 回写 redis 的时候如果 db 被更新,那你回写的就是脏数据,后面读到的都是脏数据,肯定是不对的。

    3 加锁会阻塞所有其他读写,toc 业务不建议用。

    这种一般都有现成的方案,不建议自己造轮子。
    bxb100
        2
    bxb100  
       2022-03-03 22:38:07 +08:00
    延时双删
    9c04C5dO01Sw5DNL
        3
    9c04C5dO01Sw5DNL  
       2022-03-03 23:05:43 +08:00   1
    现成方案,不要造轮子。

    非严格一致可以参考现成方案
    https://coolshell.cn/articles/17416.html
    bigbyto
        4
    bigbyto  
       2022-03-04 00:45:09 +08:00
    你这相当于把操作串行了,而且可靠性依赖 redis 的锁,但 redis 的锁并不可靠。A 获得锁,此时发生 gc stop the world ,锁过期,此时 B 获得锁成功。

    这问题的本质就是同时更新两个数据源,如果要求严格的一致性,就需要把所有的操作作为一个原子操作提交,这个实际上是很困难的,比如你可以引入 NPC 协议,这样系统复杂度会大大增加且引入了新的单点,只能在性能和一致性之间做 trade off
    Maboroshii
        5
    Maboroshii  
       2022-03-04 02:09:04 +08:00 via Android
    最终一致,不要管 mysql 了 纯 redis 操作
    Brian1900
        6
    Brian1900  
       2022-03-04 03:51:48 +08:00
    是不是 redis 没用对地方
    Tenlearn
        7
    Tenlearn  
       2022-03-04 09:50:09 +08:00
    @bxb100 延时双删实践上就是扯淡,除了串行没有任何方案能保证完全一致,还是要加过期时间
    leafre
        8
    leafre  
       2022-03-04 10:53:51 +08:00
    必须强一致性,用粗粒度锁,并发冲突概率极大,性能肯定差,实际生产肯定不这样使用。
    xuanbg
        9
    xuanbg  
       2022-03-04 12:50:03 +08:00
    对于缓存的作用,我发现有很多人其实走进了误区。我们在使用缓存的时候,一定要先明确一点:缓存是用来加速的,仅此而已!
    当你给缓存数据赋予更多的职责的时候,缓存也就不是缓存,而是内存数据库了。两个数据库如何保持一致,这是数据库层面的问题,不要在业务层面去解决。不然业务逻辑将会无比复杂,而且根本就没有完美解决方案。

    如果你 redis 里面的数据只是缓存,那么就要在享受高效读的好处时,就必须要接受缓存数据不够实时带来的一系列问题。
    如果你把 redis 当内存数据库使用,就要接受掉电丢数据的结果。又想读写快,又不想意外丢数据,你想啥呢!
    sunqb
        10
    sunqb  
       2022-03-04 14:31:42 +08:00
    为什么需要保证强一致性?你的业务如果有这个需求,就不应该上 mysql 了,直接 oracle 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5196 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 03:46 PVG 11:46 LAX 20:46 JFK 23:46
    Do have faith in what you're doing.
    ubao msn 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