dot Redis 8 来了——而且是开源的

了解更多

3.1 字符串

返回主页

3.1 字符串

你将会从第 1 章和第 2 章中回忆起,STRING 保存的是字节序列,与许多编程语言中的字符串,甚至是 C/C++ 风格的 char 数组没有显着差异。在 Redis 中,STRING 用于存储三种类型的值

  • 字节字符串值
  • 整数值
  • 浮点数值

整数和浮点数可以按任意数值增加或减少(必要时整数会转换为浮点数)。整数的范围相当于平台的 long 整数范围(32 位平台上为有符号 32 位整数,64 位平台上为有符号 64 位整数),而浮点数的范围和值限制为 IEEE 754 浮点双精度数。这种三向查看最简单的 Redis 值的能力可能是一种优势;它在数据表示方面提供了比仅允许字节字符串值更大的灵活性。

在本节中,我们将讨论 Redis 可用的最简单的结构,STRING。我们将介绍基本的数值递增和递减操作,随后介绍位和子字符串操作调用,你将会明白,即使是最简单的结构也具有一些令人惊讶的功能,使其在各种强大的方式中都非常有用。

在表 3.1 中,你可以看到 Redis STRING 上可用的整数和浮点数递增/递减操作。

表 3.1 Redis 中的递增和递减命令
命令 使用示例和描述
INCR INCR key-name — 将键存储的值增加 1
DECR DECR key-name — 将键存储的值减少 1
INCRBY INCRBY key-name amount — 将键存储的值增加提供的整数值
DECRBY DECRBY key-name amount — 将键存储的值减少提供的整数值
INCRBYFLOAT INCRBYFLOAT key-name amount — 将键存储的值增加提供的浮点数值(在 Redis 2.6 及更高版本中可用)

在 Redis 中设置 STRING 值时,如果该值可以解释为以 10 为底的整数或浮点数值,Redis 将会检测到这一点,并允许你使用各种 INCR*DECR* 操作来操作该值。如果你尝试递增或递减一个不存在或为空字符串的键,Redis 将会像该键的值为零一样进行操作。 如果你尝试递增或递减一个其值不能被解释为整数或浮点数的键,你将会收到一个错误。在下一个列表中,你可以看到与这些命令的一些交互。

列表 3.1 一个示例交互,展示了 Redis 中的 INCRDECR 操作
>>> conn = redis.Redis()
>>> conn.get('key')

当我们获取一个不存在的键时,我们会得到 None 值,该值不会显示在交互式控制台中。

>>> conn.incr('key')
1
>>> conn.incr('key', 15)
16

我们可以递增不存在的键,并且我们可以传递一个可选值来增加超过 1 的值。

>>> conn.decr('key', 5)
11

与递增一样,递减采用一个可选参数,用于指定要递减的量。

>>> conn.get('key')
'11'

当我们获取该键时,它就像一个字符串。

>>> conn.set('key', '13')
True
>>> conn.incr('key')
14

当我们设置该键时,我们可以将其设置为字符串,但仍然可以像操作整数一样操作它。

在阅读其他章节后,你可能会注意到我们实际上只调用 incr()。在内部,Python Redis 库使用传递的可选第二个值调用 INCRBY,如果省略该值,则调用 1。在撰写本文时,Python Redis 客户端库支持 Redis 2.6 的完整命令集,并通过与 incr() 工作方式相同的 incrbyfloat() 方法提供 INCRBYFLOAT 支持。

Redis 还提供了用于读取和写入字节字符串值部分的方法(整数和浮点数值也可以像字节字符串一样访问,尽管这种用法不太常见)。如果我们使用 Redis STRING 值以有效的方式打包结构化数据,这将非常有用,我们将在第 9 章中讨论这一点。表 3.2 显示了一些可以用于操作 Redis 中 STRING 的子字符串和各个位的方法。

表 3.2 Redis 中可用的子字符串操作命令
命令 使用示例和描述
APPEND APPEND key-name value — 将提供的值连接到已存储在给定键中的字符串
GETRANGE GETRANGE key-name start end — 获取子字符串,包括从开始偏移量到结束偏移量的所有字符,包括端点
SETRANGE SETRANGE key-name offset value — 将从提供的偏移量开始的子字符串设置为给定值
GETBIT GETBIT key-name offset — 将字节字符串视为位字符串,并返回字符串中提供的位偏移量处的位的值
SETBIT SETBIT key-name offset value — 将字节字符串视为位字符串,并设置字符串中提供的位偏移量处的位的值
BITCOUNT BITCOUNT key-name [start end] — 计算字符串中 1 位的数量,可以选择从提供的字节偏移量开始和结束
BITOP BITOP operation dest-key key-name [key-name …] — 对提供的字符串执行按位运算 AND、OR、XOR 或 NOT 之一,并将结果存储在目标键中

GETRANGE AND SUBSTR 过去,GETRANGE 被命名为 SUBSTR,并且 Python 客户端继续使用 substr() 方法名从字符串中获取范围。当使用 2.6 之后的 Redis 版本时,你应该使用 getrange() 方法,而对于 2.6 之前的 Redis 版本,则使用 substr()

当使用 SETRANGESETBIT 写入字符串时,如果 STRING 之前不够长,Redis 将会自动使用 null 扩展 STRING,然后再更新和写入新数据。 当使用 GETRANGE 读取 STRING 时,任何超出 STRING 末尾的数据请求都不会返回,但是当使用 GETBIT 读取位时,任何超出 STRING 末尾的位都被视为零。在下面的列表中,你可以看到这些 STRING 操作命令的一些用法。

列表 3.2 一个示例交互,展示了 Redis 中的子字符串和位操作
>>> conn.append('new-string-key', 'hello ')

让我们将字符串 “hello ” 附加到之前不存在的键 “new-string-key” 上。

6L

当附加一个值时,Redis 会返回到目前为止的字符串长度。

>>> conn.append('new-string-key', 'world!')
12L

当附加一个值时,Redis 会返回到目前为止的字符串长度。

>>> conn.substr('new-string-key', 3, 7)

Redis 使用 0 索引,并且当访问范围时,默认包含端点。

'lo wo'

字符串 “lo wo” 来自 “hello world!” 的中间。

>>> conn.setrange('new-string-key', 0, 'H')

让我们设置几个字符串范围。

12

当在字符串内部设置一个范围时,Redis 也会返回字符串的总长度。

>>> conn.setrange('new-string-key', 6, 'W')
12
>>> conn.get('new-string-key')

让我们看看我们现在有什么!

'Hello World!'

是的,我们大写了我们的 H 和 W。

>>> conn.setrange('new-string-key', 11, ', how are you?')

使用 setrange,我们可以替换字符串中的任何位置,并且我们可以使字符串更长。

25
>>> conn.get('new-string-key')
'Hello World, how are you?'

我们替换了感叹号,并在字符串的末尾添加了更多内容。

>>> conn.setbit('another-key', 2, 1)

如果我们写入一个超出字符串大小的位,它会填充 null。

0

设置位也会返回设置之前该位的值。

>>> conn.setbit('another-key', 7, 1)
0
>>> conn.get('another-key')

如果你想解释存储在 Redis 中的位,请记住位偏移量是从最高位到最低位的。

'!'

我们将位 2 和位 7 设置为 1,这给了我们 “!”,也就是字符 33。

在许多其他键值数据库中,数据存储为纯字符串,没有进行操作的机会。其他一些键值数据库确实允许你前置或附加字节,但 Redis 在读取和写入子字符串的能力方面是独一无二的。 在许多方面,即使 Redis 仅提供 STRING 和这些操作字符串的方法,Redis 也比许多其他系统更强大;有进取心的用户可以使用子字符串和位操作调用以及 WATCH/MULTI/EXEC(我们将在 3.7.2 节中简要介绍,并在第 4 章中详细讨论)来构建任意数据结构。 在第 9 章中,我们将讨论使用 STRING 来存储一种简单映射,这可以在某些情况下大大减少内存使用。

通过少量的工作,我们可以存储一些类型的序列,但是我们可以执行的操作种类受到限制。但是,如果我们使用 LIST,我们将会拥有更广泛的命令和操作 LIST 项目的方式。