# 分布式锁


## 什么是分布式锁？

分布式锁是一种并发技术，它使得多个程序或服务可以安全地访问网络环境中的共享数据。通过锁机制来保证一致性和访问安全性，使每个工作线程都有机会得到资源的权力，从而可靠地释放锁，并且不会造成死锁。

除了 Redis 之外，还有其他可以实现分布式锁的方法，比如 [Zookeeper](https://zookeeper.apache.org/)、[Etcd](https://etcd.io/) 等.

MySQL 上不能使用锁，因为这样它将会面临一致性和可扩展性方面的问题，而 Redis 相比之下具有更快的访问速度，以及更好的跨语言支持和跨域安全性。

分布式锁的目标是能够在网络环境中的多个进程或服务之间实现安全的数据共享，并能保证**数据一致性**、**可容错性**和**无死锁**。

## Redis

### 基于 Redis 实现的问题

1. 使用单台 Redis，会有单点故障问题。
2. Redis Sentinel 保证可用性。由于异步复制，不能保证互斥的安全属性。

### 单 Redis 的正确实现

使用单 Redis 实现资源锁定时，需要创建一个键，该键通常使用 Redis 的过期功能创建，具有固定时长，以便最终释放它。

1. 获取锁
   要获取锁， client 只需要使用 `SET` 命令并设置一个 `NX PX` 参数即可，其中 `NX` 是“仅当密钥不存在时”参数，`PX` 是过期时间，以毫秒为单位。`my_random_value`的一种实现是当前的 UNIX 时间戳 + 客户端 ID

```
SET resource_name my_random_value NX PX 30000
```

2. 释放锁
   只有当密钥存在并且存储在密钥中的值正是我期望的值时才删除该密钥。

```
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end
```

### Redlock

红锁算法是一种分布式锁定机制，用于同步一系列分布式任务，其中 N 个 Redis 主节点可以在不同的计算机或虚拟机上运行。为了获取锁，客户端尝试在所有节点上使用相同的键来锁定它们，并使用一个比总锁自动释放时间短的超时时间。当客户端成功锁定大部分实例时，并且锁的有效期大于零，则认为获得了锁。如果客户端不能获得锁，则会尝试解锁所有节点。

---

[Distributed Locks with Redis](https://redis.io/docs/manual/patterns/distributed-locks/)

