
1 fancy111 2020 年 4 月 2 日 都 2020 年了,你还来问这个问题,连百度收录的都是三五年前的解决方案了。 |
3 loryyang 2020 年 4 月 2 日 重点看你的处理是什么,要多严格的 just once |
5 index90 2020 年 4 月 2 日 用 token 同一时间,只有一个 worker 获得有效 token worker 可以利用 token 修改该 task 的状态和访问其相关资源 |
6 dapang1221 2020 年 4 月 2 日 现成的消息队列怎么不用…处理完后回复 ACK 确认 |
7 ThirdFlame 2020 年 4 月 2 日 那不就和 人工作业一样么,有 worker 处理了,那设置个标记说明 处理中。 等处理完成了,把标记置为完成。 |
8 jugelizi 2020 年 4 月 2 日 via iPhone 无非是单线程 或者锁 |
10 looplj 2020 年 4 月 2 日 上面的说法跟 LZ 提的没看出有什么区别 单线程也很难就直接保证了,没有考虑 处理完成,但是更新状态失败这个问题。 要 Exactly Once 基本是要业务层保证,幂等,可 redo |
11 NeinChn 2020 年 4 月 2 日 @dapang1221 现成消息队列大部分不支持 exactly once.大多都是 at least once/at most once 所以一般还是需要自行做可重入 |
12 index90 2020 年 4 月 2 日 @muziling 我先说一下我对题目的理解,就是有一个分布式作业系统,一个作业只能被一个 worker 执行,worker 可能会突然死掉,多个 worker 会抢占作业。 首先第一,作业需要有状态机 第二,为什么一个作业只能由一个 worker 执行,本质原因是这个作业所关联的资源(包括他自身的信息,如状态)只能由一个线程进行读写。那么可以解决资源的访问权限。 第三,确定状态转移的最大时间,就是 token 的超时时间,你可以依赖 token 超时保证不会再有其他线程在访问你的作业资源。 |
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 。 是的话说明抢到了锁,执行任务,然后删锁…… 不是的话说明锁被别人抢走了,那继续去看过期的问题……没过期就休眠…… |
14 also24 2020 年 4 月 2 日 当然,其实还有更简单的办法: SET task-24-key anystring NX EX max-lock-time 设置成功说明抢到了锁 设置失败说明没抢到 任务跑完了就 DEL task-24-key 就行~ |
15 ppcoin 2020 年 4 月 2 日 消息队列 at least once + 幂等的 consumer? |
16 Chenamy2017 2020 年 4 月 2 日 记录中增加一个更新 id,每次更新时如果更新 id 一致则更新,并且更新 id 自增。其他人去更新时发现 id 不一致,则不允许更新。 |
17 reus 2020 年 4 月 2 日 何必保证只处理一次,保证处理多次,作用也相同就行。 |
18 lightingtime 2020 年 4 月 2 日 @also24 那 Redis 那台机器挂了呢 |
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 |
20 lightingtime 2020 年 4 月 2 日 @also24 thanks |