我们使用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 Cache,因为我们已经使用Azure Cloud来托管我们的Web API。我们计划使用ManagerId + Date来识别共享资源(我们想要锁定的资源)。这将导致Manager在一个日期锁定,因此在其他日期可以为同一个Manager提供其他锁定。我们计划使用Azure Redis Cache的一个实例,这样安全吗?
答案 0 :(得分:0)
第一季度:Redlock或Zookeeper是否适合我们的用例,还是有更好的解决方案?
我认为Redlock不是您的用例的最佳选择,因为:
a)其保证是在使用DB操作之前设置的特定时间(TTL)。如果由于某种原因(与DevOps交流,并检查How to do distributed locking)该数据库操作花费的时间比TTL长,那么您就失去了锁定有效性的保证(请参阅{{中的 lock Validation time 3}})。您可以使用较大的TTL(分钟),也可以尝试使用另一个监视数据库操作时间的线程来扩展它的有效性-但这变得异常复杂。另一方面,使用Zookeeper(ZK)之前,您的锁一直在那里,直到您将其卸下或过程死亡为止;可能是您的数据库操作挂起时导致锁定也挂起的情况,但是DevOps工具很容易发现这些问题,这些工具会终止挂起过程,从而释放ZK锁定(也可以选择使用有一个监控流程,该流程也可以更快,更具体地针对您的业务方式执行此操作。
b)在尝试锁定进程时必须“打架”才能获得锁定; “战斗”应该让他们等待,然后重试以获取锁。这些可能导致 retry-count 溢出,从而导致无法获取锁。在我看来,这不是一个比较不重要的问题,但是使用ZK,解决方案要好得多:没有“打架”,但是所有进程都会排成一排,等待轮到自己来锁定(检查official documentation)。
c)Redlock基于难以估量的时间度量;至少检查ZK lock recipe处包含“自鸣得意”的段落(也是 Conclusion 段落),然后再考虑一下TTL值应该多大,以确保基于RedLock(时间)锁定。
由于这些原因,我认为RedLock是有风险的解决方案,而Zookeeper是针对您的用例的良好解决方案。我不知道其他适合您情况的更好的分布式锁定解决方案,但确实存在其他分布式锁定解决方案,例如只需检查How to do distributed locking。
第二季度:我们计划使用一个Azure Redis缓存实例,这样是否足够安全?
对于您的用例来说可能是安全的,因为TTL似乎是可预测的(如果我们真的相信时间测量-请参阅下面的警告),但是仅(如果从属可以接管发生故障的主控可以) 延迟(不确定是否可以,请检查Redis配置功能)。如果您在锁同步到从属服务器之前松开了主机,则另一个进程可能只会获得相同的锁。 Redlock建议使用至少延迟1个TTL的延迟重启(检查Apache ZooKeeper vs. etcd3中的性能,崩溃恢复和fsync )。如果出于Q1:a + c的原因,您的TTL太长了,则系统将无法锁定它,这可能是一个无法接受的长时期(因为您仅有的1个Redis主设备必须由< em> delayed fashion)。
PS:我再次强调要阅读马丁·克莱普曼(Martin Kleppmann)的official documentation,您会发现令人难以置信的原因,即数据库操作被延迟(在到达存储服务之前先搜索 ),并且也令人难以置信锁定时未按时进行测量的原因(还有一个有趣的理由反对使用Redlock)