Redis—密钥模式可能过期的最大记录数

Redis—密钥模式可能过期的最大记录数,redis,Redis,假设我们是一个在线销售T恤的卖家。我们只剩下一件T恤要卖了。未完成的订单放在redis中,并在1小时内自动过期。我们最多只能销售剩下的1件t恤,因此我们必须将redis中待处理的订单密钥数量限制为1件。如果订单已完成,将删除redis中的临时订单,并将已完成的订单写入数据库以执行 如果客户来了,我们必须检查剩余库存量(在我们的示例中为1件t恤)以及redis中已经有多少待处理订单(到期前),如果没有可用库存可供出售,如果我们没有足够的库存(在我们假设的示例中为1件t恤),我们将不允许订购t恤 这

假设我们是一个在线销售T恤的卖家。我们只剩下一件T恤要卖了。未完成的订单放在redis中,并在1小时内自动过期。我们最多只能销售剩下的1件t恤,因此我们必须将redis中待处理的订单密钥数量限制为1件。如果订单已完成,将删除redis中的临时订单,并将已完成的订单写入数据库以执行

如果客户来了,我们必须检查剩余库存量(在我们的示例中为1件t恤)以及redis中已经有多少待处理订单(到期前),如果没有可用库存可供出售,如果我们没有足够的库存(在我们假设的示例中为1件t恤),我们将不允许订购t恤

这是我的尝试(我第一次使用redis,主要是因为redis可以自动终止任何数据库中不需要的挂起密钥)

  • 顾客A来访。检查redis是否存在未决订单-扫描“订单:t_shirtid:1”。没有
  • 启动事务-观察“订单:t_shirtid:1”,多,setex“订单:t_shirtid:1”3600 1,执行
  • 如果客户B访问,我们将看到一个待定订单,其键“order:t_shirtid:1”的值为1,不允许客户B订购
  • 如果1小时后,密钥“order:t_shirtid:1”过期且尚未完成,则客户B在访问时将看到redis中没有使用该密钥的内容,可以继续订购
  • 此策略有时会失败,因为客户A和客户B可能会转到不同的应用程序服务器,都会发现redis中没有“order:t_shirtid:1”的内容,都会准备按顺序写入redis(也就是说,手表将不起作用,因为首先客户A进入,完成所有操作,然后客户B进入redis并写入相同的内容,但更重要的是,两个客户都已逐个完成“订单:T恤id:1”的扫描,以了解redis中没有未决订单).因此,我们刚刚允许客户下订单,即使只剩下1件T恤可供销售


    那么这个用例的正确方法是什么呢?我很想了解其他人都做了些什么。提前感谢您的帮助。

    因为您使用的是WATCH/MULTI/EXEC,只有当B在A完成(执行)事务后启动事务时,竞争条件才会发生

    在我看来,解决这个问题的更好方法是将临时订单存储在一个已排序的集合中。这将让您用原子Redis操作替换扫描,并将其包含在事务流中,从而消除竞争条件(以及提高性能)。但是,如果采用这种方法,则需要手动使ZSET的成员过期(使用分数存储时间戳,定期/在访问时删除旧成员)


    顺便说一句,从您的示例来看,对于给定的t恤ID,似乎只能有一个临时订单。

    谢谢。您是对的。B必须在a执行后开始。手动过期是我想要避免的,因为这是应用程序中需要跟踪的另一件事。是否有一种Lua脚本化的方法来处理此赌注ter?当然-逻辑是完全Lua-able的。请看(唯一的)Josiah Carlson关于类似方法的回答(虽然是Python,但对Lua-fy来说应该很简单):再次感谢!最后一个问题。我们必须如何定期进行此操作?我们必须扫描特定模式的每个键吗(如“order:tshirts:”)然后再使用ZREMRANGEBYSCORE?还有,我如何防止在“订单:t恤:排序集?我们是否应该首先在事务中检查其大小?但在事务中,我们是否能够首先获得大小,以确定是否向集合中添加新内容?抱歉,如果这个问题看起来很幼稚-我个人非常不熟悉,我更喜欢在每次触按有问题的键后进行操作,因此在您的情况下,请执行ZR每当您向项目的排序集添加新订单时,EMRANGEBYSCORE。依我看,这比定期(例如cron)更可取运行清理作业。至于在事务中检查它,请确定-只需在开始时查看密钥,读取相关成员,然后启动多块-如果密钥更改,执行将失败。重新更新-没有问题,我们在某个阶段都是新的;)