文章目录
- 前言
- 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.分布式锁的常规实现方案
- 基于关系型数据库(如mysql)
- 基于表记录实现(创建锁表,与业务抽离,资源字段唯一性限制锁获取)
- 乐观锁(多与业务关联,适用于高并发多读场景)
- 悲观锁(多与业务关联,适用于高并发多写)
- 基于zookeeper
- 自写实现(在相同父节点下创建有序子节点,核心:获取锁-用watch阻塞-前锁释放-唤醒-再次获取-执行业务-释放锁)
- curator-InterProcessMutex
- 基于redis
- 基于jedis自实现
- redisson框架
方案比较
- 从理解的难易程度
zookeeper > 缓存 > 数据库 - 从实现的复杂性角度
数据库 > 缓存 >= zookeeper - 从性能角度
缓存 > zookeeper >= 数据库 - 从可靠性角度
zookeeper > 缓存 > 数据库