这是我参与更文挑战的第19天,活动详情查看:更文挑战
字符串对象的批量获取命令
获取字符串对象的命令有 get key,如果要获取 n 个健值,则要执行 n 次的 get key 命令,总时间消耗为 。
Redis可以支撑每秒数万次的读写操作,但是这里的读写操作是针对服务端的。对于客户端来说,每条命令,除了执行时间还有网络时间。由于执行命令时间在服务端已经优化到很高效,因此每条命令的网络时间成了更大的开销,对于开发人员来说,网络可能会成为性能的瓶颈。
使用 mget key [key] 命令,可以批量获取健值,对于获取 n 个健值,时间消耗为 。使用mget命令可以有效提高开发效率。
使用批量操作, 有助于提高业务处理效率, 但是要注意的是每次批量操作所发送的命令数不是无节制的, 如果数量过多可能造成Redis阻塞或者网络拥塞。
渐进式遍历命令
在Redis中,使用keys、hgetall、smembers、zrange四个遍历型命令时,可能产生阻塞问题。从Redis 2.8 版本之后,提供 scan、hscan、sscan、zscan四个命令实现渐进式遍历。
scan命令
## scan命令
scan cursor [match pattern] [count number]
- cursor是必需参数, 实际上cursor是一个游标, 第一次遍历从0开始, 每次scan遍历完都会返回当前游标的值, 直到游标值为0, 表示遍历结束。
- match pattern是可选参数, 它的作用的是做模式的匹配, 这点和keys的模式匹配很像。
- count number是可选参数, 它的作用是表明每次要遍历的键个数, 默认值是10, 此参数可以适当增大。
和keys命令执行时会遍历所有键不同, scan采用渐进式遍历的方式来解决keys命令可能带来的阻塞问题, 每次scan命令的时间复杂度是O(1) , 但是要真正实现keys的功能, 需要执行多次scan。
现有一个Redis有26个键(英文26个字母) , 现在要遍历所有的键, 使用scan命令效果的操作如下。 第一次执行scan 0, 返回结果分为两个部分: 第一个部分6就是下次scan需要的cursor, 第二个部分是10个键。
127.0.0.1:6379> scan 0
1) "6"
2) 1) "w"
2) "i"
3) "e"
4) "x"
5) "j"
6) "q"
7) "y"
8) "u"
9) "b"
10) "o"
使用新的cursor="6", 执行scan 6
127.0.0.1:6379> scan 6
1) "11"
2) 1) "h"
2) "n"
3) "m"
4) "t"
5) "c"
6) "d"
7) "g"
8) "p"
9) "z"
10) "a"
这次得到的cursor="11", 继续执行scan 11得到结果cursor变为0, 说明所有的键已经被遍历过了
127.0.0.1:6379> scan 11
1) "0"
2) 1) "s"
2) "f"
3) "r"
4) "v"
5) "k"
6) "l"
hscan、sscan、zscan命令
这三个命令的使用方式与scan命令相类似。
hscan面向哈希类型,用以解决hgetall命令可能发生的阻塞问题。sscan面向集合类型,用以解决smembers命令可能发生的阻塞问题。zscan面向有序集合类型,用以解决zrange命令可能发生的阻塞问题。
渐进式遍历命令的缺点
渐进式遍历可以有效的解决keys等命令可能产生的阻塞问题, 但是渐进式遍历命令并非完美无瑕, 如果在遍历的过程中如果有键的变化(增加、 删除、 修改) ,那么遍历效果可能会碰到如下问题:
-
新增的键可能没有遍历到,
-
遍历出了重复的键等情况
也就是说渐进式遍历命令并不能保证完整的遍历出来所有的键, 这些是我们在开发时需要考虑的。