cronsun icon indicating copy to clipboard operation
cronsun copied to clipboard

设置了单机单进程,但是会出现两个节点同时跑一个任务

Open pupilcp opened this issue 6 years ago • 15 comments

Please answer these questions before submitting your issue. Thanks! 在你提交 issue 前,请先回答以下问题,谢谢!

  1. What version of Go and cronsun version are you using? 你用的是哪个版本的 Go 和 哪个版本的 cronsun? v0.3.4

  2. What operating system and processor architecture are you using (go env)? 你用的是哪个操作系统,什么架构的? centos7

  3. What did you do? If possible, provide a recipe for reproducing the error. A complete runnable program is good. 你做了什么,遇到了什么问题?尽可能描述清楚问题,最好把操作步骤写下来,按这些步骤操作后能重现你的问题。 设置了单机单进程,但是会出现两个节点同时跑一个任务 备注:这个任务的实际执行时间超过设置的计划任务时间 image image

  4. What did you expect to see? 你期望得到什么样的结果? 按理设置了单机单进程,就算有多个节点,应该只有一个进程在跑

  5. What did you see instead? 现在你得到的结果是什么样的? 目前会出现两个节点同时跑一个任务

pupilcp avatar Dec 04 '18 03:12 pupilcp

遇到了同样的情况,不知道解决了没有,请教一下

dz1iang avatar Feb 01 '19 09:02 dz1iang

遇到了同样的情况,不知道解决了没有,请教一下

之前私聊作者了,年后回来问下他,目前暂时使用单节点运行。

pupilcp avatar Feb 01 '19 10:02 pupilcp

嗯嗯,我这边也看一下,到时候请同步一下信息

dz1iang avatar Feb 01 '19 10:02 dz1iang

etcd的全局锁是不安全的,而下面这个函数,也没有处理不安全的情况

func (c *Client) GetLock(key string, id client.LeaseID) (bool, error) { key = conf.Config.Lock + key ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout) resp, err := DefalutClient.Txn(ctx). If(client.Compare(client.CreateRevision(key), "=", 0)). Then(client.OpPut(key, "", client.WithLease(id))). Commit() cancel()

if err != nil { return false, err }

return resp.Succeeded, nil }

dz1iang avatar Feb 11 '19 11:02 dz1iang

应该是因为各个节点之间时钟有一些差异, 测试脚本执行得比较快,某个节点执行完了,另外一个节点才开始执行

QLeelulu avatar Feb 12 '19 06:02 QLeelulu

应该是因为各个节点之间时钟有一些差异, 测试脚本执行得比较快,某个节点执行完了,另外一个节点才开始执行

有办法解决吗,但是我这边出现问题的脚本是执行比较长时间的

pupilcp avatar Feb 12 '19 07:02 pupilcp

etcd的全局锁是不安全的,而下面这个函数,也没有处理不安全的情况

func (c *Client) GetLock(key string, id client.LeaseID) (bool, error) { key = conf.Config.Lock + key ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout) resp, err := DefalutClient.Txn(ctx). If(client.Compare(client.CreateRevision(key), "=", 0)). Then(client.OpPut(key, "", client.WithLease(id))). Commit() cancel()

if err != nil { return false, err }

return resp.Succeeded, nil }

使用 https://github.com/etcd-io/etcd/tree/master/clientv3/concurrency 获取锁,并且每次都判断锁的revision

dz1iang avatar Feb 13 '19 06:02 dz1iang

etcd的全局锁是不安全的,而下面这个函数,也没有处理不安全的情况 func (c *Client) GetLock(key string, id client.LeaseID) (bool, error) { key = conf.Config.Lock + key ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout) resp, err := DefalutClient.Txn(ctx). If(client.Compare(client.CreateRevision(key), "=", 0)). Then(client.OpPut(key, "", client.WithLease(id))). Commit() cancel() if err != nil { return false, err } return resp.Succeeded, nil }

使用 https://github.com/etcd-io/etcd/tree/master/clientv3/concurrency 获取锁,并且每次都判断锁的revision

问下具体需要怎么做?修改源码,重新编译etcd吗

pupilcp avatar Feb 13 '19 06:02 pupilcp

etcd的全局锁是不安全的,而下面这个函数,也没有处理不安全的情况 func (c *Client) GetLock(key string, id client.LeaseID) (bool, error) { key = conf.Config.Lock + key ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout) resp, err := DefalutClient.Txn(ctx). If(client.Compare(client.CreateRevision(key), "=", 0)). Then(client.OpPut(key, "", client.WithLease(id))). Commit() cancel() if err != nil { return false, err } return resp.Succeeded, nil }

使用 https://github.com/etcd-io/etcd/tree/master/clientv3/concurrency 获取锁,并且每次都判断锁的revision

问下具体需要怎么做?修改源码,重新编译etcd吗

修改了crunsun的源码,etcd没有操作。 拿到concurrency 锁后,在获取一次concurrency锁的key,比较锁与key的revision

dz1iang avatar Feb 13 '19 06:02 dz1iang

etcd的全局锁是不安全的,而下面这个函数,也没有处理不安全的情况 func (c *Client) GetLock(key string, id client.LeaseID) (bool, error) { key = conf.Config.Lock + key ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout) resp, err := DefalutClient.Txn(ctx). If(client.Compare(client.CreateRevision(key), "=", 0)). Then(client.OpPut(key, "", client.WithLease(id))). Commit() cancel() if err != nil { return false, err } return resp.Succeeded, nil }

使用 https://github.com/etcd-io/etcd/tree/master/clientv3/concurrency 获取锁,并且每次都判断锁的revision

问下具体需要怎么做?修改源码,重新编译etcd吗

修改了crunsun的源码,etcd没有操作。 拿到concurrency 锁后,在获取一次concurrency锁的key,比较锁与key的revision

您那边都处理好了吗,有效果不

pupilcp avatar Feb 13 '19 07:02 pupilcp

etcd的全局锁是不安全的,而下面这个函数,也没有处理不安全的情况 func (c *Client) GetLock(key string, id client.LeaseID) (bool, error) { key = conf.Config.Lock + key ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout) resp, err := DefalutClient.Txn(ctx). If(client.Compare(client.CreateRevision(key), "=", 0)). Then(client.OpPut(key, "", client.WithLease(id))). Commit() cancel() if err != nil { return false, err } return resp.Succeeded, nil }

使用 https://github.com/etcd-io/etcd/tree/master/clientv3/concurrency 获取锁,并且每次都判断锁的revision

问下具体需要怎么做?修改源码,重新编译etcd吗

修改了crunsun的源码,etcd没有操作。 拿到concurrency 锁后,在获取一次concurrency锁的key,比较锁与key的revision

您那边都处理好了吗,有效果不

跑了几个小时的测试环境,目前没有出现同时跑的情况

dz1iang avatar Feb 13 '19 07:02 dz1iang

etcd的全局锁是不安全的,而下面这个函数,也没有处理不安全的情况 func (c *Client) GetLock(key string, id client.LeaseID) (bool, error) { key = conf.Config.Lock + key ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout) resp, err := DefalutClient.Txn(ctx). If(client.Compare(client.CreateRevision(key), "=", 0)). Then(client.OpPut(key, "", client.WithLease(id))). Commit() cancel() if err != nil { return false, err } return resp.Succeeded, nil }

使用 https://github.com/etcd-io/etcd/tree/master/clientv3/concurrency 获取锁,并且每次都判断锁的revision

问下具体需要怎么做?修改源码,重新编译etcd吗

修改了crunsun的源码,etcd没有操作。 拿到concurrency 锁后,在获取一次concurrency锁的key,比较锁与key的revision

您那边都处理好了吗,有效果不

跑了几个小时的测试环境,目前没有出现同时跑的情况

我问了作者,他想你帮忙提个pr

pupilcp avatar Feb 13 '19 09:02 pupilcp

etcd的全局锁是不安全的,而下面这个函数,也没有处理不安全的情况 func (c *Client) GetLock(key string, id client.LeaseID) (bool, error) { key = conf.Config.Lock + key ctx, cancel := context.WithTimeout(context.Background(), c.reqTimeout) resp, err := DefalutClient.Txn(ctx). If(client.Compare(client.CreateRevision(key), "=", 0)). Then(client.OpPut(key, "", client.WithLease(id))). Commit() cancel() if err != nil { return false, err } return resp.Succeeded, nil }

使用 https://github.com/etcd-io/etcd/tree/master/clientv3/concurrency 获取锁,并且每次都判断锁的revision

问下具体需要怎么做?修改源码,重新编译etcd吗

修改了crunsun的源码,etcd没有操作。 拿到concurrency 锁后,在获取一次concurrency锁的key,比较锁与key的revision

您那边都处理好了吗,有效果不

跑了几个小时的测试环境,目前没有出现同时跑的情况

我问了作者,他想你帮忙提个pr

我们之前也修改的比较多了,后面找个时间看下

dz1iang avatar Feb 13 '19 10:02 dz1iang

我也遇到这个问题了,你们是咋解决的。

valiner avatar Dec 08 '20 09:12 valiner

我出现情况是如果是短任务(毫秒级别执行完的任务),会出现多台机器同时执行的情况,出现这个问题的原因

  1. 多个服务器时间不统一
  2. A机器获得锁且执行完后释放锁,这个时候b机器才刚刚执行到获取锁的代码,b也能拿锁

解决方案 为了防止情况2的发生,在defer lk.unlock()里面,睡眠100ms,防止过快释放锁。

valiner avatar Dec 09 '20 09:12 valiner