如何在redis上同步多个writer?

时间:2016-12-21 23:14:33

标签: redis synchronization

我有多个编写器在redis中覆盖相同的密钥。我如何保证只选择一个写入最后?

我可以在Redis中执行写同步吗?首先同步编写器吗?

背景: 在我的系统中,一个独特的调度程序发送工作对各种工作人员。然后每个工作人员在Redis中写入结果覆盖相同的密钥。我需要确保只有最后一位接收调度员工作的工作人员才能在Redis中写道。

3 个答案:

答案 0 :(得分:2)

使用有序集( ZSET ):添加等于unix时间戳的分数,然后删除除最高等级以外的所有分数。

Redis Ordered set是一个集合,其中每个条目还有得分。该集合根据分数排序,有序集合中元素的位置称为排名。

按顺序:

  1. 删除所有分数等于或小于您要添加的条目(zremrangebyscore)。由于您要添加一个集合,如果您的值重复,您的新条目将被忽略,您希望保持该条目具有最高排名。
  2. 将您的值添加到zset(zadd
  3. 按排名删除所有条目,但排名最高(zremrangebyrank
  4. 的条目
  5. 您应该在交易(pipeline
  6. 内进行

    python中的示例:

    # timestamp contains the time when the dispatcher sent a message to this worker
    key = "key_zset:%s"%id
    pipeline = self._redis_connection.db.pipeline(transaction=True)
    pipeline.zremrangebyscore(key, 0, t)  # Avoid duplicate Scores and identical data
    pipeline.zadd(key, t, "value")
    pipeline.zremrangebyrank(key, 0, -2)
    pipeline.execute(raise_on_error=True)
    

答案 1 :(得分:0)

如果我是你,我会使用redlock

在您写入该密钥之前,您获取该密钥,然后更新它,然后释放锁。

我使用Node.js所以它看起来像这样,实际上不是正确的代码,但你明白了。

Promise.all(startPromises)
        .bind(this)
        .then(acquireLock)
        .then(withLock)
        .then(releaseLock)
        .catch(handleErr)


function acquireLock(key) {
    return redis.rl.lock(`locks:${key}`, 3000)
}

function withLock(lock) {
    this.lock = lock
    // do stuff here after get the lock
}

function releaseLock() {
    this.lock.unlock()
}

答案 2 :(得分:0)

您可以将redis管道与Transaction一起使用。

Redis是单线程服务器。服务器将同步执行命令。当使用带有事务的Pipeline时,服务器将以原子方式执行管道中的所有命令。

  

<强>交易

     
    

MULTI,EXEC,DISCARD和WATCH是Redis交易的基础。它们允许在一个步骤中执行一组命令,具有两个重要保证:     事务中的所有命令都被序列化并按顺序执行。在执行Redis事务的过程中,永远不会发生由另一个客户端发出的请求。这可以保证命令作为单个隔离操作执行。

  

python

中的一个简单示例
with redis_client.pipeline(transaction=True) as pipe:
    val = int(pipe.get("mykey"))
    val = val*val%10
    pipe.set("mykey",val)
    pipe.execute()