redis获取存在的键值_Redis 分布式锁、限流
谈及分布式系统的时候,很多企业都会使用到分布式锁,分布式锁的实现方案目前主要是存在两种,redis实现和zookeeper实现。
redis实现方案是多个线程相互竞争,在redis的某一个节点内创建一个键值对,谁能创建成功谁就获取到了锁。锁的释放就是删除当前线程创建的键值对,交给剩余线程去争抢。
/** * 应该有两个时间 一个是redis中的键失效时间 一个是执行是循环的跳出时间 * @param key * @param expire * @return */ @Override public Lock tryLock(String key, int expire, int waitime) { Boolean success; Long start = System.currentTimeMillis(); Long end = System.currentTimeMillis() + (waitime * 1000); Long number = 0L; Lock lock = new Lock(Lockeys+key , UUID.randomUUID().toString() , 0L); while(true){ success = redisTemplate.opsForValue().setIfAbsent(lock.getKey(),lock.getValue(),expire, TimeUnit.SECONDS); if(success == null){ //此处应该抛出异常 获取锁失败 throw new RuntimeException("获取锁失败"); } if(success){ break; } //等待时间太长自动释放 Long curtime = System.currentTimeMillis(); if(curtime>end){ break; } try { Thread.sleep(100); //休眠100毫秒 number++;//也可以根据自旋的次数来选择释放 } catch (InterruptedException e) { e.printStackTrace(); } } Long locktime = System.currentTimeMillis(); lock.setLocktime(locktime-start); lock.setFalg(success); return lock; }
tryLock方法试图去获取锁,获取成功返回true,获取失败返回false。上面的代码主要的封装一个Lock对象,对象中存在的属性是键值对、锁的获取时间等。请求redis的原子操作类去试图创建一个有限时间的键值对。创建成功的线程返回true执行后续的业务逻辑,未获取锁的线程不断在轮询去请求redis试图获取锁,所以线程设置了休眠100毫秒,减少不必要的线程不断的轮询redis。不断轮询的线程不可能一致让它阻塞在此,所以我们这边设置了一个时间,线程等待一定的时间未拿到锁之后,直接返回false。
锁释放:
/** * 为了防止锁释放的不是当前锁,需要校验value * @param lock * @param * @return */ @Override public Boolean unlock(Lock lock) { String value = (String) redisTemplate.opsForValue().get(lock.getKey()); if(value.equals(lock.getValue())){ return redisTemplate.delete(lock.getKey()); }else { return false; } }
锁的释放其实就是在redis中删除当前线程创建的键值对,怎么保证删除对应的键值对是当前线程创建的呢?我们这边比较了一个key值对应的value值,只有两者相同才会执行删除操作。
使用redis的分布式锁绕不开的一个问题就是业务逻辑执行超时后,锁自动释放,所以就无法保证原子性操作。Redis的Liberary中提供了一个第三方的插件Redisson。其大致流程如图所示:
redisson存在一个watch(看门狗)机制,当前业务逻辑执行超时还未释放锁的时候,会定期延长锁的超时时间。
限流对于分布式系统而言是绕不开的问题,redis提供的几种限流的实现方式
(lua脚本实现原子操作)
限流算法:令牌桶算法、漏桶算法
令牌桶算法:存在一个定时任务不断的向桶里面发送令牌,桶里面溢出的话,令牌会丢弃。
一个请求进来会首先去桶中获取令牌,令牌可以获取多个,获取到令牌后才能转发请求,未获取到令牌,请求丢弃。
漏桶算法:
以一定的速率向桶中放置令牌,然后一定的速率流出。突发的大批量请求不适合使用漏桶算法。
lua脚本,通过lua实现redis令牌增加的原子操作
--lua 下标从 1 开始-- 限流 keylocal key = KEYS[1]-- 限流大小local limit = tonumber(ARGV[1])-- 获取当前流量大小local curentLimit = tonumber(redis.call('get', key) or "0")if curentLimit + 1 > limit then -- 达到限流大小 返回 return 0;else -- 没有达到阈值 value + 1 redis.call("INCRBY", key, 1) -- EXPIRE后边的单位是秒 redis.call("EXPIRE", key, 10) return curentLimit + 1end
入参key值和limit限制,如若操作数量则返回0,没有超过限制则Key对应得数量+1。设置key值得过期时间10秒。
我是凯腾凯,互联网浪潮下一枚苟且偷生的程序员
redis获取存在的键值_Redis 分布式锁、限流相关推荐
- redis setnx 分布式锁_Redis 分布式锁PHP
Redis 分布式锁的作用 在单机环境下,有个秒杀商品的活动,在短时间内,服务器压力和流量会陡然上升.这个就会存在并发的问题.想要解决并发需要解决一下问题 1.提高系统吞吐率也就是qps 每秒处理的请 ...
- Redis教程:NoSQL键值存储
课程大纲 Redis是使用ANSI C编写的具有可选持久性的开源,网络化,内存中键值数据存储.根据DB-Engines.com的月度排名,Redis是最受欢迎的键值存储. 它的名字意思是远程字典服务器 ...
- 【Redis】Redis 哈希 Hash 键值对集合操作 ( 哈希 Hash 键值对集合简介 | 查询操作 | 增加操作 | 修改操作 )
文章目录 一.哈希 Hash 键值对集合 二.查询操作 1.Redis 中查询 Hash 键值对数据 2.查询 Hash 键是否存在 3.查询 Hash 中所有的键 Field 4.查询 Hash 中 ...
- C#递归获取JSON所有键值对
因工作需要,我需要获取JSON所有键值对. 这里我使用List存储,因为有键冲突,但是要求是所有键值对都需要,不理会冲突,所以没有使用字典. public static List<string& ...
- map中获取数组_如何从php多维数组中获取特定的键值?
点击蓝字关注我们!每天获取最新的编程小知识! 源 / php中文网 源 / www.php.cn 在这篇文章中,我们将给大家介绍如何在php中从多维数组中获取特定的键值数组.这里我们将使用a ...
- Redis应用详解(一)分布式锁
1. 前言 在某些场景中,多个进程必须以互斥的方式独占共享资源,这时用分布式锁是最直接有效的. 随着技术快速发展,数据规模增大,分布式系统越来越普及,一个应用往往会部署在多台机器上(多节点),在有些场 ...
- 【2020尚硅谷Java大厂面试题第三季 04】Redis 9种数据类型使用场景,分布式锁演变步骤,lua脚本,redis事务,Redisson,Redis内存占用,删除策略,内存淘汰策略,手写LRU
1.安装redis6.0.8 2023 02 02 为:redis-7.0.8.tar.gz 2.redis传统五大数据类型的落地应用 3.知道分布式锁吗?有哪些实现方案?你谈谈对redis分布式锁的 ...
- Redis面试常问3 如何实现分布式锁 记住Redis的原子性
Redis面试常问3 如何实现分布式锁 上面的伪代码有问题 从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改: http://redisdoc.com/string ...
- 深度解析串行并发并行,开发人员需彻底搞懂丨mysql|redis|skynet|协程|索引|读写分离|分布式锁|主从同步
深度解析串行并发并行,开发人员需彻底搞懂 视频讲解如下,点击观看: 深度解析串行并发并行,开发人员需彻底搞懂丨mysql|redis|skynet|协程|索引|读写分离|分布式锁|主从同步丨C/C++ ...
最新文章
- 查询Oracle中字段名带.的数据
- 使用plsql连接远程oracle数据库配置
- 什么是集群(cluster)
- 知识图谱数据构建的“硬骨头”,阿里工程师如何拿下?
- css3波浪纹路_使用CSS3实现的波浪分隔线
- SpringBoot:搭建第一个Web程序
- mybatisplus批量插入原理_Word如何批量打印请柬、奖状、桌牌?一键批量制作就这么简单...
- FPGA资源评估方法
- cgdb 不显示源码问题
- 利用CNN和迁移学习方法识别植物叶片疾病
- Guava学习笔记:Immutable(不可变)集合
- python bootstrap 中位数_【机器学习】Bootstrap详解
- php 如何开发oa系统,如何开发oa系统
- c语言编程中分数怎么表示,用C语言编程平均分数
- C语言sb代码,10个重要的算法C语言实现源代码
- 关于电子科技大学学生用餐情况的一些调查
- zabbix触发器通过钉钉发送警报
- 【原理】Basic Integer Overflows
- 微信公众号怎么生成能追踪效果的二维码?
- 基于Java毕业设计校园面包超市系统源码+系统+mysql+lw文档+部署软件