当前位置: 首页 > 知识库问答 >
问题:

更新Redis键/值时获取锁

闻人修平
2023-03-14

我在更新和获取键/值时使用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方法,以接受锁密钥过期时的额外参数。所以我想知道我是否需要AcquireLock?我的类在每个操作中都使用AcquireLock,比如Get

但是这种方法并不是每次都有效。例如,如果锁中的操作抛出异常,那么密钥将保持锁定状态。对于这种情况,我已将DefaultLockExire参数添加到AcquireLock方法以使“锁定”密钥过期。

有没有更好的解决方案,或者我们什么时候需要获得锁,比如多线程编程中的“锁”块。

共有3个答案

谈秦斩
2023-03-14

正如@JulianR所说,ServiceStack中的锁定。Redis仅适用于应用程序级的分布式锁(即在分布式文件系统上使用DB或空的. lock文件进行替换),并且它仅适用于其他ServiceStack。Redis客户端在其他进程中使用相同的密钥/API来获取锁。

对于正常的Redis操作,您永远不需要这样做,因为它们都是原子的。如果您想确保redis操作的组合以原子方式发生,那么您可以在Redis事务中组合它们,或者您可以在服务器端Lua脚本中执行它们——两者都允许批处理操作的原子执行。

苏坚成
2023-03-14

我不会使用锁进行get/set操作。Redis会自动执行这些操作,因此在设置或获取时不可能“在你下面更改”。我构建了数百个客户端同时更新/操作值的系统,并且从不需要锁来执行这些操作(尤其是过期)。

我不知道Service Stack redis是如何实现它的锁定的,所以我不能说它失败的原因。但是,我不确定我是否会相信它,因为Redis端不需要真正的锁定来进行数据操作。Redis是单线程的,所以在那里锁定没有意义。

如果您正在进行复杂的操作,其中您获得了一个值,基于它进行操作,然后在一段时间后更新它,并且在此期间无法更改值,我建议阅读和摸索http://redis.io/topics/transactions,看看您想要的是否是Redis的好处,您的代码是否需要重构以消除问题,或者至少找到更好的方法来做到这一点。

例如,SETNX可能是您获得想要的东西所需要的路线,但没有细节,我不能说它会起作用。

郑浩博
2023-03-14

正如真正的Bill答案所说,Redis本身不需要锁。ServiceStack客户端提供的锁定不是针对Redis,而是针对您的应用程序。在C#应用程序中,您可以使用lock(obj)在本地锁定东西,这样就不能同时发生某些事情(一次只有一个线程可以访问锁定的部分),但这只在您有一个Web服务器的情况下起作用。如果您想防止同时发生某些事情,您需要一个位于Web服务器之外的锁定机制。Redis很适合这样做。

我们有一个案例,如果客户已经有购物车,则检查它,如果没有,则创建它。在检查和创建它之间,有一段时间,另一个请求也可能发现购物车不存在,也可能继续创建购物车。这是锁定的经典案例,但简单的lock在这里不起作用,因为请求可能来自完全不同的Web服务器。因此,我们使用ServiceStack Redis客户端(带有一些抽象)使用Redis进行锁定,并且一次只允许一个请求进入“创建购物车”部分。

所以要回答你的实际问题:不,你不需要锁来获取/设置Redis的值。

 类似资料:
  • 问题内容: 如何使用排序集从Redis获取多个键的值? 这将有两个用户。 如何在一个查询中检索具有键“ David”和“ Linda”的用户? 问题答案: 无需在Redis中引入新命令的方法有多种。 例如,您可以使用感兴趣的名称填充临时集,然后计算该临时集与zset之间的交集: 使用流水线操作,只会产生一次往返,并且您可以在tmp中填充任意数量的输入参数。 使用Redis 2.6,您还可以将这些行

  • 问题内容: 我目前正在与Redis一起玩,我有几个问题。是否可以从键数组中获取值? 例: 当我返回时。我可以遍历此列表并获得用户:1,获得用户:2。但这感觉不对,有没有办法让所有与会者的信息一目了然? 在rails中,我会做这样的事情: 但是在redis中我不能,因为它返回键,而不是存储在该键上的实际对象。 谢谢 :) 问题答案: 在项目上循环并同步访问每个元素不是很有效。使用Redis 2.4,

  • 问题内容: 我将数据存储在Redis中。我将它存储在GUID,createday和它的大小中。 因此,我定义以下内容: 我希望查看我的数据库中的所有文件。因此,我尝试以下操作: 但是res是。我该怎么做? 问题答案: 返回存储在key处的哈希的所有字段和值,您不能指定掩码: http //redis.io/commands/hgetall 您可以调用获取符合条件的所有键的列表,然后循环获取所有值。

  • 我用Redis做我在Laravel的缓存。 在我的代码库中,我有一段代码设置了一个缓存值,如下所示: 因此在这一点上,键是,值是,如果我要运行,我自然会得到10。 我一直在试图挖掘内部的原因,我不在此详述,但我试图找到缓存中的所有键,,而这个特定的键在列表中显示为。我做了一点研究,发现门面为这些场景使用了前缀,这对我来说是有意义的。 所以很自然,如果这是Redis的关键字,那么我应该可以这样做:

  • 问题内容: 我有一个数据库应用程序,其中一个组的建模如下: 我们设置了一个包含多字段的外键,因为我们要确保a不能拥有与其所在所有者不同的所有者。由于其他原因(我认为我不需要对此进行详细说明),group_owner_id不能从表中删除,因此仅删除它是不可行的。 我的大问题是,如果我想为整个组更新,我正在编写这样的代码(用伪代码): 有办法解决吗?似乎有点笨拙。希望我已经发布了足够的细节。 谢谢。

  • 问题内容: 我在我的socket.io聊天应用程序的Redis存储中存储了用户名/ SocketID对。 当用户断开连接时,我需要从Redis存储中删除用户名/ socketID对。我已经看到了如何从键中获取值,但从未从值中获取键。可能吗?或无论哪种方式,我怎么能只从值中删除键/值对。这是我的代码 用于在连接上添加存储 对于断开连接,客户端将不知道何时断开连接,可能是由于Internet连接断开而