由于项目重构需要,之前原本保存在应用内存下的一个BlockingQuene,需要修方案放到redis里面,所以一对一的写了一个RedisBlockingQuene,但是过程中发现redis的list中,阻塞做了小优化,让我们看看吧。

日常使用的redis命令

连接redis,并登录

1
2
3
4
5
6
7
#redis version
./redis-server -v
Redis server v=4.0.9 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=f9e9200ea1e870b1
#connect redis server
./redis-cli -h 127.0.0.1 -p 6379
#auth
auth 123456

普通操作SET key value [EX seconds][PX milliseconds] [NX|XX]

将字符串值 value 关联到 key

如果 key 已经持有其他值, SET 就覆写旧值,无视类型。

对于某个原本带有生存时间(TTL)的键来说, 当 SET 命令成功在这个键上执行时, 这个键原有的 TTL 将被清除。

可选参数

从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改:

  • EX second :设置键的过期时间为 second 秒。 SET key value EX second 效果等同于 SETEX key second value
  • PX millisecond :设置键的过期时间为 millisecond 毫秒。 SET key value PX millisecond 效果等同于 PSETEX key millisecond value
  • NX :只在键不存在时,才对键进行设置操作。 SET key value NX 效果等同于 SETNX key value
  • XX :只在键已经存在时,才对键进行设置操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#set/get key value
127.0.0.1:6379> set key 1
OK
127.0.0.1:6379> get key
"1"

#set key value [EX seconds]
127.0.0.1:6379> set key-expire expire ex 10
OK
127.0.0.1:6379> ttl key-expire
(integer) 2
127.0.0.1:6379> get key-expire
"expire"
127.0.0.1:6379> get key-expire
(nil)

#set key value [EX seconds] [PX milliseconds] [NX|XX]
#SETNX set if not exists
127.0.0.1:6379> SET not-exists-key "value" NX
OK
127.0.0.1:6379> SET not-exists-key "value" NX
(nil)
127.0.0.1:6379> get not-exists-key
"value"
#SETXX set if exists
127.0.0.1:6379> SET exists-key "value" XX
(nil)
127.0.0.1:6379> SET exists-key "value"
OK
127.0.0.1:6379> SET exists-key "new-value" XX
OK

list

普通使用LPOP,LPUSH,LLEN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#LPUSH key value [value ...]
127.0.0.1:6379> LPUSH list 'value1'
(integer) 1
127.0.0.1:6379> LPUSH list value2
(integer) 2
127.0.0.1:6379> LPUSH list value3
(integer) 3
127.0.0.1:6379> LLEN list
(integer) 3
127.0.0.1:6379> LPOP list
"value3"
127.0.0.1:6379> LPOP list
"value2"
127.0.0.1:6379> LPOP list
"value1"

文艺使用BLPOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#BLPOP key [key ...] timeout 多个list,顺序拿到就结束,都没有则超时timeout后返回nil
127.0.0.1:6379> LPUSH list 'value1'
(integer) 1
127.0.0.1:6379> LPUSH list value2
(integer) 2
127.0.0.1:6379> LPUSH list value3
(integer) 3
127.0.0.1:6379> LPUSH list1 value3
(integer) 1
127.0.0.1:6379> BLPOP list list1 10
1) "list" #key
2) "value3" #value

#timeout 0
127.0.0.1:6379> BLPOP list list1 10
1) "list"
2) "value2"
127.0.0.1:6379> BLPOP list list1 10
1) "list"
2) "value1"
127.0.0.1:6379> BLPOP list list1 10
1) "list1"
2) "value3"
127.0.0.1:6379> BLPOP list list1 10
^[[A
(nil)
(10.09s)
127.0.0.1:6379>
127.0.0.1:6379> BLPOP list list1 0
| #waiting直到拿到值

这里支持从多个list中获取,我个人感觉应该是有多种考虑可能

  • 减少阻塞的连接数,间接提高连接使用率。但是实际应用中,同一个功能可以从多个list里面拿数据的并不是很多。
  • 还有一种就是针对BRPOPLPUSH的备份命令,如果从原队列没拿到,继续从备份对接获取值

曾经使用场景