利用redis实现分布式锁
分布式锁一般有三种实现方式:
1. 数据库乐观锁;
2. 基于ZooKeeper的分布式锁;
3. 基于Redis的分布式锁;
这里大概说一下三种方式的优缺点,数据库乐观锁优点是实现简单,只需要for update关键词就可以实现,缺点是无法满足高并发量以及数据库读写频繁的系统
ZooKeeper分布式锁无论是从性能以及实现的功能来说都是非常优秀,只是在开发起来需要一定的基础,对新手可能不是很友好
而本文主要讲第三种利用redis实现分布式锁,优点是开发相对简单,能满足一定并发量的系统,缺点是存在线程争抢锁的问题,当并发量到达一定级别,多个线程去争抢同一个锁,对性能的影响较大
事务以及原子性
虽然Redis是单线程运行,但是在分布式的情况下对同一资源进行操作还是会出现问题,下图是一个简单的例子
所以一定要保证tomcat1以及tomcat2读写的原子性,既读与写要么都执行,要么都不执行。关于事务的原子性可以查询这里
那么如何保证呢,redis在2.6中加入了lua脚本功能可以轻松的解决这个问题,下面是一个简单的例子实现了上述的加100操作
Jedis jedis = jedisPool.getResource();
String script = "local a = redis.call('get', KEYS[0]) a = a + 100 redis.call('set', a)"; jedis.eval(script, 1, rname+"Lock",RedisCacheFactory.FactoryUUID,"1000");
分布式锁的具体实现
大概讲一下思路:首先加锁的方式是向redis里存入一个KEY-VALUE,KEY存入的加锁对象可以是方法、类、数据等等,VALUE存入持有锁的节点(例如tomcat1)
大概整理了一下几个问题:
Q:为什么VALUE存入持有锁的节点
A:为的是防止A加的锁被B给解除,保证只有持有锁的节点才能解锁
Q:怎么存入持有锁的节点
A:这里只是我的思路是在tomcat启的时候生成一个uuid作为该tomcat的token存入到VALUE中
Q:怎么防止死锁
A:利用Redis设置键的过期时间
下面贴出部分代码,仅供参考
加锁
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(),RedisInstance.hostName,Integer.parseInt(RedisInstance.port),5000,password);
Jedis jedis = jedisPool.getResource();
// key1 : key值 argv1 :value值 argv2 :过期时间
String script = "if redis.call('EXISTS',KEYS[1]) ==0 then redis.call('set',KEYS[1],ARGV[1]) redis.call('EXPIRE',KEYS[1],ARGV[2]) return 1 else return 0 end";
long result = (long) jedis.eval(script, 1, rname+"Lock",RedisCacheFactory.FactoryUUID,"1000");
jedis.close();
jedisPool.close();
解锁
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(),RedisInstance.hostName,Integer.parseInt(RedisInstance.port),5000,password);
Jedis jedis = jedisPool.getResource();
String script = "if redis.call('EXISTS',KEYS[1]) ==1 and redis.call('GET',KEYS[1])==ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";
long result = (long) jedis.eval(script, 1, rname+"Lock",RedisCacheFactory.FactoryUUID);
jedis.close();
jedisPool.close();
以上仅个人意见,如有错误的地方,还请各位海涵。
后面可能会整合这次缓存改造的所有环节发出来给大家参考 一下
补充说明一下:lua操作redis时如果操作多个key不在同一节点下会出错,原因是因为Cluster会将数据自动分布到不同的节点(虚拟的16384个slot,具体看这里)。
解决办法 后面会贴出详细教程
利用redis实现分布式锁的更多相关文章
- 利用redis实现分布式锁知识点总结及相关改进
利用redis实现分布式锁知识点总结及相关改进 先上原文,本文只为总结及对相关内容的质疑并提出若干意见,原文内容更详细https://www.cnblogs.com/linjiqin/p/800383 ...
- 【Redis】利用 Redis 实现分布式锁
技术背景 首先我们需要先来了解下什么是分布式锁,以及为什么需要分布式锁. 对于这个问题,我们可以简单将锁分为两种--内存级锁以及分布式锁,内存级锁即我们在 Java 中的 synchronized 关 ...
- springboot利用redis实现分布式锁(redis为单机模式)
1.pom文件添加redis支持 <dependency> <groupId>org.springframework.boot</groupId> <arti ...
- spring boot 利用redisson实现redis的分布式锁
原文:http://liaoke0123.iteye.com/blog/2375469 利用redis实现分布式锁,网上搜索的大部分是使用java jedis实现的. redis官方推荐的分布式锁实现 ...
- 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存
原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...
- 利用redis实现分布式事务锁,解决高并发环境下库存扣减
利用redis实现分布式事务锁,解决高并发环境下库存扣减 问题描述: 某电商平台,首发一款新品手机,每人限购2台,预计会有10W的并发,在该情况下,如果扣减库存,保证不会超卖 解决方案一 利用数据 ...
- 基于redis的分布式锁的分析与实践
前言:在分布式环境中,我们经常使用锁来进行并发控制,锁可分为乐观锁和悲观锁,基于数据库版本戳的实现是乐观锁,基于redis或zookeeper的实现可认为是悲观锁了.乐观锁和悲观锁最根本的区别在于 ...
- 基于redis的分布式锁二种应用场景
“分布式锁”是用来解决分布式应用中“并发冲突”的一种常用手段,实现方式一般有基于zookeeper及基于redis二种.具体到业务场景中,我们要考虑二种情况: 一.抢不到锁的请求,允许丢弃(即:忽略) ...
- 利用多写Redis实现分布式锁原理与实现分析(转)
利用多写Redis实现分布式锁原理与实现分析 一.关于分布式锁 关于分布式锁,可能绝大部分人都会或多或少涉及到. 我举二个例子:场景一:从前端界面发起一笔支付请求,如果前端没有做防重处理,那么可能 ...
随机推荐
- 利用AnyProxy代理监控APP流量
1.介绍 AnyProxy 是阿里巴巴基于 Node.js 开发的一款开源代理服务器. 代理服务器站在客户端和服务端的中间,它可以收集双方通信的每个比特.一个完整的代理请求过程为:客户端首先与代理服务 ...
- 如何从本地远程访问虚拟机内的Mysql服务器?
假设重装了操作系统,则本地的很多软件可能都需要重新安装,比如数据库.但是,假设我们把一些重要的软件安装在虚拟机当中,则在重装操作系统之前,数据库服务器可以和虚拟机一起进行备份.重装操作系统之后,原先的 ...
- GC算法基础
寻找垃圾对象的算法:1. 引用计数(无法处理循环引用) 2. 根寻法(被广泛引用在gc算法中) 清理垃圾的算法: 1. 标记复制 2. 标记清理 3. 标记整理 分代算法的好处: 1. 分代处理, ...
- div+css+position实现简单的纵向导航栏
完成效果: 这应该是很简单的纵向导航栏了. OK,进入正题 首先,我们看上面的效果图可以分析得出,要实现这个效果需要用到的技术点 1.hover 2.position 3.布局 我认为在这个效果的实现 ...
- 7-unittest和requests重构、封装处理get/post请求
1.概念说明 ① unittest:python中自带的单元测试框架,封装了一些校验返回的结果方法和一些用例执行前的初始化操作 ② TestCase:测试用例 ③ TestSuite:测试套,即多个测 ...
- 接口测试工具之Postman笔记
根据学习内容对Postman进行的个人总结,对于Postman说明.安装方法等说明性文字就不赘述了. 下面是页面中元素的和输入说明: New collection:集合可以把同一平台.系统,或功能的接 ...
- PMP:8.项目质量管理
内容中包含 base64string 图片造成字符过多,拒绝显示
- SQL Server对比两字符串的相似度(函数算法)
一.概述 最近有人问到关于两个字符串求相似度的函数,所以就写了本篇文章,分别是“简单的模糊匹配”,“顺序匹配”,“一对一位置匹配”.在平时的这种函数可能会需要用到,业务需求不一样,这里只给出参照 ...
- VS 快捷键使用
代码注释与整理 Ctrl+K+C:注释所选代码块 Ctrl+K+U:取消代码块注释 Ctrl+K+D:整理对齐整个代码区 Ctrl+K+F:整理对齐所选代码块 选择代码 Home:跳转行首 End:跳 ...
- springDatasolr 排序
String sortValue = (String) searchMap.get("sort");// ASC DESC String sortField = (String) ...