案例背景
分布式锁是解决协调分布式系统之间,同步访问共享资源的一种方式。详细来讲:在分布式环境下,多个系统在同时操作共享资源(如写数据)时,发起操作的系统通常会通过一种方式去协调其他系统,然后获取访问权限,得到访问权限后才可以写入数据,其他系统必须等待权限释放。
分布式锁
我和其他的面试官交流后发现,很多面试官都会问候选人与分布式锁相关的问题,在一些细节上挖得还比较细。比如在分布式系统中涉及共享资源的访问,一些面试官会深挖如何控制并发访问共享资源;如何解决资源争抢等技术细节,这些问题在下单场景、优惠券场景都会被考察到,足以证明“分布式锁”考点的重要性。
那么假设你正在面试,面试官模拟了系统秒杀的场景:为了防止商品库存超售,在并发场景下用到了分布式锁的机制,做商品扣减库存的串行化操作。然后问你:“你如何实现分布式锁?”
你该怎么回答呢?
案例分析
当你听到这个问题后,心里会不会窃喜?觉得这是一道送分题,因为可选方案有很多,比如:
-
基于关系型数据库 MySQL 实现分布式锁;
-
基于分布式缓存 Redis 实现分布式锁;
你从中选择一个熟悉的实现方式,然后和面试官展开拉锯式的问答环节。
你:“可以基于 Redis 的 setnx 命令来实现分布式锁。”
面试官:“当拿到锁的服务挂掉,如何防止死锁?”
你:“可以为锁设置一个过期时间。”
面试官:“那如何保证加锁和设置过期时间是原子操作?” ……
如果面试官觉得你回答问题的思路清晰有条理,给出的实现方案也可以落地,并且满足你的业务场景,那么他会认可你具备初中级研发工程师该具备的设计能力,但不要高兴得太早。
因为有些面试官会继续追问:“分布式锁用 Zookeeper 实现行不行?”,“分布式锁用 etcd 实现行不行?” 借机考察你对分布式协调组件的掌握。你可能会觉得开源组件那么多,自己不可能每一个都用过,答不出来也无妨。但面试官提问的重点不是停留在组件的使用上,而是你对分布式锁的原理问题的掌握程度。
换句话说,“如果让借助第三方组件,你怎么设计分布式锁?” 这背后涉及了分布式锁的底层设计逻辑,是你需要掌握的。
在给出方案之前,你要明确待解决的问题点是什么。虽然你可以借助数据库 DB、Redis 和 ZooKeeper 等方式实现分布式锁,但要设计一个分布式锁,就需要明确分布式锁经常出现哪些问题,以及如何解决。
-
可用性问题:无论何时都要保证锁服务的可用性(这是系统正常执行锁操作的基础)。
-
死锁问题:客户端一定可以获得锁,即使锁住某个资源的客户端在释放锁之前崩溃或者网络不可达(这是避免死锁的设计原则)。