语法

1
SETRANGE key offset value

可用版本

≥ 2.2.0

时间复杂度

$O(1)$

不包含复制新字符串的时间。通常情况下,这个字符串非常小,所以摊销后的复杂度是 $O(1)$。否则,复杂度是 $O(M)$,M 是字符串参数 value 的长度。

ACL类别

@write, @string, @slow

用字符串参数 value 覆盖存储在 key 上的字符串的一部分,覆盖的位置从偏移量 offset 开始。

例如,存储在键 user 原来的字符串值为 Johnson,现在用字符串 LIN 替换该字符串值从偏移量 4 开始之后的所有字符,覆盖后最终的字符串值为 JohnLIN

1
2
3
4
5
6
7
8
redis> SET user "Johnson"
OK
redis> GET user
"Johnson"
redis> SETRANGE user 4 "LIN"
(integer) 7
redis> GET user
"JohnLIN"

如果偏移量 offset 大于存储在 key 上的字符串的长度,则用零字节(zero-bytes)进行填充该字符串以使偏移量合法。

例如,存储在键 username 上原来的字符串为 JohnLIN,现在通过 SETRANGE 命令,用字符串 LIN 替换该字符串从偏移量 10 开始之后的所有字符,但该字符串的长度只有 7,所以会先使用三个零字节(\x00)填充到该字符串的左侧,使字符串的长度变为 10,然后再用字符串 LIN 替换该字符串值从偏移量 10 开始之后的所有字符:

1
2
3
4
5
6
redis> GET username
"JohnLIN"
redis> SETRANGE username 10 "LIN"
(integer) 13
redis> GET username
"JohnLIN\x00\x00\x00LIN"

不存在的键则被认为是空字符串,所以这个命令将确保它持有一个足够大的字符串,以便能够在偏移处设置值。如:

1
2
3
4
redis> SETRANGE jk 2 "LIN"
(integer) 5
redis> GET jk
"\x00\x00LIN"

注意:我们可以设置的最大偏移量是 $2^{29} -1$(536870911),这是因为 Redis 字符串被限制在 512 兆字节。如果需要设置的偏移量超过这个大小,我们可以使用多个键。

警告:当设置最后一个可能的字节,并且存储在 key 处的字符串值还没有持有字符串值,或者持有一个小的字符串值,Redis 需要分配所有的中间内存,这可能会阻塞服务器一段时间。在 2010 年的 MacBook Pro 上,设置字节号 536870911(512MB分配)大约需要 300ms,设置字节号 134217728(128MB分配)大约需要 80ms,设置位号 33554432(32MB分配)大约需要 30ms,设置位号 8388608(8MB分配)大约需要 8ms。请注意,一旦完成了第一次分配,以后对同一键的 SETRANGE 的调用将不会有分配的开销。

返回值

返回修改后的字符串长度。

(END)