分布式锁的实现

一、背景

  • 在分布式系统中,一个应用部署在多台机器中,在某些场景下,为了保证数据的一致性,要求在同一时刻,同一任务只在一个节点上运行,即保证某个行为在同一时刻只能被一个线程执行。
  • 单机单进程多线程环境下,通过锁很容易做到,比如 mutexspinlock信号量 等。
  • 多机多进程环境下,就需要使用 分布式锁 来解决了。
    • 分布式场景:我们的应用由多个节点构成,这些节点可能分布在不同的机器中,也有可能分布在不同的网络环境中,通常这些进程之间通过 socket 进行通信。

二、分布式锁

  • 是什么类型的锁 ?
    • 在分布式场景中实现互斥类型的锁
      • 互斥类型:同一时刻只允许一个执行体进入临界资源
  • 解决了什么问题 ?
    • 在分布式场景中,同时只允许一个节点执行某类任务。
  • 锁 = 资源 + 行为
    • 资源:
      • 要记录进程的全局唯一 ID
      • 放在 数据库zookeeperetcd 中,可以让所有的执行体访问
    • 行为:加锁、解锁。(以网络通信的方式)
      • 加锁:把当前进程的唯一标识打到当前数据库的某一个字段中,作为一个标记,说明当前进程持有锁。
        • 加锁的方式:原来没有标记,现在打上标记了。
      • 解锁:谁加的锁,谁释放锁,也就是加锁对象和解锁对象必须是同一个对象,除了因为网络异常而造成的锁超时情况
        • 解锁的方式:持锁方去清除标记,比如置为 0,这样其他的进程才能去加锁。

三、分布式锁特性

  • 互斥性。
    • 锁打上标记:加锁。
    • 锁取消标记:解锁。
    • 标记:执行体的唯一标识,可以通过雪花算法生成。
  • 锁超时。
    • 在分布式场景中,允许一个进程退出,并希望其他的进程能够继续工作。
    • 当持有锁的进程想要解锁的时候,由于某些原因,比如进程宕机、网络异常,导致无法清除数据库中的标记,也就是持锁的进程没有能力去释放锁了,那么我们应该提供一种机制,让数据库自动地去释放锁 → 时间一到,数据库自动地释放锁
  • 可用性。
    • 合理时间内得到合理的回复
    • 实现:
      • 计算型:开多个备份点。
      • 存储型:
        • 多个备份点。
        • 主从切换。
  • 容错性。
    • 一致性来解决(半数以上)。
      • raft 一致性算法。
      • redlock。
    • 高可用 = 可用性 + 容错性

四、分布式锁类型

  • 重入锁和非重入锁。
    • 重入锁:
      • 允许同一个线程多次获取同一把锁,而不会导致死锁。当一个线程持有锁时,它可以再次获取相同的锁而不被阻塞。
      • std::recursive_mutex
    • 非重入锁:
      • 不允许同一个线程在持有锁的情况下再次获取相同的锁,会导致死锁。
      • std::mutex
  • 公平锁和非公平锁。
    • 公平锁:排队,对应互斥锁。
    • 非公平锁:轮询,对应自旋锁。

五、实现分布式锁

  • 基于中间件来实现 → 所有的节点都能访问到。
  • 资源存储在中间件中。
  • 加锁、解锁行为基于中间件的特性来实现。

MySQL 实现分布式锁

  • 锁的存储:表。
  • 获取锁和释放锁:字段。
  • 互斥语义:
    • 唯一性约束:unique keyprimary key
    • 利用 innodb 中的 S 锁和 X 锁互斥。
      select * from lock where ... lock in share mode;
      update lock set ... where ...
      
  • 锁超时:
    • 表增加一个字段:加锁时间戳
    • 另起进程(超进程),定时检测是否超时。
  • 其他进程怎么获取锁:主动探寻,实现定时器 → MySQL 只能实现非公平锁
  • 递归锁:表中增加一个字段 count。
  • 创建表。
    DROP TABLE IF EXISTS `dislock`;
    CREATE TABLE 

相关推荐

  1. 分布式实现

    2024-04-15 04:14:05       45 阅读
  2. 分布式实现方式

    2024-04-15 04:14:05       46 阅读
  3. 基于redis分布式实现方案

    2024-04-15 04:14:05       64 阅读
  4. 分布式几种实现方式:

    2024-04-15 04:14:05       50 阅读
  5. ZooKeeper 分布式实现方法

    2024-04-15 04:14:05       42 阅读
  6. 分布式几种实现方式

    2024-04-15 04:14:05       38 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-15 04:14:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-15 04:14:05       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-15 04:14:05       82 阅读
  4. Python语言-面向对象

    2024-04-15 04:14:05       91 阅读

热门阅读

  1. 反射+配置文件+抽象工厂模式

    2024-04-15 04:14:05       41 阅读
  2. 工作流引擎项目解析(二)

    2024-04-15 04:14:05       108 阅读
  3. 【面试八股文之通信协议】

    2024-04-15 04:14:05       40 阅读
  4. Go语言中如何处理goroutine和循环变量

    2024-04-15 04:14:05       36 阅读
  5. 多多采集器使用指南 拼多多商家爬虫工具介绍

    2024-04-15 04:14:05       110 阅读
  6. kotlin基础学习教程以及代码案例

    2024-04-15 04:14:05       36 阅读
  7. WLAN故障处理

    2024-04-15 04:14:05       39 阅读
  8. Vue取消表单校验提示的方法

    2024-04-15 04:14:05       31 阅读
  9. 秒杀优化-基于阻塞队列实现秒杀优化

    2024-04-15 04:14:05       39 阅读
  10. VRTK/SteamVR手柄震动功能

    2024-04-15 04:14:05       34 阅读
  11. Docker - MySQL

    2024-04-15 04:14:05       36 阅读