现在有没有新的机制来确保一条记录只被处理一次 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
muziling
V2EX    程序员

现在有没有新的机制来确保一条记录只被处理一次

  •  
  •   muziling 2020 年 4 月 2 日 3527 次点击
    这是一个创建于 2181 天前的主题,其中的信息可能已经有所发展或是发生改变。
    单线程,或多线程,怎么保证一条记录只被处理一次
    目前是 处理前把记录状态改为处理中,并判断 update 返回值是否为 1, 是的话,开始处理,否则跳过此记录

    这种方法一条记录就要 update 一次,性能会有损失,而且如果在处理时,程序强制重启了,会造成处理中的记录是否有处理成功并不知道。

    现在 2020 年了,有没有新的解决方案?
    20 条回复    2020-04-02 18:11:30 +08:00
    fancy111
        1
    fancy111  
       2020 年 4 月 2 日
    都 2020 年了,你还来问这个问题,连百度收录的都是三五年前的解决方案了。
    muziling
        2
    muziling  
    OP
       2020 年 4 月 2 日
    @fancy111 求指教,搜索到的很多时候要花很大精力筛选
    loryyang
        3
    loryyang  
       2020 年 4 月 2 日
    重点看你的处理是什么,要多严格的 just once
    muziling
        4
    muziling  
    OP
       2020 年 4 月 2 日
    @loryyang 最严格和 允许异常重启时重复一次 ,方案分别是什么, 想了解下,有个底。
    index90
        5
    index90  
       2020 年 4 月 2 日
    用 token
    同一时间,只有一个 worker 获得有效 token
    worker 可以利用 token 修改该 task 的状态和访问其相关资源
    dapang1221
        6
    dapang1221  
       2020 年 4 月 2 日
    现成的消息队列怎么不用…处理完后回复 ACK 确认
    ThirdFlame
        7
    ThirdFlame  
       2020 年 4 月 2 日
    那不就和 人工作业一样么,有 worker 处理了,那设置个标记说明 处理中。 等处理完成了,把标记置为完成。
    jugelizi
        8
    jugelizi  
       2020 年 4 月 2 日 via iPhone
    无非是单线程
    或者锁
    muziling
        9
    muziling  
    OP
       2020 年 4 月 2 日
    @index90 没能理解,多个 worker,分别执行不同的 task, token 怎么做,或者能给个搜索的关键字吗?
    looplj
        10
    looplj  
       2020 年 4 月 2 日
    上面的说法跟 LZ 提的没看出有什么区别

    单线程也很难就直接保证了,没有考虑 处理完成,但是更新状态失败这个问题。

    要 Exactly Once 基本是要业务层保证,幂等,可 redo
    NeinChn
        11
    NeinChn  
       2020 年 4 月 2 日
    @dapang1221 现成消息队列大部分不支持 exactly once.大多都是 at least once/at most once
    所以一般还是需要自行做可重入
    index90
        12
    index90  
       2020 年 4 月 2 日
    @muziling 我先说一下我对题目的理解,就是有一个分布式作业系统,一个作业只能被一个 worker 执行,worker 可能会突然死掉,多个 worker 会抢占作业。

    首先第一,作业需要有状态机

    第二,为什么一个作业只能由一个 worker 执行,本质原因是这个作业所关联的资源(包括他自身的信息,如状态)只能由一个线程进行读写。那么可以解决资源的访问权限。

    第三,确定状态转移的最大时间,就是 token 的超时时间,你可以依赖 token 超时保证不会再有其他线程在访问你的作业资源。
    also24
        13
    also24  
       2020 年 4 月 2 日
    这东西本质上来说就是锁。

    做好超时和释放机制就行。

    举例,任务 task-24,我们用 Redis 来上锁。

    构造 A-value = "ServerA:" + str(now_ts + timeout)
    A 客户端先 SET task-24-key A-value NX
    如果设置成功,说明拿到了锁,那就执行任务。

    直到任务结束,使用一段 Lua 原子性的删除锁。
    伪代码:if GET task-24-key == A-value then DEL task-24-key


    如果刚才的 SET 没成功,说明有别人拿着锁,那就把 value 取出来看下
    K-value = GET task-24-key

    把 K-value 里的 now_ts + timeout 取出来看下过期没。
    如果没过期,说明这个锁还有效,那就休眠等着。

    如果已经过期,那就说明这个锁的主人可能已经死了,开始抢过期锁。
    构造 A-value2 ="ServerA:" + str(now_ts2 + timeout)
    继续扔一段 Lua 上去原子性的抢锁,伪代码:
    if GET task-24-key == A-value
    then
    SET task-24-key A-value2


    然后看一下 task-24-key 的值是否是 A-value2 。
    是的话说明抢到了锁,执行任务,然后删锁……
    不是的话说明锁被别人抢走了,那继续去看过期的问题……没过期就休眠……
    also24
        14
    also24  
       2020 年 4 月 2 日
    当然,其实还有更简单的办法:
    SET task-24-key anystring NX EX max-lock-time

    设置成功说明抢到了锁
    设置失败说明没抢到

    任务跑完了就 DEL task-24-key 就行~
    ppcoin
        15
    ppcoin  
       2020 年 4 月 2 日
    消息队列 at least once + 幂等的 consumer?
    Chenamy2017
        16
    Chenamy2017  
       2020 年 4 月 2 日
    记录中增加一个更新 id,每次更新时如果更新 id 一致则更新,并且更新 id 自增。其他人去更新时发现 id 不一致,则不允许更新。
    reus
        17
    reus  
       2020 年 4 月 2 日
    何必保证只处理一次,保证处理多次,作用也相同就行。
    lightingtime
        18
    lightingtime  
       2020 年 4 月 2 日
    @also24 那 Redis 那台机器挂了呢
    also24
        19
    also24  
       2020 年 4 月 2 日
    @lightingtime #18
    如果需要考虑 Redis 失效,可以考虑直接拿 RedLock 的方案

    简单点说就是,N 台 Redis 机器,只要在 N / 2 + 1 台机器上抢到了锁,就认为锁已经到手,如果只抢到少部分锁,就要及时删除。


    关于 Redlock 的介绍可以参考这里:
    https://redis.io/topics/distlock
    http://redis.cn/topics/distlock.html
    lightingtime
        20
    lightingtime  
       2020 年 4 月 2 日
    @also24 thanks
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1588 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 16:47 PVG 00:47 LAX 09:47 JFK 12:47
    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