首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java高频面试题- 每日三连问?【Day24】 — Redis篇(四)

list 还有个指令叫 blpop, 在没有消息的时候,它会阻塞住直 到消息到来。 能不能生产一次消费多次呢? 使用 pub/sub 主题订 阅者模式,可以实现 1:N 的消息队列。...使用 sortedset,拿时间 戳作为 score,消息内容作为 192key 调用 zadd 来生产消息,消费者用 zrangebyscore 指令获取 N 秒之前的数据轮询进行 处理。...正经回答: 先拿 setnx 来争抢锁,抢到之后,再用 expire 给锁加一个过期时间防止锁忘记了释放。...如果在 setnx 之后执行 expire 之前进程意 外 crash 或者要重启维护了,那会怎么样?...set 指令有参数,这个应该是可以同时把 setnx expire 合成一条指令来用的 - End -

23930
您找到你想要的搜索结果了吗?
是的
没有找到

012:Redis分布式锁

如果在 setnx expire 之间服务器进程突然挂掉了,可能是因 为机器掉电或者是被人为杀掉的,就会导致 expire 得不到执行,也会造成死锁。...这种问题的根源就在于 setnx expire 是两条指令而不是原子指令。如果这两条指令可 以一起执行就不会出现问题。也许你会想到用 Redis 事务来解决。...为了治理这个乱象,作者加入了 set 指令的扩展参数,使得 setnx expire 指令可以一起执行,彻底解决了分布式锁的乱象。从此以后所有的第三方分布式锁 library 可以休息了。.... > del lock:codehole 上面这个指令就是 setnx expire 组合在一起的原子指令,它就是分布式锁的 奥义所在。...紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnxexpire合成一条指令来用的!

83010

Redis系列(二):Redis的分布式锁解析及应用

比如在微服务的架构下,多个应用服务要同时对同一条数据做修改,要确保数据的正确性,那就只能有一个应用修改成功。...String类型实现 使用setnx(SET if Not Exists)指令实现,即如果 key 不存在,才会设置它的值,否则什么也不做。...通过expire指令实现锁过期时间害存在一些问题,试想如果expire出错,没有成功执行,那么也将会造成前面的死锁情况。...因为 setnx expire 是两条指令而不是原子指令,在Redis2.8版本中,可以通过set key velue ex timeout nx来实现setnxexpire两条指令。...但匹配value删除key是两条指令,不是原子操作,且redis中没有提供set这样的扩展参数,没法直接通过指令实现原子操作。

15210

天下无难试之Redis面试刁难大全

Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用原理方面对小伙伴们进行各种刁难。...先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。...这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样? 这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。...紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnxexpire合成一条指令来用的!...你给出两个词汇就可以了,forkcow。

78231

你可能不知道的Redis用法

原子性问题 实现以上逻辑后,仍存在问题,比如在执行setnx指令之后,但在expire指令时服务器出现异常,没有给锁设置上过期时间,锁依然会陷入死锁的状态,一直不会释放。...可能你会想到事务,但在这里不行,因为expire是依赖于setnx的执行结果的,如果没有抢到锁,expire不应该被执行。事务里没有if-else的逻辑,要么全部执行,要么一个都不执行。...在Redis 2.8 版本中,作者加入了set指令的扩展参数,使得setnxexpire指令可以一起执行。.... > del lock.test 上面的指令就是setnxexpire组合在一起的原子指令。...该模块使用了漏斗算法,并提供了原子的限流指令指令只有一条:cl.throttle,对着文档来使用即可。 7.

64930

使用复述,实现分布式锁及其优化

此种方法看似没有什么问题,但其实则有一个漏洞:在加锁的过程中,客户端顺序的向复述,服务器发送了SETNX到期命令,那么假设在SETNX命令执行完成之后,在到期命令发出去之前客户端发生崩溃(或客户端与复述...> 当复述,服务器收到这样的指令序列时,C1C2的SETNX都同时返回了1,此时C1C2都认为自己拿到了锁,这种情况明显是不符合预期的。...(有些同学会提到复述的管道特性,此处明显不适用,因为第二条指令的执行以来与第一条执行的结果,管道无法实现) 另外,上面的分布式锁还有一个问题,那就是服务器之间时间同步的问题。...(“过期”、钥匙(1),当时(ARGV[2))) 返回 真正的 其他的 返回 假 结束 注意:此脚本中命令的执行并不是严格意义上的原子性,如果其中第二条指令到期执行失败,整个脚本执行会返回错误,但是第一条指令...因为脚本的提交执行只有一条复述,命令,就避免了上面所说的客户端异常问题。

835100

Redis-分布式锁

占"坑"一般使用:setnx(set if not exists)指令,只允许被一个程序占有,使用完后调用del释放锁。...1、在申请锁时,给这把锁设置一个"租期":127.0.0.1:6379> SETNX lock 1    // 加锁127.0.0.1:6379> EXPIRE lock 10  // 10s后自动过期现在的操作...,加锁、设置过期是 2 条命令,有没有可能只执行了第一条,第二条却「来不及」执行的情况发生呢?...例如:1、SETNX 执行成功,执行 EXPIRE 时由于网络问题,执行失败2、SETNX 执行成功,Redis 异常宕机,EXPIRE 没有机会执行3、SETNX 执行成功,客户端异常崩溃,EXPIRE...Redis 2.6.12 版本之前,我们需要想尽办法,保证 SETNX EXPIRE 原子性执行,还要考虑各种异常情况如何处理。

14610

Redis(3)——分布式锁深入探究

但是匹配 value 删除 key 在 Redis 中并不是一个原子性的操作,也没有类似保证原子性的指令,所以可能需要使用像 Lua 这样的脚本来处理了,因为 Lua 脚本可以 保证多个指令的原子性执行...SETTEX/ SETNX 最底层实现 void setGenericCommand(client *c, int flags, robj *key, robj *val, robj *expire,...ok_reply : shared.ok); } 就像上面介绍的那样,其实在之前版本的 Redis 中,由于 SETNX EXPIRE 并不是 原子指令,所以在一起执行会出现问题。...也许你会想到使用 Redis 事务来解决,但在这里不行,因为 EXPIRE 命令依赖于 SETNX 的执行结果,而事务中没有 if-else 的分支逻辑,如果 SETNX 没有抢到锁,EXPIRE 就不应该执行...为了解决这个疑难问题,Redis 开源社区涌现了许多分布式锁的 library,为了治理这个乱象,后来在 Redis 2.8 的版本中,加入了 SET 指令的扩展参数,使得 SETNX 可以 EXPIRE

48420

redis做分布式锁可能不那么简单

这个问题还是要从计算机的发展说起,随着计算机硬件的不断升级,多核cpu,多线程,多通道等技术把计算机的计算速度大幅度提升,原来同一时间只能执行一条cpu指令的时代已经过去。...5.支持阻塞非阻塞 ReentrantLock 一样支持 lock trylock 以及 tryLock(long timeOut)。...若键key 已经存在, 则SETNX 命令不做任何动作。SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。...但是这里不行,因为 expire 是依赖于 setnx 的执行结果的,如果 setnx 没抢到锁,expire 是不应该执行的。...以上情况的出现是因为两个命令并非一个原子性操作,所以在redis 2.8 版本之后出现了新的命令 SETEX key seconds value 所以现在可以利用一条原子性操作的命令来获取锁 redis

61050

深入理解分布式锁

比如: 127.0.0.1:6379> setnx lock redisLock (integer) 1 127.0.0.1:6379> expire lock 10 // do something....... 127.0.0.1:6379> del lock (integer) 1 上面的逻辑看似是不会发生死锁,其实不然,如果在setnxexpire命令之间,客户端发生了异常,可以是物理异常,比如断电...这种情况发生的死锁,其根本原因是setnxexpire是两条指令,不具有原子性,客户端在执行完第一条指令后,不能保证第二条指令一定能正常执行。...也许有人会想到Redis事务机制,但是事务机制是为了保证多条命令要么同时成功,要么同时失败,而这里的expire指令是依赖setnx指令的执行结果的,如果setnx指令没有成功抢到锁,那么expire指令不应该去执行...为了解决这个问题,在Redis的2.8版本及更新版本,为set命令加入了扩展参数,使得set命令的扩展参数融合了setnxexpire两条指令,使得两者成为一条原子指令,解决了上面的所有问题。

42030

漫画:什么是分布式锁?

setnx不支持超时参数,所以需要额外的指令,伪代码如下: expire(key, 30) 综合起来,我们分布式锁实现的第一版伪代码如下: if(setnx(key,1) == 1){ expire...因为上面的伪代码中,存在着三个致命问题: 1. setnxexpire的非原子性 设想一个极端场景,当某线程执行setnx,成功得到了锁: ?...setnx刚执行成功,还未来得及执行expire指令,节点1 Duang的一声挂掉了。 ? 这样一来,这把锁就没有设置过期时间,变得“长生不老”,别的线程再也无法获得锁了。 怎么解决呢?...setnx指令本身是不支持传入超时时间的,幸好Redis 2.6.12以上版本为set指令增加了可选参数,伪代码如下: set(key,1,30,NX) 这样就可以取代setnx指令。...当过去了29秒,线程A还没执行完,这时候守护线程会执行expire指令,为这把锁“续命”20秒。守护线程从第29秒开始执行,每20秒执行一次。 ? 当线程A执行完任务,会显式关掉守护线程。 ?

1K30

漫画:什么是分布式锁?

setnx命令并不完善,后续会介绍替代方案) 3.Zookeeper分布式锁 利用Zookeeper的顺序临时节点,来实现分布式锁等待队列。...setnx不支持超时参数,所以需要额外的指令,伪代码如下: expire(key, 30) 综合起来,我们分布式锁实现的第一版伪代码如下: if(setnx(key,1) == 1){ expire...因为上面的伪代码中,存在着三个致命问题: 1. setnxexpire的非原子性 设想一个极端场景,当某线程执行setnx,成功得到了锁: setnx刚执行成功,还未来得及执行expire指令,节点...setnx指令本身是不支持传入超时时间的,幸好Redis 2.6.12以上版本为set指令增加了可选参数,伪代码如下: set(key,1,30,NX) 这样就可以取代setnx指令。...当过去了29秒,线程A还没执行完,这时候守护线程会执行expire指令,为这把锁“续命”20秒。守护线程从第29秒开始执行,每20秒执行一次。 当线程A执行完任务,会显式关掉守护线程。

28930

程序员修神之路--redis做分布式锁可能不那么简单

这个问题还是要从计算机的发展说起,随着计算机硬件的不断升级,多核cpu,多线程,多通道等技术把计算机的计算速度大幅度提升,原来同一时间只能执行一条cpu指令的时代已经过去。...5 支持阻塞非阻塞 ReentrantLock 一样支持 lock trylock 以及 tryLock(long timeOut)。...若键key 已经存在, 则SETNX 命令不做任何动作。SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。...但是这里不行,因为 expire 是依赖于 setnx 的执行结果的,如果 setnx 没抢到锁,expire 是不应该执行的。...以上情况的出现是因为两个命令并非一个原子性操作,所以在redis 2.8 版本之后出现了新的命令 SETEX key seconds value 所以现在可以利用一条原子性操作的命令来获取锁 redis

43940

redis分布式锁解决多进程多线程下单个进程单个线程运行

2.redis的分布式锁实现 2.1 setnx+expire setnx key value,将key设置为value,当键不存在时,才能成功,若键存在,什么也不做,成功返回1,失败返回0。...SETNX实际上就是SET IF NOT Exists的缩写。...setnx key val expire key seconds 但是,上述两个操作不具有原子性,如果执行完第一条指令应用异常或者重启了,锁将无法过期。...if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then redis.call('expire',KEYS[1],ARGV[2]) else return...直接使用可能存在如下问题: 超时解锁导致并发 例如:如果线程 A 成功获取锁并设置过期时间 30 秒,但线程 A 执行时间超过了 30 秒,锁过期自动释放,此时线程 B 获取到了锁,线程 A 线程 B

97610

Redis几个常见面试题目

5.怎么用Redis创建分布式锁 先用setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。...注意:如果在setnx之后,并且在执行expire之前,进程意外崩溃或者要重启维护了,这个锁就永远得不到释放了。...为了解决这个问题,set指令有非常复杂的参数,可以同时把setnxexpire合成一条指令 6.假如Redis里面有1亿个key,其中有10万个key是以固定的前缀开头的,如何将这些全部找出来?...如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1秒1次,这个时候最多会丢失1s的数据。...(3) 为了主从复制的速度连接的稳定性,MasterSlave最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master

28030
领券