基于Redis实现分布式锁
分布式锁具有的特性:
1、排他性:
文件系统:
数据库:主键 唯一约束 for update
性能较差,容易出现单点故障
锁没有失效时间,容易死锁
缓存Redis:setnx
实现复杂:
存在死锁(或短时间死锁)的可能
zookeeper:类似文件系统
实现相对简单
可靠性高
性能较好
应用场景:
自动生成编码,格式为:"YYYYMMDD001"
多客户同时提交数据,数据库里出现多人存储一个编码。应实现效果,每人一个编码。
解决方案:
1、在redis里,创建一个编码池(每天凌晨1点初始化)。
2、每次项目启动,初始化redis编码池
3、编码池里没有编码,去数据库里查询当天最大编码,然后+1
@Component
public class CodeNumPool implements ApplicationRunner { @Autowired
private ICodeNumRedisService codeNumRedisService; @Autowired
private PeopleBusinessBasicInfoRepository peopleBusinessBasicInfoRepository; /**
* @Author: qsy
* @Date: Created in 上午 11:24 2019/1/3/003
* @Description: 每天1:00重置编码池
*/
@Scheduled(cron = "0 0 1 * * ?")
public void ResetCodeNoPool() {
codeNumRedisService.deleteCodeNumPool();
codeNumRedisService.initCodeNumPool(1);
} /**
* @Author: qsy
* @Date: Created in 下午 4:59 2019/1/3/003
* @Description: 项目一启动就初始化redis编码池
*/
@Override
public void run(ApplicationArguments args) throws Exception {
String oldCodeNo = peopleBusinessBasicInfoRepository.findNewCodeNo();
String codeNum = CodeNoUtils.getDateStr(oldCodeNo);
Integer no = StringUtil.stringToInteger(codeNum.substring(9, 13));
codeNumRedisService.deleteCodeNumPool();
codeNumRedisService.initCodeNumPool(no);
}
}
public interface ICodeNumRedisService {
/**初始化编码池*/
boolean initCodeNumPool(int no);
/**获取编码*/
String getCodeNum();
/**清空编码池*/
boolean deleteCodeNumPool();
}
@Service
public class CodeNumRedisServiceImpl implements ICodeNumRedisService {
@Autowired
private RedisTemplate<String, String> redisTemplate; /**
* @Author: qsy
* @Date: Created in 下午 3:01 2019/1/3/003
* @Description: 初始化编码池
*/
@Override
public boolean initCodeNumPool(int no) {
Boolean res = redisTemplate.opsForValue().setIfAbsent(Constans.INIT_NUM_LOCK, Constans.INIT_NUM_LOCK);
if (res) {
ListOperations<String, String> list = redisTemplate.opsForList();
for (int i = no; i < Constans.MAX_NUM; i++) {
String codeNo = StringUtil.DecimalFormat(i, Constans.FORMAT);
list.leftPush(Constans.CODE_NUM_POOL, "P" + DateUtil.getReqDate() + codeNo);
}
redisTemplate.delete(Constans.INIT_NUM_LOCK);
} return true;
} /**
* @Author: qsy
* @Date: Created in 下午 3:01 2019/1/3/003
* @Description: 获取编码
*/
@Override
public String getCodeNum() {
//加锁
while (true) {
Boolean res = redisTemplate.opsForValue().setIfAbsent(Constans.NUM_LOCK, Constans.INIT_NUM_LOCK);
if (res) {
ListOperations<String, String> list = redisTemplate.opsForList();
//释放锁
String num = list.rightPop(Constans.CODE_NUM_POOL);
redisTemplate.delete(Constans.NUM_LOCK);
return num;
}
}
} /**
* @Author: qsy
* @Date: Created in 下午 3:00 2019/1/3/003
* @Description: 清空编码池
*/
@Override
public boolean deleteCodeNumPool() {
return redisTemplate.delete(Constans.CODE_NUM_POOL);
}
}
基于Redis实现分布式锁的更多相关文章
- 基于redis 实现分布式锁的方案
在电商项目中,经常有秒杀这样的活动促销,在并发访问下,很容易出现上述问题.如果在库存操作上,加锁就可以避免库存卖超的问题.分布式锁使分布式系统之间同步访问共享资源的一种方式 基于redis实现分布式锁 ...
- 基于redis的分布式锁
<?php /** * 基于redis的分布式锁 * * 参考开源代码: * http://nleach.com/post/31299575840/redis-mutex-in-php * * ...
- 基于Redis的分布式锁真的安全吗?
说明: 我前段时间写了一篇用consul实现分布式锁,感觉理解的也不是很好,直到我看到了这2篇写分布式锁的讨论,真的是很佩服作者严谨的态度, 把这种分布式锁研究的这么透彻,作者这种技术态度真的值得我好 ...
- 基于 Redis 的分布式锁
前言 分布式锁在分布式应用中应用广泛,想要搞懂一个新事物首先得了解它的由来,这样才能更加的理解甚至可以举一反三. 首先谈到分布式锁自然也就联想到分布式应用. 在我们将应用拆分为分布式应用之前的单机系统 ...
- 基于redis的分布式锁(转)
基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- 基于redis的分布式锁实现
1.分布式锁介绍 在计算机系统中,锁作为一种控制并发的机制无处不在. 单机环境下,操作系统能够在进程或线程之间通过本地的锁来控制并发程序的行为.而在如今的大型复杂系统中,通常采用的是分布式架构提供服务 ...
- 基于redis的分布式锁(不适合用于生产环境)
基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- 基于 redis 的分布式锁实现 Distributed locks with Redis debug 排查错误
小结: 1. 锁的实现方式,按照应用的实现架构,可能会有以下几种类型: 如果处理程序是单进程多线程的,在 python下,就可以使用 threading 模块的 Lock 对象来限制对共享变量的同步访 ...
- 转载:基于Redis实现分布式锁
转载:基于Redis实现分布式锁 ,出处: http://blog.csdn.net/ugg/article/details/41894947 背景在很多互联网产品应用中,有些场景需要加锁处理,比如 ...
- redis系列:基于redis的分布式锁
一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...
随机推荐
- 自定义GridControl编辑器
本文版权归博主 惊梦无痕 所有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作.SourceLink 鉴于网上的针对GridControl的一些代码比较凌乱,且功能分散,故将整理过的代码分享出来 ...
- #6 判断一个数是否为2的n次方
「ALBB面试题」 [题目] 如何判断一个数是否为2的n次方 [题目分析] 看到这种题,相信大家第一反应就是循环除2,这样做肯定是可以得出结果的:但是这种做法无疑大大增加了计算机的运行时间,一个非常大 ...
- Spring Boot 2.x基础教程:快速入门
简介 在您第1次接触和学习Spring框架的时候,是否因为其繁杂的配置而退却了?在你第n次使用Spring框架的时候,是否觉得一堆反复黏贴的配置有一些厌烦?那么您就不妨来试试使用Spring Boot ...
- [Vue] vue2.0
vue实例 所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象 当一个 Vue 实例被创建时,它将 data 对象中的所有的属性加入到 Vue 的响应式系统中.当这些属性的值发生改变时,视 ...
- python 文件和目录操作题库
1. 把一个目录下所有的文件删除,在所有的目录下新建一个a.txt的文件,并在文件下写入"python"关键字. 解题思路: 1.如果目录存在则切换进入目录 ...
- linq用法整理
linq用法整理 普通查询 var highScores = from student in students where student.ExamScores[exam] > score se ...
- c# 抽象类,抽象方法使用(abstract)
入行一年多,在这个IT行业,开发技术主要使用的是.NET,而对应使用的高级语言自然就是c#了.从2017年7月入职后,在平时的工作过程中,只记得使用一些方法去完成逻辑功能,而很少去深究一些语法特性,特 ...
- 简述C#中IO的应用
在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.IO 定义了一系列类.接口. ...
- 在Linux上部署Web项目
You believe it or not there is a feeling, lifetime all not lost to time. 在Linux上部署Web项目 这个是普通的web项目, ...
- 折腾Java设计模式之迭代器模式
迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its ...