场景举例

分布式系统里有些业务需要加锁。在无状态的多进程服务里,有些业务需要保证状态同步,以免因为客户端抖动造成并发问题。

举个例子:

  1. 假设某业务会进行读取和存储操作,有 A, B 两个请求同时进入了集群,并且可能被分别分配到了集群中两个不同的节点,在宏观上他们可以说是并发执行的;
  2. A 请求进来时,进行了读取,但未完成存储;
  3. 由于并发关系,B 请求也在交叉进行业务运算。由于读取和储存操作不是原子性的,有可能会造成 B 在 A 完成储存之前,先进行了数据的修改;
  4. 而此时 A 要对同一个数据源进行写操作时,却又把 B 的数据覆盖了;

解决方法

为了保持一致性,保证 A 和 B 不允许同时进行,在分布式场景下我们没办法通过本地变量来实现锁,因为服务分布在不同的机器。因此需要有一个中间服务来保证状态唯一性。

这里通过 redis 来实现

思路如下:

  1. 加锁:在业务请求进来时,首先通过 redis.setnx() 设置一个 key, 而且这个 key 必须是针对这次请求唯一的。比如说 ID 为 10 的用户,操作了数据 ID 为 42 的订单数据。那么我们可以通过这两个 ID 来组合出一个业务唯一的 key: ORDER_10_42:lock

  2. 过期机制:通过 redis.expire() 给这个 key 创建一个过期时间,防止极端情况下,锁也能通过 TTL 机制正常释放;

  3. 释放锁:通过 redis.del() 来主动删除 key.