Bootstrap

(面试经典问题之分布式锁)分布式锁的基本原理、作用以及实现

一、什么是分布式锁

分布式锁指的是在分布式场景中实现互斥类型的锁。

分布式是什么意思?分布式表示运行的节点可能在不同的机器或不同的网段中,节点间通信通过socket。互斥类型是什么意思?互斥类型表示同一时刻只允许一个执行体进入临界资源。

二、分布式锁的特性

分布式锁具有三大特性:

1、互斥性:同上所述,互斥性要求同一时刻只允许一个执行体进入临界资源。具体的操作包括加锁、解锁、给执行体打上唯一标记。

2、锁超时性:由于其分布式的特性(节点间需要通过网络进行通信),而一旦某获取了锁的节点出现网络故障或者进程宕机,从而无法释放锁,这将导致其他尝试获取该锁的节点或进程一直阻塞。因此,为避免该情况的发生,需要对其设置锁超时特性,即在某节点获取锁的时候设定一个时间,当超过该时间后该节点自动释放锁资源。

3、可用性:通俗来讲就是在合理时间内得到合理的回复。具体展开来又可细分为:

  • 高可用性:确保即使部分节点故障,锁的机制仍然能保持有效,避免系统宕机。
  • 网络分区容忍性:能够合理处理网络分区情况,确保系统的正常运行。
  • 死锁防止:通过超时机制等方式,避免死锁的发生。
  • 性能和响应时间:保持高效的锁操作,减少性能开销。

三、解决了什么问题 

在分布式场景下,只允许一个节点执行某类任务。

四、分布式锁的实现问题

常见的分布式锁的实现方式为:

  • 基于 Redis 实现分布式锁
  • 基于 ZooKeeper 实现分布式锁
  • 基于 Etcd 实现分布式锁
  • 基于 Mysql 实现分布式锁

看到这读者是否有产生跟我一样的疑问:分布式锁在层次结构上应属于“基础组件”层次,而redis,mysql这些属于“中间件”层次,正常来说,中间件是在基础组件的基础上实现的,那为什么这里反而是基于中间件去实现基础组件呢? 

原因在于,像redis这样的中间件,它们提供了构建分布式锁所需的原子操作,而这些原子操作是实现分布式锁的基础。换句话说,redis等这些中间件,它们的某些功能(SETNX EXPIRE)可以非常有效的用于实现分布式锁,我们基于redis实现分布式锁就是基于这些他们自带的功能。

这里以使用redis实现分布式锁举例:

import redis
import uuid
import time

# 创建 Redis 连接
r = redis.StrictRedis(host='localhost', port=6379, db=0)

lock_key = "my_lock"
lock_value = str(uuid.uuid4())  # 锁的唯一标识
lock_timeout = 10  # 锁的超时时间(秒)

# 获取锁
def acquire_lock():
    # 使用 SETNX 设置锁并设置过期时间
    if r.setnx(lock_key, lock_value):
        r.expire(lock_key, lock_timeout)
        return True
    return False

# 释放锁
def release_lock():
    # 只有锁的持有者才能释放锁
    if r.get(lock_key) == lock_value:
        r.delete(lock_key)

# 使用锁
if acquire_lock():
    try:
        print("Lock acquired, doing work...")
        time.sleep(5)  # 模拟任务执行
    finally:
        release_lock()
        print("Lock released")
else:
    print("Unable to acquire lock")
  • SETNX:用于设置一个值,仅当该键不存在时才设置。如果 Redis 返回 True,则表示锁成功获取;否则,表示锁已被其他客户端占用。
  • expire:为锁设置超时时间,避免死锁发生。如果客户端崩溃或网络中断,锁会在超时后自动释放。
  • DEL:释放锁时,首先需要检查当前锁值是否与客户端的值匹配,防止误删其他客户端的锁。

综上所述: 

  • Redis 本身并没有直接提供“分布式锁”功能,但它提供了支持实现分布式锁所需的基础操作(如 SETNXEXPIRE)。
  • 基于这些操作,我们可以构建一个分布式锁系统。因此,可以说 Redis 提供了实现分布式锁的基础构建块,但实现分布式锁的功能依赖于如何使用这些操作。

 如果希望使用一个现成的分布式锁库,可以选择 Redisson,它是基于 Redis 的高层次封装,提供了直接的分布式锁功能。

;