当前位置:首页 > 问答 > 正文

分布式锁到底是啥?这篇文章帮你彻底搞明白,不用再迷糊了

综合自网络技术博客和社区讨论,如CSDN、知乎等平台的常见解释)

你是不是经常听到“分布式锁”这个词,感觉它很高大上,但又有点摸不着头脑?别担心,今天我们就用最直白的方式,把它彻底讲清楚,咱们不从那些复杂的定义开始,先来看一个你肯定能懂的例子。

想象一下,你们公司只有一个很抢手的会议室,很多团队都要用,为了避免冲突,行政部在门口挂了一把实体锁,只有拿到唯一一把钥匙的人才能进去开会,这把锁和这把钥匙,在单机世界里,就相当于一个“锁”,它保证在同一时间,只有一个团队(一个进程)能使用会议室(共享资源)。

公司发展壮大了,变成了一个集团,在全国各地都有分公司,每个分公司都有自己的会议室,但总部的核心服务器资源只有一套,所有分公司的程序都需要远程访问这个服务器上的某个重要数据文件(比如库存数量),这时候问题就来了。

北京分公司的程序A想要修改库存,它先检查了一下,发现没人锁着这个文件,于是它准备修改,深圳分公司的程序B也想要修改库存,它远程检查时,由于网络稍微慢了一点点,它也没发现程序A正在操作,于是它也认为可以修改,结果,两个程序同时修改了库存,最后的数据肯定就乱套了。

你看,之前那把挂在单个会议室门上的物理锁(单机锁)在这种情况下就失效了,因为访问资源(服务器文件)的客户端(分公司程序)不在同一台机器上,它们无法通过操作同一个系统内存来协调谁先谁后。

怎么解决这个问题呢?我们需要一把能让所有分散在各地的程序都“认”的锁,这就是“分布式锁”要干的事情。

分布式锁到底是啥?这篇文章帮你彻底搞明白,不用再迷糊了

分布式锁的本质是什么?

它就是一个在所有分布式系统节点(比如各个分公司的服务器)之间都可见的、统一的“约定场所”,这个“场所”必须是中心化的、大家都能访问到的,它的核心目标非常简单,就一条:保证在分布式系统里,在同一时间,只有一个客户端(程序实例)能对某个共享资源进行操作。

这就好比,集团总部设立了一个“全球会议室预订中心”(比如ZooKeeper、Redis等中间件),无论北京还是深圳的公司,要使用总部的服务器资源前,不能直接去用,必须先给这个“预订中心”打电话申请。

  • 加锁: 北京的程序A先打电话给“预订中心”说:“我要用一下库存文件。”“预订中心”一看,现在没人用,就在自己的小本本上记下:“库存文件被A预订了”,然后告诉A:“好的,你可以用了。”这个过程就是“加锁成功”。
  • 锁被占用: 紧接着,深圳的程序B也打电话来申请用同一个文件。“预订中心”一查小本本,说:“对不起,这个文件已经被A占用了,请你等一会儿。”程序B要么等待,要么放弃,这就是“加锁失败”。
  • 解锁: 等程序A用完了文件,它必须再打个电话告诉“预订中心”:“我用完了,锁还给你。”“预订中心”就把小本本上那条记录划掉,这样其他程序就可以来申请了,这就是“解锁”。

实现分布式锁的常见“预订中心”有哪些?

分布式锁到底是啥?这篇文章帮你彻底搞明白,不用再迷糊了

在技术世界里,这个“全球预订中心”通常由一些能提供一致性强、可靠性高的中间件来担任,最常见的有:

  1. 基于Redis的实现: 就像用一个公共的、速度极快的记事本(内存数据库),程序A来设置一个键值对(key=“库存锁”, value=“A”),如果设置成功了,就表示拿到锁,Redis有原子操作和过期时间等特性,可以较好地实现分布式锁,这是目前非常流行的一种方式。
  2. 基于ZooKeeper的实现: ZooKeeper像一个高度可靠的文件系统,程序A要抢锁时,就在一个约定的目录下创建一个临时的、顺序的节点,如果它创建的这个节点是序号最小的,那它就抢到了锁,ZooKeeper通过自身的强一致性协议,能非常可靠地保证锁的互斥性。
  3. 基于数据库的实现: 比如利用数据库的唯一约束,大家争着往一张表里插入一条代表锁的记录,谁插入成功了,谁就获得了锁,这种方式比较简单,但性能通常不如前两者。

用好分布式锁,要注意哪些坑?

事情还没那么简单,这个“全球预订中心”的方案也会遇到一些现实问题:

  • 死锁问题: 如果程序A拿到锁之后,还没来得及释放锁,自己就崩溃了(比如服务器断电),那这个锁就永远被它占着,其他程序谁也拿不到,形成了“死锁”,分布式锁通常都要设置一个“过期时间”,就像租会议室最多租2小时,超时自动释放。
  • 锁误释放问题: 设置了过期时间又可能引发新问题,如果程序A因为某些原因(比如垃圾回收)卡住了,超过了锁的过期时间,锁被自动释放了,这时程序B拿到了锁,但过了一会儿程序A缓过来了,它以为自己还持有锁,继续操作资源,并且操作完后把锁给释放了——结果把程序B的锁给释放了!这就会导致混乱,锁的值通常要带有客户端的唯一标识,释放时只能释放自己的锁。
  • 脑裂问题: 在某些极端网络情况下,“预订中心”本身可能会出问题,比如主从节点之间网络断开,导致出现了两个“预订中心”都以为自己是老大,可能就会把同一把锁同时分配给两个不同的客户端。

分布式锁并不是什么魔法,它就是一个在分布式环境下,为了解决多个节点竞争同一资源而引入的协调工具,它的思想很简单,就是找一个大家都认可的“裁判”来发号施令,要想在复杂的网络环境中实现一个健壮、可靠的分布式锁,需要考虑非常多的细节(过期时间、误释放、网络分区等),这也是它看似简单实则复杂的地方。

希望这个比喻能帮你彻底搞明白分布式锁到底是个啥!