redis - StackExchange.Redis - LockTake/LockRelease 用法

标签 redis stackexchange stackexchange.redis

我将 Redis 与 StackExchange.Redis 一起使用。我有多个线程将在某个时候访问和编辑同一个键的值,因此我需要同步数据操作。

查看可用函数,我看到有两个函数,TakeLock 和 ReleaseLock。但是,这些函数同时采用键和值参数,而不是预期的要锁定的单个键。 GitHub 上的 intellisene 文档和源代码没有解释如何使用 LockTake 和 LockRelease 函数或为键和值参数传递什么。

问:StackExchange.Redis 中 LockTake 和 LockRelease 的正确用法是什么?

我打算做的伪代码示例:

//Add Items Before Parallel Execution
redis.StringSet("myJSONKey", myJSON);

//Parallel Execution
Parallel.For(0, 100, i =>
    {
        //Some work here
        //....

        //Lock
        redis.LockTake("myJSONKey");

        //Manipulate
        var myJSONObject = redis.StringGet("myJSONKey");
        myJSONObject.Total++;
        Console.WriteLine(myJSONObject.Total);
        redis.StringSet("myJSONKey", myNewJSON);

        //Unlock
        redis.LockRelease("myJSONKey");

        //More work here
        //...
    });

最佳答案

一把锁有3个部分:

  • key (锁在数据库中的唯一名称)
  • 值(调用者定义的 token ,既可用于指示谁“拥有”锁,也可用于检查释放和扩展锁是否正确完成)
  • 持续时间(有意锁定是有限持续时间的事情)

如果没有想到其他值,guid 可能会产生合适的“值”。我们倾向于使用机器名(如果多个进程可能在同一台机器上竞争,则使用机器名的变形版本)。

另外,请注意获取锁是推测性的,而不是阻塞性。完全有可能您未能获取锁,因此您可能需要对此进行测试并可能添加一些重试逻辑。

一个典型的例子可能是:

RedisValue token = Environment.MachineName;
if(db.LockTake(key, token, duration)) {
    try {
        // you have the lock do work
    } finally {
        db.LockRelease(key, token);
    }
}

请注意,如果工作很长(特别是循环),您可能需要在中间添加一些偶尔的 LockExtend 调用 - 再次记住检查是否成功(以防超时).

另请注意,所有 单独的 redis 命令都是原子的,因此您无需担心两个谨慎的操作相互竞争。对于更复杂的多操作单元,事务脚本 是选项。

关于redis - StackExchange.Redis - LockTake/LockRelease 用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25127172/

相关文章:

mongodb - 基于用例的数据库技术选择

html - html 中的 StackExchange 颜色图标

mysql - 将进程从 mysql 转换为 Redis

mongodb - 我应该使用 MongoDB 或 CouchDB 还是其他什么?

openid - 没有 Google+ 的 Google OpenID 委托(delegate)提供商

c# - 在 StackExchange Redis 客户端上跟踪消息

asp.net - Redis 是适合公司警报消息系统的消息系统吗?

asp.net - 数以千计的 TaskCanceledException 异常

javascript - NodeJS Redis 客户端返回错误值

python - 将 stackexchange api 作为 json 打开时,无法解码任何 JSON 对象