利用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实现分布式锁原理与实现分析 一.关于分布式锁 关于分布式锁,可能绝大部分人都会或多或少涉及到. 我举二个例子:场景一:从前端界面发起一笔支付请求,如果前端没有做防重处理,那么可能 ...
随机推荐
- Python开发——15.协程与I/O模型
一.协程(Coroutine) 1.知识背景 协程又称微线程,是一种用户态的轻量级线程.子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完 ...
- 排序算法(sorting algorithm)之 插入排序(insertion sort)
https://en.wikipedia.org/wiki/Insertion_sort loop1: 4,6,1,3,7 -> 4,6,1,3,7 loop2: 4,6,1,3,7 -> ...
- 第十二章 FTP服务器安装与配置
习题 1.简述FTP的连接模式. FTP的连接模式有PORT和PASV两种,其中PORT模式是主动模式,PASV是被动模式, 这里所说的主动和被动都是相对于服务器而言的.如果是主动模式,数据端口为20 ...
- redis在linux云服务器上完整的搭建步骤
Redis的安装 搭建环境: 华为云linux服务器 Linux系统CneterOS-7.3 SSH客户端 Xshell6 安装c语言编译环境软件如下: 安装报错 然后找到了解决方法: 安装kerne ...
- vue数据双向绑定
Vue的双向绑定是通过数据劫持结合发布-订阅者模式实现的,即通过Object.defineProperty监听各个属性的setter,然后通知订阅者属性发生变化,触发相应的回调. 整个过程分为以下几步 ...
- 关于Selenium WebDriver的geckodriver
下载Selenium的最新版本地址:http://selenium-release.storage.googleapis.com/index.html 友情提示:如果一直下载不了,可能是浏览器与下载工 ...
- Redis-01.初探
官网 http://redis.io 中文网 http://redis.cn 命令参考 http://redisdoc.cn Redis(Remote Dictionary Server)是一个开源的 ...
- 转载:Package by feature, not layer
原文地址:Package by feature, not layer Package by feature, not layer The first question in building an a ...
- 公司项目接触到了FormData,总结一下
Javascript FormData() 对象! 1.创建 var formData = new FormData(); 2.如果有form对象 则先获取form表单 然后初始化时直接加入进去 eg ...
- 史上最完整的MySQL注入
原文作者: Insider 免责声明:本教程仅用于教育目的,以保护您自己的SQL注释代码. 在阅读本教程后,您必须对任何行动承担全部责任. 0x00 ~ 背景 这篇文章题目为“为新手完成MySQL注入 ...