基于MongoDB的分布式锁的实现
2021-04-24 本文已影响0人
大数据ZRL
背景
- 并发量:小于50
- 不同机器上的多个线程修改同一份数据
参考链接
优秀的分布式锁应该具有的特性
- 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
- 高可用、高性能的获取锁与释放锁
- 具备可重入特性:锁失效前可以重新获取锁而不会出现死锁情况
- 具备锁失效机制、防止死锁
- 具备非阻塞锁特性,即没有获取到锁直接返回获取锁失败
基于Zookeeper方式
- https://www.jianshu.com/p/b9e17ebfb1fa
- 锁:创建节点目录
- 优点
具备高可用、可重入、阻塞锁特性、可解决失效死锁问题 - 缺点
因为需要频繁的创建和删除节点,性能上不如Redis方式
基于Redis方式
- 创建锁
// 当且仅当key不存在时,set一个key为val的字符串,返回1;
// 若key存在,则什么都不做,返回0。
SETNX key val;
- 设置超时时间
// 为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。
expire key timeout;
- 释放锁
// 删除key
delete key;
- 单机Redis(Jedis)
- Redisson(支持可重入锁)
- 架设在Redis基础上的一个Java驻内存数据网格(In-Memory Data Grid)。充分的利用了Redis键值数据库提供的一系列优势,基于Java实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。
- RedLock(解决单点故障的问题)
- 有N个Redis master,这些节点完全互相独立,不存在主从复制或者其他集群协调机制
- 有N/2+1节点获取锁则成功获取锁
基于MongoDB方式
demo.gif存在问题
- 锁信息还未同步到其他节点,当前节点就挂了,可能会导致两个线程都创建锁成功了
- 不支持可重入性
- MongoDB读写性能不够高,但是并发量不高,不要求很高的及时性,当前够用了