我在更新和获取键/值时使用 ServiceStack Redis 中的 AcquireLock 方法,如下所示:
public virtual void Set(string key, T entity)
{
using (var client = ClientManager.GetClient())
{
using (client.AcquireLock(key + ":locked", DefaultLockingTimeout, DefaultLockExpire))
{
client.Set(key, entity);
}
}
}
我扩展了 AcqurieLock 方法以接受锁定 key 到期的额外参数。所以我想知道我是否需要 AcquireLock?我的类(class)在 Get<>、GetAll<>、ExpireAt、SetAll<> 等每个操作中都使用 AcquireLock。
但这种方法并非每次都有效。例如,如果对锁的操作抛出异常,则 key 保持锁定状态。对于这种情况,我已将 DefaultLockExpire 参数添加到 AcquireLock 方法以使“锁定” key 过期。
有没有更好的解决方案,或者我们在多线程编程中什么时候需要像“锁” block 一样获取锁。
最佳答案
正如 The Real Bill 的回答所说,Redis 本身不需要锁。 ServiceStack 客户端在锁定方面提供的不是针对 Redis,而是针对您的应用程序。在 C# 应用程序中,您可以使用 lock(obj)
在本地锁定事物,这样事情就不会同时发生(一次只有一个线程可以访问锁定的部分),但这只有在您有一个线程时才有效网络服务器。如果你想防止某些事情同时发生,你需要一个位于网络服务器之外的锁定机制。 Redis 非常适合这一点。
我们有一个案例,检查客户是否已有购物车,如果没有,则创建它。在检查和创建它之间,有一段时间另一个请求也可能发现购物车不存在,并且可能还会继续创建一个。这是锁定的经典案例,但简单的 lock
在这里不起作用,因为请求可能来自完全不同的 Web 服务器。因此,为此,我们使用 ServiceStack Redis 客户端(具有一些抽象)来使用 Redis 进行锁定,并且一次只允许一个请求进入“创建购物车”部分。
所以回答你的实际问题:不,你不需要锁来获取/设置 Redis 的值。
关于locking - 更新 Redis 键/值时获取锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14982260/