redis分布式锁实践
分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的
我们先来看一个无锁的情况下会导致什么问题:
这是一个普通的更新用户年龄的功能,各层代码如下,访问controller层,一个更新,一个查询

这是service层,我们使用contdownlatch发令枪来模拟线程同时并的情况,发令枪设为32,即32个线程同时去请求修改年龄,

这里使用线程池来提交多线程任务,看代码知道,这里我们已经有了判断年龄的操作,当查询用户查询大于0时,才去调更新用户年龄-1的方法,等下看看有没有用

这里是sql,可以看到两个sql,一个查询用户年龄,一个会执行用户年龄每次减1 ,

这里是用户数据,我们可以看到,用户UID为UR12324的用户,他的年龄是30,接着我们来调32个线程来操作减他年龄

我们请求下这个方法

然后看看结果:


可以看到库中年龄已被减为-2,在未加锁的情况下,查询较验并没有什么作用,此时如果加个synchronized或lock锁肯定能避免这种情况,但我们本文讨论的是多实例或分布式环境中,此加锁方式仍然会产生问题,感兴趣的可以试下是不是
下面我们开始实现一个redis分布式锁,来避免这种情况发生,先说说实现思路:
1,线程请求访问前先调用加锁的方法,加锁就去里生成一个随机数同时保存在线程本地变量和redis的某key中,此key设有效期为200ms,具体值根据业务执行时间自行调整,加锁成功;
2.其它线程试着访问拿出它本地变量与redis中某key进行比较,如果不一致,则说明有锁,此线程休眠一段时间,再试着加锁;
3.加锁成功的线程在操作结束后删掉它持有锁(用lua实现,保证原子性,在它比对和删除锁的过程中,其它线程不会加锁成功),让其它线程再次加锁以执行任务;
下面看看我们写的锁代码:
片段1:使用redislock 实现lock来复写它的方法

片段2:试着加锁的方法

片段3:解锁方法,此处首先从线程本地变量获取它的随机数,然后调用lua脚本,与redis中key相比较,如果相同则删除,否则返回0;

此为lua脚本方法,用此方法可以保证判断和删除的原子性,在此过程中没有线程可以操作此key

到此为止,我们锁基本写完,来测试下有没有用:

我们在此方法前后分别加入加锁和解锁方法,使用方式和lock锁一样, 我们重新把年龄恢复到30后来测试一下吧
先看看日志

这里可以看到各个线程争夺锁的情况,再看看执行结果


这里我们可以看到虽然是32个线程并发执行,但此值并不会变为负数,加锁成功.
我们可以看到最后2个线程并没有执行方法


此时说明加锁成功,大家可以在分布式环境中测试更明显,有关极端情况下解锁失败后应该做什么也可以由我们自己决定,比redission要灵活,带锁的redis最好是单实例,在集群中可能会出问题,有机会我们再用zk实现下.
redis分布式锁实践的更多相关文章
- spring-boot 中实现标准 redis 分布式锁
一,前言 redis 现在已经成为系统缓存的必备组件,针对缓存读取更新操作,通常我们希望当缓存过期之后能够只有一个请求去更新缓存,其它请求依然使用旧的数据.这就需要用到锁,因为应用服务多数以集群方式部 ...
- 分布式锁实践(一)-Redis编程实现总结
写在最前面 我在之前总结幂等性的时候,写过一种分布式锁的实现,可惜当时没有真正应用过,着实的心虚啊.正好这段时间对这部分实践了一下,也算是对之前填坑了. 分布式锁按照网上的结论,大致分为三种:1.数据 ...
- redis分布式锁的这些坑,我怀疑你是假的开发
摘要:用锁遇到过哪些问题? 一.白话分布式 什么是分布式,用最简单的话来说,就是为了较低单个服务器的压力,将功能分布在不同的机器上面:就比如: 本来一个程序员可以完成一个项目:需求->设计-&g ...
- Redis分布式锁 (图解-秒懂-史上最全)
文章很长,而且持续更新,建议收藏起来,慢慢读! 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : 极致经典 + 社群大片好评 < Java 高并发 三 ...
- 利用redis分布式锁的功能来实现定时器的分布式
文章来源于我的 iteye blog http://ak478288.iteye.com/blog/1898190 以前为部门内部开发过一个定时器程序,这个定时器很简单,就是配置quartz,来实现定 ...
- Redis分布式锁
Redis分布式锁 分布式锁是许多环境中非常有用的原语,其中不同的进程必须以相互排斥的方式与共享资源一起运行. 有许多图书馆和博客文章描述了如何使用Redis实现DLM(分布式锁管理器),但是每个库都 ...
- redis分布式锁和消息队列
最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...
- redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- spring boot redis分布式锁
随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁.分布式锁的实现有很多种,比如基于数据库. zookeeper 等,本文主要介绍使用 Redis 做分布式锁的方式,并封装成spring b ...
随机推荐
- 【一天一道LeetCode】#242. Valid Anagram
一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Given t ...
- popupwindow和listview
在使用PopupWindow的时候,有一个不好的地方就是不太好设置弹出窗体的大小.如果指定绝对大小,那么对于不同分辨率不同尺寸的手机来说,显示出来效果会不同,从而导致用户体验不佳. 为了达到Popup ...
- FND Debug Log(FND_LOG_MESSAGES)
之前每个模块记录日志的方式都不同,都会把日志写到不同的文件中,对于User来说很麻烦,需要记住很多的配置,现在越来越多的模块使用FND Logging来存储日志,比如WIP,RCV,OAF...FND ...
- C语言实现4种常用排序
实在没事搞,反正面试也要用到,继续来写4种排序算法.因为那天用java写了排序,突然想到我是要面试IOS,起码也得用C写.C竟然忘干净了,方法都不会写了.囧啊! 下面用C实现4种排序算法:快速排序.冒 ...
- Get and Post(Unity3D开发之六)
猴子原创,欢迎转载.转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢! 原文地址: http://www.cocos2dev.com/?p=565 unity3d中的www直 ...
- android:layout_gravity和gravity的区别
文章转自http://blog.csdn.net/shakespeare001/article/details/784346,给出了很详细的解释. 1.首先来看看Android:layout_grav ...
- BottomSheet底部动作条使用
底部动作条 底部动作条(Bottom Sheets)是一个从屏幕底部边缘向上滑出的一个面板,使用这种方式向用户呈现一组功能.底部动作条呈现了简单.清晰.无需额外解释的一组操作. 使用环境 底部动作条( ...
- C++对象模型(二):The Semantics of Copy Constructors(拷贝构造函数之编译背后的行为)
本文是 Inside The C++ Object Model's Chapter 2 的部分读书笔记. 有三种情况,需要拷贝构造函数: 1)object直接为另外一个object的初始值 2)ob ...
- ISLR系列:(2)分类 Logistic Regression & LDA & QDA & KNN
Classification 此博文是 An Introduction to Statistical Learning with Applications in R 的系列读书笔记,作为本人的一 ...
- 跨平台移动APP开发进阶(四)AngularJS简介
AngularJS 是一个为动态WEB应用设计的结构框架.它能让你使用HTML作为模板语言,通过扩展HTML的语法,让你能更清楚.简洁地构建你的应用组件. 它的创新点在于,利用 数据绑定 和 依赖注入 ...