我将 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 个部分组成:
- 密钥(数据库中锁的唯一名称)
- 值(调用者定义的令牌,可用于指示谁“拥有”锁,并检查释放和扩展锁是否正确完成)
- 持续时间(锁故意是一个有限持续时间的东西)
如果没有其他值出现,指南可能会制定一个合适的“值”。我们倾向于使用机器名称(如果多个进程可以在同一台机器上竞争,则使用机器名称的 munged 版本)。
另外,请注意,获取锁是投机的, not blocking。你完全有可能fail获得锁,因此您可能需要对此进行测试,并可能添加一些重试逻辑。
一个典型的例子可能是:
RedisValue token = Environment.MachineName;
if(db.LockTake(key, token, duration)) {
try {
// you have the lock do work
} finally {
db.LockRelease(key, token);
}
}
请注意,如果工作很长(特别是循环),您可能需要偶尔添加一些内容LockExtend
中间调用 - 再次记住检查是否成功(以防超时)。
另请注意all单个 redis 命令是原子的,因此您无需担心两个谨慎的操作相互竞争。对于更复杂的多操作单元,交易 and 脚本编写是选项。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)