在 Redis 中怎么实现代码出现异常时数据回滚 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
suyuanhxx
V2EX    Redis

在 Redis 中怎么实现代码出现异常时数据回滚

  •  
  •   suyuanhxx
    suyuanhxx 2016-12-01 10:47:23 +08:00 7761 次点击
    这是一个创建于 3301 天前的主题,其中的信息可能已经有所发展或是发生改变。

    场景:一段代码中有两处数据库操作(保存和更新,先保存后更新,两张表),保存数据库同时将数据保存到缓存,更新数据库时同时更新缓存。当更新数据库代码出现异常时,数据库可以使用事务的方式实现回滚,如果这时已经保存到缓存的数据怎么回滚?

    当然可以在异常捕获中删除缓存,这样子有点粗暴...

    如果是先更新后保存,缓存是不是回不去了?示意图我就不贴了,相信 V 站大神都能看懂

    第 1 条附言    2016-12-01 13:42:05 +08:00
    根据 @virusdefender 这位给出的资料,我已经有了思路,淘汰缓存-》先淘汰缓存,再写数据库,这样不容易出错(也能尽可能避免脏数据),但会增加缓存 miss 次数
    第 2 条附言    2016-12-01 19:59:27 +08:00
    附言中说的不是很对,好像要根据不同的场景,使用不同的缓存淘汰策略
    22 条回复    2018-11-13 16:08:30 +08:00
    suyuanhxx
        1
    suyuanhxx  
    OP
       2016-12-01 11:07:22 +08:00
    是不是节点选错了...
    server
        2
    server  
       2016-12-01 11:11:52 +08:00
    为啥已经要把缓存放到事务里
    lrh3321
        4
    lrh3321  
       2016-12-01 11:21:31 +08:00
    不是应该 更新 /保存 成功以后,再去更新缓存的吗?
    est
        5
    est  
       2016-12-01 11:36:30 +08:00   1
    coolshell 缓存更新的套路

    http://coolshell.cn/articles/17416.html
    suyuanhxx
        6
    suyuanhxx  
    OP
       2016-12-01 12:49:24 +08:00
    @server
    @lrh3321 公司代码习惯, service 层保存数据库时立马保存到缓存,防止忘记数据缓存
    suyuanhxx
        7
    suyuanhxx  
    OP
       2016-12-01 12:50:04 +08:00
    @est
    @virusdefender 3Q ,我去看看
    moro
        8
    moro  
       2016-12-01 13:05:57 +08:00
    redis 事务这章你看看能不能满足你的要求。
    https://redis.io/topics/transactions
    jyf
        9
    jyf  
       2016-12-01 13:18:18 +08:00
    mvvm
    suyuanhxx
        10
    suyuanhxx  
    OP
       2016-12-01 13:39:16 +08:00
    @moro redis 事务我们有用,但不是这个场景,并发更新缓存时使用。这个场景是读写数据库和缓存的问题
    Mirana
        11
    Mirana  
       2016-12-01 13:58:07 +08:00
    先更新数据库 在更新缓存,要不会有并发一致性的问题
    suyuanhxx
        12
    suyuanhxx  
    OP
       2016-12-01 13:59:52 +08:00
    @Mirana 你说的是应该是异步执行, pub sub 的模式?
    Mirana
        13
    Mirana  
       2016-12-01 14:24:02 +08:00
    @suyuanhxx 不是啊 业务里实现就可以,写不去更新缓存,写成功让缓存失效,读 miss 之后去数据库拉然后回种
    moro
        14
    moro  
       2016-12-01 14:36:35 +08:00
    先淘汰缓存,不能避免同时被读旧数据而载入缓存,还是会有脏数据。
    MrJing1992
        15
    MrJing1992  
       2016-12-01 15:01:18 +08:00
    先淘汰缓存也有问题的。
    suyuanhxx
        16
    suyuanhxx  
    OP
       2016-12-01 19:52:54 +08:00
    @Mirana 按照你的思路,写成功-》淘汰缓存-》如果更新失败-》数据库回滚,(如果更新成功也是一样)缓存一定 miss ,拉取数据库数据到缓存。那我们就要重新设计缓存思路,也就是只在读时将数据存到缓存,而且数据第一次被都读时缓存一定 miss 。或者将这一次存储时只存数据库。这样写代码不够优雅....(此处鬼脸)。如果先先更新,后保存就不适用了.....
    suyuanhxx
        17
    suyuanhxx  
    OP
       2016-12-01 19:58:40 +08:00
    @moro 高并发时会有脏数据产生,在淘汰掉缓存后和更新时第二张表时此时发生读操作,就会产生脏数据。可以使用 redis 中的事务 watch key 防止此时的都操作产生的脏数据。
    Mirana
        18
    Mirana  
       2016-12-01 23:41:09 +08:00
    @suyuanhxx 写成功,为什么会更新失败呢。 我说的写成功是指数据库事务都提交了才算。。
    suyuanhxx
        19
    suyuanhxx  
    OP
       2016-12-02 09:39:51 +08:00
    @Mirana 场景里面提到了,保存是一张表,更新是一张表,两张表都可能出错
    suyuanhxx
        20
    suyuanhxx  
    OP
       2016-12-02 09:44:04 +08:00
    @Mirana 如果保存和更新同时使用事务包裹,在这个事务执行时高并发情况下读的还是脏数据。而且我这个还是对整个 list 进行遍历读写....
    Mirana
        21
    Mirana  
       2016-12-02 17:55:53 +08:00
    @suyuanhxx 事务开始前淘汰缓存 然后执行事务 提交事务 这样不会有脏数据 但是要注意事务的隔离级别
    HansCathy
        22
    HansCathy  
       2018-11-13 16:08:30 +08:00
    两张表直接放两个事务啊,单事务会有问题
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5269 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 47ms UTC 08:09 PVG 16:09 LAX 00:09 JFK 03:09
    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