例:
SCAN 0 MATCH test* COUNT 10 //每次返回10条以test为前缀的key
如何通过 Redis 实现分布式锁
分布式锁
分布式锁是控制分布式系统之间共同访问共享资源的一种锁的实现。如果一个系统,或者不同系统的不同主机之间共享某个资源时,往往需要互斥,来排除干扰,满足数据一致性。
分布式锁需要解决的问题如下:
-
互斥性:任意时刻只有一个客户端获取到锁,不能有两个客户端同时获取到锁。
-
安全性:锁只能被持有该锁的客户端删除,不能由其他客户端删除。
-
死锁:获取锁的客户端因为某些原因而宕机继而无法释放锁,其他客户端再也无法获取锁而导致死锁,此时需要有特殊机制来避免死锁。
-
容错:当各个节点,如某个 Redis 节点宕机的时候,客户端仍然能够获取锁或释放锁。
如何使用 Redis 实现分布式锁
使用 SETNX 实现,SETNX key value:如果 Key 不存在,则创建并赋值。
该命令时间复杂度为 O(1),如果设置成功,则返回 1,否则返回 0。
由于 SETNX 指令操作简单,且是原子性的,所以初期的时候经常被人们作为分布式锁,我们在应用的时候,可以在某个共享资源区之前先使用 SETNX 指令,查看是否设置成功。
如果设置成功则说明前方没有客户端正在访问该资源,如果设置失败则说明有客户端正在访问该资源,那么当前客户端就需要等待。
但是如果真的这么做,就会存在一个问题,因为 SETNX 是长久存在的,所以假设一个客户端正在访问资源,并且上锁,那么当这个客户端结束访问时,该锁依旧存在,后来者也无法成功获取锁,这个该如何解决呢?
由于 SETNX 并不支持传入 EXPIRE 参数,所以我们可以直接使用 EXPIRE 指令来对特定的 Key 来设置过期时间。
用法:
EXPIRE key seconds
程序:
RedisService redisService = SpringUtils.getBean(RedisService.class);
long status = redisService.setnx(key,“1”);
if(status == 1){
redisService.expire(key,expire);
doOcuppiedWork();
}
这段程序存在的问题:假设程序运行到第二行出现异常,那么程序来不及设置过期时间就结束了,则 Key 会一直存在,等同于锁一直被持有无法释放。
出
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
现此问题的根本原因为:原子性得不到满足。
解决:从 Redis 2.6.12 版本开始,我们就可以使用 Set 操作,将 SETNX 和 EXPIRE 融合在一起执行,具体做法如下:
-
EX second:设置键的过期时间为 Second 秒。
-
PX millisecond:设置键的过期时间为 MilliSecond 毫秒。
-
NX&#