【发布时间】:2018-11-28 18:08:54
【问题描述】:
我们有使用 Azure SQL 数据库的 Web API。数据库模型有客户和经理。客户可以添加约会。我们不能允许同一经理的 2 个或更多客户的重叠约会。因为我们在分布式环境中工作(多个Web服务器实例可以同时将记录插入数据库),所以有可能会保存无效的约会。例如,客户 1 想要 10:00 - 10:30 之间的约会。客户 2 想要 10:15 - 10:45 之间的约会。如果两个约会同时发生,那么 Web API 中的验证代码将不会捕获错误。这就是为什么我们需要像分布式锁管理器这样的东西。我们从 Redis 和 Zookeeper 中了解了 Redlock。我的问题是:Redlock 或 Zookeeper 是我们用例的好选择还是有更好的解决方案?
如果我们使用 Redlock,我们会使用 Azure Redis 缓存,因为我们已经使用 Azure Cloud 来托管我们的 Web API。我们计划使用 ManagerId + Date 来识别共享资源(我们要锁定的资源)。这将导致 Manager 在某个日期被锁定,因此可能会在其他日期为同一 Manager 获得其他锁定。我们计划使用一个 Azure Redis 缓存实例,这样够安全吗?
【问题讨论】:
-
我不会通过锁定整个事情来解决这个问题。这是一个先到先得的场景,对吧?在保留约会之前,请检查约会空档是否仍然可用。如果不是 - 返回 HTTP 409 或其他内容 - 并通知用户找到另一个插槽 - 否则从您的 WebAPI 返回 200。
-
我们正在使用实体框架 ORM,因此有可能当一个实例检查预约空闲槽并确定它是空闲时,在它将新预约插入数据库之前,另一个 Web 服务实例也确定该预约插槽是空闲的并且还插入约会 = 我们得到约会重叠,所以我们正在尝试解决这个问题
-
当然我明白你的意思 - 但仍然有办法解决这个问题而无需锁定。例如:使用 WebAPI 将消息放在队列中,并仅使用 1 个工作人员来获取消息,检查重叠并存储在数据库中。解决并发问题的一种方法是消除并发。我是从 Mark Seamann 在 Pluralsight 上的功能架构课程中得到的:pluralsight.com/courses/functional-architecture-fsharp
-
嘿@JochenvanWylick,我是 Vukasins 的同事之一。您对消息队列的权利可以消除并发性,但这带来了两个问题:您无法扩展工作角色,其次,如果成功创建约会,则需要立即通知用户,这意味着我们有为 UI 创建更复杂的通知系统
-
是的,确实,这两点都是正确的。这是一个权衡 - 但肯定是可能的。这就是为什么我强烈建议关于复数的课程。一个著名的例子是亚马逊库存系统。如果您同时向 2 位用户展示“还剩 1 件商品” - 并且其中一位购买得更快,那么第二位购买者可能会收到错误消息。但是亚马逊并不会在有人看到该商品时立即停止购买——如果他们的销售量超过库存(这种情况只会发生几次),他们会进行补偿。
标签: azure redis locking apache-zookeeper