你将会从第 1 章和第 2 章中回忆起,STRING 保存的是字节序列,与许多编程语言中的字符串,甚至是 C/C++ 风格的 char 数组没有显着差异。在 Redis 中,STRING 用于存储三种类型的值
整数和浮点数可以按任意数值增加或减少(必要时整数会转换为浮点数)。整数的范围相当于平台的 long 整数范围(32 位平台上为有符号 32 位整数,64 位平台上为有符号 64 位整数),而浮点数的范围和值限制为 IEEE 754 浮点双精度数。这种三向查看最简单的 Redis 值的能力可能是一种优势;它在数据表示方面提供了比仅允许字节字符串值更大的灵活性。
在本节中,我们将讨论 Redis 可用的最简单的结构,STRING。我们将介绍基本的数值递增和递减操作,随后介绍位和子字符串操作调用,你将会明白,即使是最简单的结构也具有一些令人惊讶的功能,使其在各种强大的方式中都非常有用。
在表 3.1 中,你可以看到 Redis STRING 上可用的整数和浮点数递增/递减操作。
命令 | 使用示例和描述 |
---|---|
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 将会像该键的值为零一样进行操作。 如果你尝试递增或递减一个其值不能被解释为整数或浮点数的键,你将会收到一个错误。在下一个列表中,你可以看到与这些命令的一些交互。
>>> 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 的子字符串和各个位的方法。
命令 | 使用示例和描述 |
---|---|
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()。
当使用 SETRANGE 和 SETBIT 写入字符串时,如果 STRING 之前不够长,Redis 将会自动使用 null 扩展 STRING,然后再更新和写入新数据。 当使用 GETRANGE 读取 STRING 时,任何超出 STRING 末尾的数据请求都不会返回,但是当使用 GETBIT 读取位时,任何超出 STRING 末尾的位都被视为零。在下面的列表中,你可以看到这些 STRING 操作命令的一些用法。
>>> 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 项目的方式。