分布式锁闲谈

分布式锁闲谈

前言

服务器单机情况下,要锁住某个资源,我们一般用到的是synchronized,lock等锁,这是java提供的,也确实能很有效的锁住资源。

但是在服务器集群的情况下,上面这些单机锁就不起作用了,你能锁住这台机器,但剩下的机器都没锁,就没有意义。
所以,一般解决这种问题,我们都用分布式锁。

分布式锁原理

分布式锁,主要原理就是新增了一个第三方存储介质,代替以前的synchronized。
假设服务器A对某个资源加锁后,就在这个第三方介质中记录,然后其他服务器再访问该资源的时候,就能知道这个资源被锁住了,效果就达到了。
所以也可以说,这个第三方资源,也可以理解成将服务器集群强行变成了一个单机服务器了。

一般情况下,能担当这个第三方介质的,有以下三种。

1.数据库
2.redis
3.zookeeper

1.数据库

不管集群有几个服务器,都会操作一张表
所以,想要加锁,只需在数据库中插入一条数据即可,记录这个资源的唯一标识,状态为已加锁。
再有加锁的请求,一查数据库已经加锁了,就是没有获取到锁。

一般基于数据库的分布式锁,都会考虑以下几个问题
锁的失效时间(一般做法就是job定时扫,删掉过期的锁,但多久才算过期,是一个很值得仔细研究的问题,一般都是因具体业务来定)
数据库的可靠性(这个倒不是主要问题,一般可以通过搭建集群等方式解决)
数据库的效率问题(毕竟数据库是读磁盘,肯定没有读内存快)

2.redis

这个应该是最常见的,redis分布式锁。
setNx方法估计很多人都用过,不多说了,set if not exist
旧版本的redis,加锁和设置过期时间,但这样是有问题的,比如加锁了,但没有来得及设置过期时间,服务挂了,那么这个锁就死锁了
新版redis,相当于将这两步合成一个方法了,支持多参数,这就感觉很完美啊,不过我没用过,可以试试,应该没问题。

一般基于redis的分布式锁,会考虑以下问题:
锁的失效问题(和数据库分布式锁一样,失效时间设置多少算最优,没有答案,只能job异步扫,一样的问题,所以不能算是一个优雅的解决方案)
锁是非阻塞的 (成功失败都会立即返回,这个要看业务怎么操作了,也可以在业务上手动阻塞住,这不是问题,但要知道)

3.zookeeper

大数据高并发,一般用这个
使用临时有序节点,服务器A的方法加锁就在对应方法节点上创建一个临时有序节点,算是获得锁,因为第一个创建的,序号最小,所以后面再有其他服务器想要加锁时,一查自己的节点的序号不是最小,所以就算没有获得锁。
因为zookeeper的临时有序节点,当加锁的这个线程断掉后,这个节点也自动消失,那么锁也就自动释放了,是不是感觉特别合适做分布式锁,上面两个关于锁的失效问题,用zookeeper得到了优雅的解决

一般需要注意的是:
zookeeper相对复杂(zookeeper算是比较重量级的,甚至有些小项目都不会用到zookeeper,所以也没有必要为了一个简单的分布式锁的问题,强行使用zookeeper)
性能问题(一般和redis比性能,都是弟弟)

总结

在性能方面,redis > zookeeper > 数据库
在实现的复杂度方面,zookeeper > redis > 数据库
对于新手而言,数据库 > redis > zookeeper
可靠性方面,zookeeper > redis > 数据库

所以,一般项目用redis分布式锁就可以了,
如果对可靠性要求很高,那么建议考虑zookeeper分布式锁,
几乎很少用数据库分布式锁,主要还是性能问题。

补充

其实分布式锁就是一个集群环境如何共享资源的问题,我们看问题的角度不应该仅仅停留在分布式锁这里。很多问题的解决方案,其实都是大同小异的。
比如shiro的集群session共享,一般做法也是放在redis中,其实和这个redis的分布式锁原理一样。
还有很多类似场景,欢迎评论补充。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 后端与前端Date类型与String类型互相转换(使用注解)

一:java 后端格式化输出Date类型的属性值到前端 后端返回的类型中,直接定义Date类型,加上此注解,直接将Date类型转成自定义的格式给前端 class TestDateOutput{JsonFormat(pattern "yyyy-MM-dd")private Date create…

spring boot配置对上传文件的大小限制

spring boot配置对上传文件的大小限制 spring-boot 2.0之前 Spring Boot1.4版本后配置更改为(默认单个文件最大1Mb,单次请求文件总数大小最大10Mb): spring.http.multipart.maxFileSize 20MB spring.http.multipart.maxRequestSize20MB spring-boot …

[设计模式] ------ 适配器模式

适配器把一个类的接口,强制变成另外一个类的接口实现。 个人建议,万不得已不要用适配器。但是,你一定要知道有这么个东西。 如果你的项目刚刚起步,就有人用了适配器,那基本上就是滥用。 适配器一般是项目庞大&#xff…

Notepad++中的UTF-8无BOM格式编码

Notepad中,关于utf-8的编码格式,有两种:以UTF-8无BOM格式编码和以UTF-8格式编码。 很容易给人一种错觉,第一反应会选择以UTF-8格式编码,感觉这种就是平时所说的UTF-8,然而这种编码是默认带BOM的&#xff0…

java 上传文件注意事项

java 上传文件注意事项 1、文件名有特殊字符的情况,所以最好是文件名前台url编码,后台再url解码,这点在下载的时候也一样 2、文件大小一定要设置,spring boot 有默认。 3、文件名校验: 3.1、文件后缀校验 3.2、conten…

[设计模式] ------ 装饰模式

首先,假设项目有个核心功能。 随着项目迭代,又产生功能1和功能2 于是有如下需求: 某个场景需要核心功能和功能1组合, 某个场景需要核心功能和功能2组合, 某个场景需要核心功能和功能1和功能2组合, 甚至以后…

hash和一致性hash

hash;简单的hash取余 优点: 计算简单,快速定位 缺点: 容错和扩展差,任何的增加机器或减少机器,都会伴随着重新set值 比如原来有五台机器做缓存,现在加一台,那么余5就变成余6&#x…

[记录]---mysql数据库,decimal类型设置默认值0,不要是null

mysql数据库 类型为decimal的字段,最好把默认值设置为0,不要设置为null。 因为null值在代码中及其容易造成空指针。

Java 线程状态---WAITING(部分转载)

看到一篇关于写线程waiting状态的文章,感觉很生动有趣,转过来保存下。 总结: waiting这个状态,就是等待,明确了等待,就不会抢资源了。 一个线程A在拿到锁但不满足执行条件的时候,需要另一个线…

[记录] --- linux上项目

1.安装jdk8 yum -y list java* 查看可安装java版本 yum install -y java-1.8.0-openjdk-devel.x86_64 java -version jdk在/usr/lib/jvm目录 2.配置环境变量 打开/etc/profile 在profile文件末尾加入: export JAVA_HOME/usr/lib/jvm/java-1.8.0 export PATH$JAVA_HOME/bin:…

[记录] --- linux安装redis

获取redis资源 wget http://download.redis.io/releases/redis-具体版本.tar.gz 解压 tar xzvf redis-具体版本.tar.gz 安装 cd redis-4.0.8 make(这个需要安装了gcc,没有gcc的先执行这个命令:yum install gcc) cd src mkdir /usr/local/redis/etc&…

服务端高并发分布式架构演进之路(转载,图画的好)

这个文章基本上从单机版到最终版,经历了加缓存,加机器,高可用,分布式,最后到云等过程,其实我一直想总结一套类似的东西,没想到有人已经先弄出来了,那就不重复造轮子了,而…

java 记录一个类加载顺序的坑

看看这个,先想想结果打印的顺序和a、b的值 public class ClassLoderTest {public static void main(String[] args) {staticFun();}static ClassLoderTest clt new ClassLoderTest();static {System.out.println(1);}{System.out.println(2);}ClassLoderTest(){Sy…

[前端记录] --- vue axios 等调用完再执行后面的语句

vue 整合echarts的时候,是先axios 调用后台接口,获取数据,再将数据渲染到页面。 一开始的问题是:第一次请求完,页面没数据,再请求一次才出现数据 分析到最后,发下是由于axios是异步请求的&…

docker容器核心技术点

docker容器核心技术点: 容器其实本质上就是一个进程,只不过容器的进程是比较特殊的。 容器技术的核心功能,就是通过约束和修改进程的动态表现,创造出一个“边界”,通过“障眼法”让人觉得它是一个独立的系统。大多数容…

spring-boot 一款无侵入型,轻量级的接口文档生成工具apiggs

spring-boot 一款无侵入型,轻量级的接口文档生成工具apiggs 名字叫:apiggs 使用只需两步,先把插件代码引入pom文件,然后编译打包即可 之后项目的target目录下,就会多出一个apiggs的文件夹,里面便是项目cont…

亚马逊S3文件存储的可视化

windos图形化工具下载:http://s3browser.com/ 类似于用xftp操作linux文件一样方便直观清晰

为什么CAP不能同时满足的简单理解

为什么CAP不能同时满足的简单理解 cap定理:前提是分布式系统中,cap三个只能满足两个,不能同时满足三个特性。 Consistency (一致性):所有节点在同一时间的数据都是完全一致的。 Availability (可用性):服务一直是可用…

Spring的@Scheduled 动态更新cron表达式

常见的本地定时写法如下: Scheduled(cron "0/5 * * * * ?")private void test() {log.info("业务处理逻辑。。。5秒一次");}如果想要动态更新cron表达式,可以这样写: 先写一个类,让cron表达式总是读成员变量…