文章目录

  • 前言
  • 1.分布式锁简介
  • 2.分布式锁必要性
  • 3.分布式锁的常规实现方案


前言

本文主要用于介绍常规分布式锁的使用及其原理,在主篇中进行了常规分布式锁的扫盲介绍,在子篇中介绍了现主流分布式锁框架的源码以及自写学习demo解析。 全部代码及介绍:https://gitee.com/FWEM/distributed-lock文章主要分为以下两个部分:

  • 本篇:
    1、常规分布式锁的扫盲介绍
  • 子篇:
    1、基于mysql实现的分布式锁原理及案例 2、基于zookeeper实现的分布式锁原理及框架源码解析 3、基于redis实现的分布式锁原理及框架源码解析

1.分布式锁简介

在如今互联网中许多程序都是采用分布式部署的,同一个资源被多个进程共享,分布式锁便是用于解决在这种场景的的数据一致性问题。

2.分布式锁必要性

在单机运行的时代,也会出现线程共享资源的场景,此时我们使用线程间加锁机制来解决这一问题,即同一时间内只能由一个线程操作某一资源,当使用完该资源后才能允许下一线程操作该资源。不同的编程语言提供了一些线程间加锁的API(java:lock、synchronized等,c++:mutex、share_mutex等)。

到了程序分布式部署的时代,此时线程间的锁已经不能满足进程共享资源的场景,如果不使用加锁机制会造成生产中数据不一致的问题,影响业务的正常运作,因此为了解决这一问题需要引用分布式锁。分布式锁,是指在分布式的部署环境下,通过锁机制来让多客户端互斥的对共享资源进行访问。

综上,分布式锁需要具备以下三个基础条件:

  • 排他性:在同一时间只会有一个客户端能获取到锁,其它客户端无法同时获取
  • 避免死锁:这把锁在一段有限的时间之后,一定会被释放(正常释放或异常释放)
  • 高可用:获取或释放锁的机制必须高可用且性能佳

此外使用分布式锁时还需要考虑分布式锁是否满足当前业务需求,如锁公平性、可重入性、是否阻塞。

3.分布式锁的常规实现方案

  1. 基于关系型数据库(如mysql)
  • 基于表记录实现(创建锁表,与业务抽离,资源字段唯一性限制锁获取)
  • 乐观锁(多与业务关联,适用于高并发多读场景)
  • 悲观锁(多与业务关联,适用于高并发多写)
  1. 基于zookeeper
  • 自写实现(在相同父节点下创建有序子节点,核心:获取锁-用watch阻塞-前锁释放-唤醒-再次获取-执行业务-释放锁)
  • curator-InterProcessMutex
  1. 基于redis
  • 基于jedis自实现
  • redisson框架

方案比较

  • 从理解的难易程度
    zookeeper > 缓存 > 数据库
  • 从实现的复杂性角度
    数据库 > 缓存 >= zookeeper
  • 从性能角度
    缓存 > zookeeper >= 数据库
  • 从可靠性角度
    zookeeper > 缓存 > 数据库