单实例redis分布式锁的简单实现
redis分布式锁的基本功能包括, 同一刻只能有一个人占有锁, 当锁被其他人占用时, 获取者可以等待他人释放锁, 此外锁本身必须能超时自动释放.
直接上java代码, 如下:
package com.test; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import java.util.Arrays; import java.util.concurrent.TimeUnit; /** * 简单的单实例redis分布式锁 * 没有实现的高级功能:锁的重入、锁的续约等 * * @Author:tt * @Description: * @CreateTime:2019/6/12 */ public class SingleRedisLock { private JedisPool jedisPool; /** * 获取锁 * * @param lockKey 锁的key * @param lockVal 锁的val,可以利用来实现"避免误删别人锁"、"锁的重入"等功能 * @param lockMaxLifeTime 锁的最大生命时长,到期自动销毁,单位:毫秒 * @param tryWaitingTime 等待获取锁的超时时间,单位:毫秒 * @param waitingSleepTime 等待获取锁的阻塞周期,单位:毫秒,设置过短会造成cpu竞争,设置过长会造成浪费,需依赖于'具体业务平均的执行时长' * @return */ public Boolean tryLock(String lockKey, String lockVal, int lockMaxLifeTime, int tryWaitingTime, int waitingSleepTime) { //lua脚本,让逻辑简单清晰,同时保证原子性 //setNX:成功-1,失败-0 String lua = " if redis.call('set',KEYS[1],ARGV[1],'PX',ARGV[2],'NX') then return 1 else return 0 end "; //获取锁的开始时间 Long tryBeginTime = System.currentTimeMillis(); //轮询 while (true) { Long result = null; Jedis jedis = null; try { jedis = jedisPool.getResource(); result = (Long) jedis.eval(lua, Arrays.asList(lockKey), Arrays.asList(lockVal, String.valueOf(lockMaxLifeTime))); } catch (Exception e) { e.printStackTrace(); } finally { if (jedis != null) { try { jedis.close(); } catch (Exception e) { } } } //获取锁成功 if (Long.valueOf(1).equals(result)) { return true; } //当前时间 Long now = System.currentTimeMillis(); //获取等待超时,就不用获取了 if (now - tryBeginTime >= tryWaitingTime) { return false; } try { //阻塞等一会儿再重新去获取 TimeUnit.MILLISECONDS.sleep(waitingSleepTime); } catch (InterruptedException e) { } } } /** * 释放锁 * * @param lockKey * @param lockVal * @return */ public void releaseLock(String lockKey, String lockVal) { //如果lockVal是自己的再删除,防止误删,场景来源:当前锁的持有者操作时间太长,锁已经自动释放并被别人占有了 String lua = "if redis.call('get', KEYS[1]) == ARGV[1] then redis.call('del', KEYS[1]) end "; Jedis jedis = null; try { jedis = jedisPool.getResource(); jedis.eval(lua, Arrays.asList(lockKey), Arrays.asList(lockVal)); } catch (Exception e) { e.printStackTrace(); } finally { if (jedis != null) { try { jedis.close(); } catch (Exception e) { } } } } //测试 public static void main(String[] args) { //连接池 JedisPool jedisPool = new JedisPool(new GenericObjectPoolConfig(), "127.0.0.1", 6379, 2000, "test123"); SingleRedisLock simpleRedisLock = new SingleRedisLock(); simpleRedisLock.jedisPool = jedisPool; //模拟10个并发 for (int i = 0; i < 10; i++) { new Thread(() -> { String lockKey = "TEST_LOCK_KEY"; String threadName = Thread.currentThread().getName(); //获取锁 Boolean locked = simpleRedisLock.tryLock(lockKey, threadName, 30000, 5000, 200); //获取锁失败 if (!locked) { System.err.println(">>> " + threadName + " 获取锁失败"); return; } //获取锁成功,模拟执行业务操作 System.out.println(">>> " + threadName + " 获取锁成功"); doShortBusiness(); //doLongBusiness(); //释放锁 simpleRedisLock.releaseLock(lockKey, threadName); }).start(); } try { TimeUnit.MILLISECONDS.sleep(60000); } catch (InterruptedException e) { } } //短任务:100毫秒 static void doShortBusiness() { try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { } } //长任务:3秒 static void doLongBusiness() { try { TimeUnit.MILLISECONDS.sleep(3000); } catch (InterruptedException e) { } } }
锁的高级功能包含锁的重入、锁的续约等, 当然为了保证锁的高可用, redis还有主从、集群等部署方式, 对应的锁的实现也有区别, 略微复杂, 不过有现成的框架可供我们参考使用, 比较知名的如Redisson, 一个强大的redis客户端, 当然包括对“分布式锁”的完美实现, 其支持redis单实例、哨兵、集群等模式。
单实例redis分布式锁的简单实现的更多相关文章
- Redis分布式锁实现简单秒杀功能
这版秒杀只是解决瞬间访问过高服务器压力过大,请求速度变慢,大大消耗服务器性能的问题. 主要就是在高并发秒杀的场景下,很多人访问时并没有拿到锁,所以直接跳过了.这样就处理了多线程并发问题的同时也保证了服 ...
- redis 分布式锁的简单使用
RedisLock--让 Redis 分布式锁变得简单 目录 1. 项目介绍 2. 快速使用 2.1 引入 maven 坐标 2.2 注册 RedisLock 2.3 使用 3. 参与贡献 4. 联系 ...
- springmvc单Redis实例实现分布式锁(解决锁超时问题)
一.前言 关于redis分布式锁, 查了很多资料, 发现很多只是实现了最基础的功能, 但是, 并没有解决当锁已超时而业务逻辑还未执行完的问题, 这样会导致: A线程超时时间设为10s(为了解决死锁问题 ...
- 自己写了个简单的redis分布式锁【我】
自己写了个简单的redis分布式锁 [注意:此锁需要在每次使用前都创建对象,也就是要在线程内每次都创建对象后使用] package redis; import java.util.Collection ...
- .NetCore使用Redis,StackExchange.Redis队列,发布与订阅,分布式锁的简单使用
环境:之前一直是使用serverStack.Redis的客服端,今天来使用一下StackExchange.Redis(个人感觉更加的人性化一些,也是免费的,性能也不会差太多),版本为StackExch ...
- Redis分布式锁实例
maven依赖 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</ ...
- Redis分布式锁
Redis分布式锁 分布式锁是许多环境中非常有用的原语,其中不同的进程必须以相互排斥的方式与共享资源一起运行. 有许多图书馆和博客文章描述了如何使用Redis实现DLM(分布式锁管理器),但是每个库都 ...
- Redlock(redis分布式锁)原理分析
Redlock:全名叫做 Redis Distributed Lock;即使用redis实现的分布式锁: 使用场景:多个服务间保证同一时刻同一时间段内同一用户只能有一个请求(防止关键业务出现并发攻击) ...
- Redlock:Redis分布式锁最牛逼的实现
普通实现 说道Redis分布式锁大部分人都会想到:setnx+lua,或者知道set key value px milliseconds nx.后一种方式的核心实现命令如下: - 获取锁(unique ...
随机推荐
- 在Java中按字节获得字符串长度的三种方法
转载:http://www.blogjava.net/nokiaguy/archive/2010/04/11/317982.html 由于Java是基于Unicode编码的,因此,一个汉字的长度为1, ...
- V Server Ubuntu
Ubuntu下代理伺服器通常使用squid 安裝 sudo apt-get install squid 修改squid.conf配置 sudo vim /etc/squid/squid.conf 公司 ...
- 数据结构——算法之(027)( 在O(1)时间内删除链表结点)
[申明:本文仅限于自我归纳总结和相互交流,有纰漏还望各位指出. 联系邮箱:Mr_chenping@163.com] 题目:在O(1)时间内删除链表结点.且不知道链表头 题目分析: 1.把要删除节点的下 ...
- 推荐美丽的flash网页MP3音乐播放器
文章来源:PHP开发学习门户 地址:http://www.phpthinking.com/archives/491 在网页制作中.假设想在网页中插入mp3音乐来增添网页的互动感,提升用户体验度,这个时 ...
- VFL语言简洁
一.VFL语言简洁 VFL(Visual format language)语言是苹果为了简化手写Autolayout代码所创建的专门负责编写约束的代码.为我们简化了许多代码量. 二.使用步骤 使用步骤 ...
- 【http代理报文】自己开发HTTP代理工具,不限语种。
我们知道通过修改浏览器设置可以使用代理访问网页,其实这个操作就是修改了每次的HTTP头. 工作中,我们难免需要通过TCP/IP协议发送HTTP报文来直接请求网页内容(比如爬虫工具),有同学问如何通过H ...
- Olddriver’s books
Olddriver 的书多的吓人,什么算法导论,组合数学英 文版(orz)......他把 n 本书都放在身后的桌子上, 每本书有一定的面积,并且书可以覆盖,求 n 本书覆盖桌面 的面积 输入格式: ...
- openstack 杂记 备忘002
- 如何在vue项目中引入阿里巴巴的iconfont图库
1. 打开 http://www.iconfont.cn/ 2. 选择我们喜欢的图标,点击上面的小车,加入图标库,即右侧的购物车 3.点击购物车,点击下载代码 4.解压下载的文件夹,将文件夹复制到 a ...
- 最大正方形 同luogu1387
这道题下面这么写就够了(n<=100)暴力,枚举 #include<bits/stdc++.h> #define ULL unsigned long long #define MAX ...