Redis - 五种数据类型与常用操作详解

Redis中的数据类型与操作可以总结为"5+1"操作-----五种数据类型以及key的操作。这里的数据类型指的是值类型,如String、HASH、Set、Zset以及list。从宏观来看,Redis是K-V模式。只是V类型不同,称之为不同数据类型。

【1】Key的常见操作

① KEYS pattern

查找所有符合给定模式 pattern 的 key 。

KEYS * 匹配数据库中所有 key 。
KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
KEYS h*llo 匹配 hllo 和 heeeeello 等。
KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。

特殊符号用 \ 隔开。

示例如下:

redis> KEYS *o*
1) "four"
2) "two"
3) "one"

redis> KEYS t??
1) "two"

redis> KEYS t[w]*
1) "two"

redis> KEYS *  # 匹配数据库内所有 key
1) "four"
2) "three"
3) "two"
4) "one"

② exists key

判断某个key是否存在。

返回值:若 key 存在,返回 1 ,否则返回 0 。


③ move key db

将当前数据库的 key 移动到给定的数据库 db 当中(当前库就没有了,被移除了)。

如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key ,或者 key 不存在于当前数据库,那么 MOVE 没有任何效果。

因此,也可以利用这一特性,将 MOVE 当作锁(locking)原语(primitive)。

示例如下:

# key 存在于当前数据库

redis> SELECT 0                             # redis默认使用数据库 0,为了清晰起见,这里再显式指定一次。
OK

redis> SET song "secret base - Zone"
OK

redis> MOVE song 1                          # 将 song 移动到数据库 1
(integer) 1

redis> EXISTS song                          # song 已经被移走
(integer) 0

redis> SELECT 1                             # 使用数据库 1
OK

redis:1> EXISTS song                        # 证实 song 被移到了数据库 1 (注意命令提示符变成了"redis:1",表明正在使用数据库 1)
(integer) 1


# 当 key 不存在的时候

redis:1> EXISTS fake_key
(integer) 0

redis:1> MOVE fake_key 0                    # 试图从数据库 1 移动一个不存在的 key 到数据库 0,失败
(integer) 0

redis:1> select 0                           # 使用数据库0
OK

redis> EXISTS fake_key                      # 证实 fake_key 不存在
(integer) 0


# 当源数据库和目标数据库有相同的 key 时

redis> SELECT 0                             # 使用数据库0
OK
redis> SET favorite_fruit "banana"
OK

redis> SELECT 1                             # 使用数据库1
OK
redis:1> SET favorite_fruit "apple"
OK

redis:1> SELECT 0                           # 使用数据库0,并试图将 favorite_fruit 移动到数据库 1
OK

redis> MOVE favorite_fruit 1                # 因为两个数据库有相同的 key,MOVE 失败
(integer) 0

redis> GET favorite_fruit                   # 数据库 0 的 favorite_fruit 没变
"banana"

redis> SELECT 1
OK

redis:1> GET favorite_fruit                 # 数据库 1 的 favorite_fruit 也是
"apple"

④ persist key

移除给定 key 的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。


⑤ expire key seconds

为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。

在 Redis 中,带有生存时间的 key 被称为『易失的』(volatile)。

生存时间可以通过使用 DEL 命令来删除整个 key 来移除,或者被 SET 和 GETSET 命令覆写(overwrite),这意味着,如果一个命令只是修改(alter)一个带生存时间的 key 的值而不是用一个新的 key 值来代替(replace)它的话,那么生存时间不会被改变。

比如说,对一个 key 执行 INCR 命令,对一个列表进行 LPUSH 命令,或者对一个哈希表执行 HSET 命令,这类操作都不会修改 key 本身的生存时间。

另一方面,如果使用 RENAME 对一个 key 进行改名,那么改名后的 key 的生存时间和改名前一样。

RENAME 命令的另一种可能是,尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)会被删除,然后旧的 key 会改名为 another_key ,因此,新的 another_key 的生存时间也和原本的 key 一样。

使用 PERSIST 命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个『持久的』(persistent) key 。

  • 更新生存时间

可以对一个已经带有生存时间的 key 执行 EXPIRE 命令,新指定的生存时间会取代旧的生存时间。

  • 过期时间的精确度

在 Redis 2.4 版本中,过期时间的延迟在 1 秒钟之内 —— 也即是,就算 key 已经过期,但它还是可能在过期之后一秒钟之内被访问到,而在新的 Redis 2.6 版本中,延迟被降低到 1 毫秒之内。

示例如下:

redis> SET cache_page "www.google.com"
OK

redis> EXPIRE cache_page 30  # 设置过期时间为 30 秒
(integer) 1

redis> TTL cache_page    # 查看剩余生存时间
(integer) 23

redis> EXPIRE cache_page 30000   # 更新过期时间
(integer) 1

redis> TTL cache_page
(integer) 29996

⑥ EXPIREAT key timestamp

EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置生存时间。不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。

示例如下:

redis> SET cache www.google.com
OK

redis> EXPIREAT cache 1355292000     # 这个 key 将在 2012.12.12 过期
(integer) 1

redis> TTL cache
(integer) 45081860

⑦ PEXPIRE key milliseconds

这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。

示例如下:

redis> SET mykey "Hello"
OK

redis> PEXPIRE mykey 1500
(integer) 1

redis> TTL mykey    # TTL 的返回值以秒为单位
(integer) 2

redis> PTTL mykey   # PTTL 可以给出准确的毫秒数
(integer) 1499

⑧ PEXPIREAT key milliseconds-timestamp

这个命令和 EXPIREAT 命令类似,但它以毫秒为单位设置 key 的过期 unix 时间戳,而不是像 EXPIREAT 那样,以秒为单位。

示例如下:

redis> SET mykey "Hello"
OK

redis> PEXPIREAT mykey 1555555555005
(integer) 1

redis> TTL mykey           # TTL 返回秒
(integer) 223157079

redis> PTTL mykey          # PTTL 返回毫秒
(integer) 223157079318

⑨ ttl key

以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。

返回值:

当 key 不存在时,返回 -2 。
当 key 存在但没有设置剩余生存时间时,返回 -1 。
否则,以秒为单位,返回 key 的剩余生存时间。

ttl keyName

⑩ pttl key

这个命令类似于 ttl命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 ttl命令那样,以秒为单位。

返回值:

当 key 不存在时,返回 -2 。
当 key 存在但没有设置剩余生存时间时,返回 -1 。
否则,以毫秒为单位,返回 key 的剩余生存时间。


(11)type key

返回 key 所储存的值的类型。

返回值:

none (key不存在)
string (字符串)
list (列表)
set (集合)
zset (有序集)
hash (哈希表)

(12)dump key

序列化给定 key ,并返回被序列化的值,使用 RESTORE 命令可以将这个值反序列化为 Redis 键。

序列化生成的值有以下几个特点:

  • 它带有 64 位的校验和,用于检测错误, RESTORE 在进行反序列化之前会先检查校验和。
  • 值的编码格式和 RDB 文件保持一致。
  • RDB 版本会被编码在序列化值当中,如果因为 Redis 的版本不同造成 RDB 格式不兼容,那么 Redis 会拒绝对这个值进行反序列化操作。

序列化的值不包括任何生存时间信息。

示例如下:

redis> SET greeting "hello, dumping world!"
OK

redis> DUMP greeting
"\x00\x15hello, dumping world!\x06\x00E\xa0Z\x82\xd8r\xc1\xde"

redis> DUMP not-exists-key
(nil)

(13)DEL key [key …]

删除给定的一个或多个 key 。

不存在的 key 会被忽略。

实例如下:

#  删除单个 key

redis> SET name huangz
OK

redis> DEL name
(integer) 1


# 删除一个不存在的 key

redis> EXISTS phone
(integer) 0

redis> DEL phone # 失败,没有 key 被删除
(integer) 0


# 同时删除多个 key

redis> SET name "redis"
OK

redis> SET type "key-value store"
OK

redis> SET website "redis.com"
OK

redis> DEL name type website
(integer) 3

【2】String

string是redis中最基本的数据类型,你可以理解成与memcached一模一样的类型,一个key对应一个value。一个redis中字符串value最多可以是512M。

string类型是二进制安全的。意思是redis的string是可以包含任何数据的,比如jpg图片或者序列化的对象。

(1)GET key

返回 key 所关联的字符串值。如果 key 不存在那么返回特殊值 nil 。

假如 key 储存的值不是字符串类型,返回一个错误,因为 GET 只能用于处理字符串值。


(2)SET key value [EX seconds] [PX milliseconds] [NX|XX]

将字符串值 value 关联到 key 。如果 key 已经持有其他值, SET 就覆写旧值,无视类型。

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

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 :只在键已经存在时,才对键进行设置操作。

因为 SET 命令可以通过参数来实现和 SETNX 、 SETEX 和 PSETEX 三个命令的效果,所以将来的 Redis 版本可能会废弃并最终移除 SETNX 、 SETEX 和 PSETEX 这三个命令。

返回值:

在 Redis 2.6.12 版本以前, SET 命令总是返回 OK 。

从 Redis 2.6.12 版本开始, SET 在设置操作成功完成时,才返回 OK 。

如果设置了 NX 或者 XX ,但因为条件没达到而造成设置操作未执行,那么命令返回空批量回复(NULL Bulk Reply)。


(3)SETEX key second value

将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。

如果 key 已经存在, SETEX 命令将覆写旧值。

这个命令类似于以下两个命令:

SET key value
EXPIRE key seconds  # 设置生存时间

不同之处是, SETEX 是一个原子性(atomic)操作,关联值和设置生存时间两个动作会在同一时间内完成,该命令在 Redis 用作缓存时,非常实用。

返回值:

设置成功时返回 OK 。
当 seconds 参数不合法时,返回一个错误。


(4)SETNX key value

将 key 的值设为 value ,当且仅当 key 不存在。

若给定的 key 已经存在,则 SETNX 不做任何动作。

SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。

返回值:

设置成功,返回 1 。
设置失败,返回 0 。


(5)APPEND key value

如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。

如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 一样。

返回值:

追加 value 之后, key 中字符串的长度。


(6)GETSET key value

将给定 key 的值设为 value ,并返回 key 的旧值(old value)。

当 key 存在但不是字符串类型时,返回一个错误。当 key 没有旧值时,也即是, key 不存在时,返回 nil 。

简单一句话,先get然后立即set。


(7)MSET key value [key value …]

同时设置一个或多个 key-value 对。

如果某个给定 key 已经存在,那么 MSET 会用新值覆盖原来的旧值,如果这不是你所希望的效果,请考虑使用 MSETNX 命令:它只会在所有给定 key 都不存在的情况下进行设置操作。

MSET 是一个原子性(atomic)操作,所有给定 key 都会在同一时间内被设置,某些给定 key 被更新而另一些给定 key 没有改变的情况,不可能发生。

实例如下:

redis> MSET date "2012.3.30" time "11:00 a.m." weather "sunny"
OK

redis> MGET date time weather
1) "2012.3.30"
2) "11:00 a.m."
3) "sunny"


# MSET 覆盖旧值例子

redis> SET google "google.hk"
OK

redis> MSET google "google.com"
OK

redis> GET google
"google.com"

返回值:

总是返回 OK (因为 MSET 不可能失败)


(8)GETRANGE key start end

返回 key 中字符串值的子字符串,字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。

负数偏移量表示从字符串最后开始计数, -1 表示最后一个字符, -2 表示倒数第二个,以此类推。

GETRANGE 通过保证子字符串的值域(range)不超过实际字符串的值域来处理超出范围的值域请求。

在 <= 2.0 的版本里,GETRANGE 被叫作 SUBSTR。

实例如下:

redis> SET greeting "hello, my friend"
OK

redis> GETRANGE greeting 0 4          # 返回索引0-4的字符,包括4。
"hello"

redis> GETRANGE greeting -1 -5        # 不支持回绕操作
""

redis> GETRANGE greeting -3 -1        # 负数索引
"end"

redis> GETRANGE greeting 0 -1         # 从第一个到最后一个
"hello, my friend"

redis> GETRANGE greeting 0 1008611    # 值域范围不超过实际字符串,超过部分自动被忽略
"hello, my friend"

(9)SETRANGE key offset value

用 value 参数覆写(overwrite)给定 key 所储存的字符串值,从偏移量 offset 开始。

不存在的 key 当作空白字符串处理。

SETRANGE 命令会确保字符串足够长以便将 value 设置在指定的偏移量上,如果给定 key 原来储存的字符串长度比偏移量小(比如字符串只有 5 个字符长,但你设置的 offset 是 10 ),那么原字符和偏移量之间的空白将用零字节(zerobytes, “\x00” )来填充。

注意你能使用的最大偏移量是 2^29-1(536870911) ,因为 Redis 字符串的大小被限制在 512 兆(megabytes)以内。如果你需要使用比这更大的空间,你可以使用多个 key 。

当生成一个很长的字符串时,Redis 需要分配内存空间,该操作有时候可能会造成服务器阻塞(block)。在2010年的Macbook Pro上,设置偏移量为 536870911(512MB 内存分配),耗费约 300 毫秒, 设置偏移量为 134217728(128MB 内存分配),耗费约 80 毫秒,设置偏移量 33554432(32MB 内存分配),耗费约 30 毫秒,设置偏移量为 8388608(8MB 内存分配),耗费约 8 毫秒。 注意若首次内存分配成功之后,再对同一个 key 调用 SETRANGE 操作,无须再重新内存。

实例如下:

# 对非空字符串进行 SETRANGE

redis> SET greeting "hello world"
OK

redis> SETRANGE greeting 6 "Redis"
(integer) 11

redis> GET greeting
"hello Redis"


# 对空字符串/不存在的 key 进行 SETRANGE

redis> EXISTS empty_string
(integer) 0

redis> SETRANGE empty_string 5 "Redis!"   # 对不存在的 key 使用 SETRANGE
(integer) 11

redis> GET empty_string                   # 空白处被"\x00"填充
"\x00\x00\x00\x00\x00Redis!"

返回值:被 SETRANGE 修改之后,字符串的长度。

一个很重要的作用是,如果某个key-value已经设置了生存时间,该方法不会重置key-value的生存时间!!!


(10)INCR key

原子性地将 key 中储存的数字值增一,注意是原子操作。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

本操作的值限制在 64 位(bit)有符号数字表示之内。

这是一个针对字符串的操作,因为 Redis 没有专用的整数类型,所以 key 内储存的字符串被解释为十进制 64 位有符号整数来执行 INCR 操作。

实例如下:

redis> SET page_view 20
OK

redis> INCR page_view
(integer) 21

redis> GET page_view    # 数字值在 Redis 中以字符串的形式保存
"21"

返回值:

执行 INCR 命令之后 key对应的value 的值。


(11)DECR key

原子性地将 key 中储存的数字值减一,注意是原子操作。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

本操作的值限制在 64 位(bit)有符号数字表示之内。

关于递增(increment) / 递减(decrement)操作的更多信息,请参见 INCR 命令。

实例如下:

# 对存在的数字值 key 进行 DECR

redis> SET failure_times 10
OK

redis> DECR failure_times
(integer) 9


# 对不存在的 key 值进行 DECR

redis> EXISTS count
(integer) 0

redis> DECR count
(integer) -1


# 对存在但不是数值的 key 进行 DECR

redis> SET company YOUR_CODE_SUCKS.LLC
OK

redis> DECR company
(error) ERR value is not an integer or out of range

返回值:

执行 DECR 命令之后 key 的值。


(12)INCRBY key increment

原子性地将 key 所储存的值加上增量 increment 。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 命令。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

本操作的值限制在 64 位(bit)有符号数字表示之内。

关于递增(increment) / 递减(decrement)操作的更多信息,参见 INCR 命令。

实例如下:

# key 存在且是数字值

redis> SET rank 50
OK

redis> INCRBY rank 20
(integer) 70

redis> GET rank
"70"


# key 不存在时

redis> EXISTS counter
(integer) 0

redis> INCRBY counter 30
(integer) 30

redis> GET counter
"30"


# key 不是数字值时

redis> SET book "long long ago..."
OK

redis> INCRBY book 200
(error) ERR value is not an integer or out of range

返回值:

加上 increment 之后, key对应value 的值。


(13)DECRBY key decrement

原子性地将 key 所储存的值减去减量 decrement 。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECRBY 操作。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

本操作的值限制在 64 位(bit)有符号数字表示之内。

实例如下:

# 对已存在的 key 进行 DECRBY

redis> SET count 100
OK

redis> DECRBY count 20
(integer) 80


# 对不存在的 key 进行DECRBY

redis> EXISTS pages
(integer) 0

redis> DECRBY pages 10
(integer) -10

返回值:

减去 decrement 之后, key 对应value的值。

redis中incr、incrby、decr、decrby属于string数据结构,它们是原子性递增或递减操作。

  • incr递增1并返回递增后的结果;
  • incrby根据指定值做递增或递减操作并返回递增或递减后的结果(incrby递增或递减取决于传入值的正负);
  • decr递减1并返回递减后的结果;
  • decrby根据指定值做递增或递减操作并返回递增或递减后的结果(decrby递增或递减取决于传入值的正负);

在设计秒杀方案时,可能会用到这一特性。


【3】Hash

Redis hash是一个键值对集合,是一个string类型的field和value的映射表。hash特别适合用于存储对象,类似java 里面的Map

简而言之,KV模式不变,但V是一个键值对(field – value)。

(1)HSET key field value

将哈希表 key 中的域 field 的值设为 value 。

如果 key 不存在,一个新的哈希表被创建并进行 HSET 操作。

如果域 field 已经存在于哈希表中,旧值将被覆盖。

返回值:

如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1 。
如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。

实例如下:

redis> HSET website google "www.g.cn"       # 设置一个新域
(integer) 1

redis> HSET website google "www.google.com" # 覆盖一个旧域
(integer) 0

(2)HGET key field

返回哈希表 key 中给定域 field 的值。

返回值:

给定域的值。当给定域不存在或是给定 key 不存在时,返回 nil 。


127.0.0.1:6379> hget website google
"www.g.cn"

127.0.0.1:6379> hget google website
(nil)


(3)HEXISTS key field

查看哈希表 key 中,给定域 field 是否存在。

返回值:

如果哈希表含有给定域,返回 1 。
如果哈希表不含有给定域,或 key 不存在,返回 0 。

实例如下:

127.0.0.1:6379> HEXISTS google website
(integer) 0

127.0.0.1:6379> HEXISTS website google
(integer) 1

(4)HMSET key field value [field value …]

同时将多个 field-value (域-值)对设置到哈希表 key 中。

此命令会覆盖哈希表中已存在的域。

如果 key 不存在,一个空哈希表被创建并执行 HMSET 操作。

返回值:

如果命令执行成功,返回 OK 。当 key 不是哈希表(hash)类型时,返回一个错误。

实例如下:

redis> HMSET website baidu "www.baidu.com" taobao "www.taobao.com"
OK


(5)HMGET key field [field …]

返回哈希表 key 中,一个或多个给定域的值。

如果给定的域不存在于哈希表,那么返回一个 nil 值。

因为不存在的 key 被当作一个空哈希表来处理,所以对一个不存在的 key 进行 HMGET 操作将返回一个只带有 nil 值的表。

返回值:

一个包含多个给定域的关联值的表,表值的排列顺序和给定域参数的请求顺序一样。

127.0.0.1:6379> hmget website baidu taobao google
1) "www.baidu.com"
2) "www.taobao.com"
3) "www.g.cn"

(6)HGETALL key

返回哈希表 key 中,所有的域和值。

在返回值里,紧跟每个域名(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。

返回值:

以列表形式返回哈希表的域和域的值。若 key 不存在,返回空列表。

实例如下:

127.0.0.1:6379> HGETALL website
1) "google"
2) "www.g.cn"
3) "baidu"
4) "www.baidu.com"
5) "taobao"
6) "www.taobao.com"

(7)HINCRBY key field increment

为哈希表 key 中的域 field 的值加上增量 increment 。

增量也可以为负数,相当于对给定域进行减法操作。

如果 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。

如果域 field 不存在,那么在执行命令前,域的值被初始化为 0 。

对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。

本操作的值被限制在 64 位(bit)有符号数字表示之内。

返回值:

执行 HINCRBY 命令之后,哈希表 key 中域 field 的值。

实例如下:

# increment 为正数

redis> HEXISTS counter page_view    # 对空域进行设置
(integer) 0

redis> HINCRBY counter page_view 200
(integer) 200

redis> HGET counter page_view
"200"


# increment 为负数

redis> HGET counter page_view
"200"

redis> HINCRBY counter page_view -50
(integer) 150

redis> HGET counter page_view
"150"


# 尝试对字符串值的域执行HINCRBY命令

redis> HSET myhash string hello,world       # 设定一个字符串值
(integer) 1

redis> HGET myhash string
"hello,world"

redis> HINCRBY myhash string 1              # 命令执行失败,错误。
(error) ERR hash value is not an integer

redis> HGET myhash string                   # 原值不变
"hello,world"

(8)HINCRBYFLOAT key field increment

为哈希表 key 中的域 field 加上浮点数增量 increment 。

如果哈希表中没有域 field ,那么 HINCRBYFLOAT 会先将域 field 的值设为 0 ,然后再执行加法操作。

如果键 key 不存在,那么 HINCRBYFLOAT 会先创建一个哈希表,再创建域 field ,最后再执行加法操作。

当以下任意一个条件发生时,返回一个错误:

  • 域 field 的值不是字符串类型(因为 redis 中的数字和浮点数都以字符串的形式保存,所以它们都属于字符串类型)
  • 域 field 当前的值或给定的增量 increment 不能解释(parse)为双精度浮点数(double precision floating point number)

返回值:

执行加法操作之后 field 域的值。

实例如下:

# 值和增量都是普通小数

redis> HSET mykey field 10.50
(integer) 1
redis> HINCRBYFLOAT mykey field 0.1
"10.6"


# 值和增量都是指数符号

redis> HSET mykey field 5.0e3
(integer) 0
redis> HINCRBYFLOAT mykey field 2.0e2
"5200"


# 对不存在的键执行 HINCRBYFLOAT

redis> EXISTS price
(integer) 0
redis> HINCRBYFLOAT price milk 3.5
"3.5"
redis> HGETALL price
1) "milk"
2) "3.5"


# 对不存在的域进行 HINCRBYFLOAT

redis> HGETALL price
1) "milk"
2) "3.5"
redis> HINCRBYFLOAT price coffee 4.5   # 新增 coffee 域
"4.5"
redis> HGETALL price
1) "milk"
2) "3.5"
3) "coffee"
4) "4.5"

(9)HKEYS key

返回哈希表 key 中的所有域。

返回值:

一个包含哈希表中所有域的表。
当 key 不存在时,返回一个空表。

实例如下:

127.0.0.1:6379> HKEYS website
1) "google"
2) "baidu"
3) "taobao"

# 空哈希表/key不存在
127.0.0.1:6379> EXISTS fake_key
(integer) 0
127.0.0.1:6379> HKEYS fake_key
(empty list or set)

(10)HLEN key

返回哈希表 key 中域的数量。

实例如下:

127.0.0.1:6379> hlen website
(integer) 3

(11)HSETNX key field value

将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。

若域 field 已经存在,该操作无效。

如果 key 不存在,一个新哈希表被创建并执行 HSETNX 命令。

返回值:

设置成功,返回 1 。
如果给定域已经存在且没有操作被执行,返回 0 。

实例如下:

redis> HSETNX nosql key-value-store redis
(integer) 1

 # 操作无效,域 key-value-store 已存在
redis> HSETNX nosql key-value-store redis 
(integer) 0

(12)HVALS key

返回哈希表 key 中所有域的值。

返回值:

一个包含哈希表中所有值的表。
当 key 不存在时,返回一个空表。

实例如下:

127.0.0.1:6379> HVALS website
1) "www.g.cn"
2) "www.baidu.com"
3) "www.taobao.com"

(13)HDEL key field [field …]

删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。

在Redis2.4以下的版本里, HDEL 每次只能删除单个域,如果你需要在一个原子时间内删除多个域,请将命令包含在 MULTI / EXEC 块内。

返回值:
被成功移除的域的数量,不包括被忽略的域。

实例如下:

# 测试数据

redis> HGETALL abbr
1) "a"
2) "apple"
3) "b"
4) "banana"
5) "c"
6) "cat"
7) "d"
8) "dog"


# 删除单个域

redis> HDEL abbr a
(integer) 1


# 删除不存在的域

redis> HDEL abbr not-exists-field
(integer) 0


# 删除多个域

redis> HDEL abbr b c
(integer) 2

redis> HGETALL abbr
1) "d"
2) "dog"

【4】List

Redis list 是简单的字符串列表 ,安装插入顺序排序。底层实际是个链表,你可以在列表的头部(左边)或者尾部(右边)添加一个元素。

它是一个字符串链表,left、right都可以插入添加。如果键不存在,创建新的链表;如果键已存在,新增内容;如果值全移除,对应的键也就消失了。

链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了。

(1)LPUSH key value [value …]

将一个或多个值 value 插入到列表 key 的表头.

如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头: 比如说,对空列表 mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a ,这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。

如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。

当 key 存在但不是列表类型时,返回一个错误。

返回值:
执行 LPUSH 命令后,列表的长度。

实例如下:

127.0.0.1:6379> LPUSH mylist 1 2 3
(integer) 3

(2)LRANGE key start stop

返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。

下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。

你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。


  • 注意LRANGE命令和编程语言区间函数的区别。

假如你有一个包含一百个元素的列表,对该列表执行 LRANGE list 0 10 ,结果是一个包含11个元素的列表,这表明 stop 下标也在 LRANGE 命令的取值范围之内(闭区间),这和某些语言的区间函数可能不一致,比如Ruby的 Range.new 、 Array#slice 和Python的 range() 函数。


  • 超出范围的下标

超出范围的下标值不会引起错误。

如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大,那么 LRANGE 返回一个空列表。

如果 stop 下标比 end 下标还要大,Redis将 stop 的值设置为 end 。

  • 返回值:

一个列表,包含指定区间内的元素。

实例如下:

127.0.0.1:6379> LRANGE mylist 0 -1
1) "3"
2) "2"
3) "1"
127.0.0.1:6379> LRANGE mylist 0 0
1) "3"

(3)LPOP key

移除并返回列表 key 的头元素。当 key 不存在时,返回 nil 。

实例如下:

127.0.0.1:6379> LPOP mylist
"3"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "2"
2) "1"

(4)RPOP key

移除并返回列表 key 的尾元素。当 key 不存在时,返回 nil 。

实例如下:

127.0.0.1:6379> RPOP mylist
"1"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "2"

(5)LINDEX key index

返回列表 key 中,下标为 index 的元素。

下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。

你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

如果 key 不是列表类型,返回一个错误。

返回值:

列表中下标为 index 的元素。
如果 index 参数的值不在列表的区间范围内(out of range),返回 nil 。

实例如下:

127.0.0.1:6379> LRANGE mylist 0 -1
1) "2"
127.0.0.1:6379> RPUSH mylist 1 2 3 4
(integer) 5
127.0.0.1:6379> LRANGE mylist 0 -1
1) "2"
2) "1"
3) "2"
4) "3"
5) "4"
127.0.0.1:6379> LINDEX mylist 0
"2"
127.0.0.1:6379> LINDEX mylist 5
(nil)
127.0.0.1:6379> LINDEX mylist 4
"4"

(6)RPUSH key value [value …]

将一个或多个值 value 插入到列表 key 的表尾(最右边)。

如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾:比如对一个空列表 mylist 执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。

如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。

当 key 存在但不是列表类型时,返回一个错误。

返回值:
执行 RPUSH 操作后,表的长度。

实例如下:

127.0.0.1:6379> LRANGE mylist 0 -1
1) "2"
2) "1"
3) "2"
4) "3"
5) "4"

# 列头插入
127.0.0.1:6379> LPUSH mylist 5
(integer) 6

127.0.0.1:6379> LRANGE mylist 0 -1
1) "5"
2) "2"
3) "1"
4) "2"
5) "3"
6) "4"

# 列尾插入
127.0.0.1:6379> RPUSH mylist 6 7
(integer) 8

127.0.0.1:6379> LRANGE mylist 0 -1
1) "5"
2) "2"
3) "1"
4) "2"
5) "3"
6) "4"
7) "6"
8) "7"

(7)LLEN key

返回列表 key 的长度。

如果 key 不存在,则 key 被解释为一个空列表,返回 0 .

如果 key 不是列表类型,返回一个错误。

# 非空列表
127.0.0.1:6379> LLEN mylist
(integer) 8

# 空列表/key不存在
127.0.0.1:6379> LLEN mylist2
(integer) 0

(8)LINSERT key BEFORE|AFTER pivot value

将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。

当 pivot 不存在于列表 key 时,不执行任何操作,返回 -1。

当 key 不存在时, key 被视为空列表,不执行任何操作。

如果 key 不是列表类型,返回一个错误。

实例如下:

127.0.0.1:6379> LINSERT mylist before 3 8
(integer) 9
127.0.0.1:6379> LRANGE mylist 0 -1
1) "5"
2) "2"
3) "1"
4) "2"
5) "8"
6) "3"
7) "4"
8) "6"
9) "7"

(9)LREM key count value

根据参数 count 的值,移除列表中与参数 value 相等的元素。

count 的值可以是以下几种:

  • count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。
  • count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。
  • count = 0 : 移除表中所有与 value 相等的值。

实例如下:

127.0.0.1:6379> LRANGE mylist 0 -1
1) "5"
2) "2"
3) "1"
4) "2"
5) "8"
6) "3"
7) "4"
8) "6"
9) "7"
127.0.0.1:6379> LREM mylist 2 2
(integer) 2
127.0.0.1:6379> LRANGE mylist 0 -1
1) "5"
2) "1"
3) "8"
4) "3"
5) "4"
6) "6"
7) "7"

(10)LSET key index value

将列表 key 下标为 index 的元素的值设置为 value 。

当 index 参数超出范围,或对一个空列表( key 不存在)进行 LSET 时,返回一个错误。

返回值:
操作成功返回 ok ,否则返回错误信息。

实例如下:

127.0.0.1:6379> LRANGE mylist 0 -1
1) "5"
2) "1"
3) "8"
4) "3"
5) "4"
6) "6"
7) "7"

127.0.0.1:6379> LSET mylist 0 0
OK

127.0.0.1:6379> LRANGE mylist 0 -1
1) "0"
2) "1"
3) "8"
4) "3"
5) "4"
6) "6"
7) "7"

(11)LTRIM key start stop

对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。

举个例子,执行命令 LTRIM list 0 2 ,表示只保留列表 list 的前三个元素,其余元素全部删除。

下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。

你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

当 key 不是列表类型时,返回一个错误。

LTRIM 命令通常和 LPUSH 命令或 RPUSH 命令配合使用,举个例子:

LPUSH log newest_log
LTRIM log 0 99

这个例子模拟了一个日志程序,每次将最新日志 newest_log 放到 log 列表中,并且只保留最新的 100 项。注意当这样使用 LTRIM 命令时,时间复杂度是O(1),因为平均情况下,每次只有一个元素被移除。


  • 注意LTRIM命令和编程语言区间函数的区别

假如你有一个包含一百个元素的列表 list ,对该列表执行 LTRIM list 0 10 ,结果是一个包含11个元素的列表,这表明 stop 下标也在 LTRIM 命令的取值范围之内(闭区间),这和某些语言的区间函数可能不一致,比如Ruby的 Range.new 、 Array#slice 和Python的 range() 函数。

  • 超出范围的下标

超出范围的下标值不会引起错误。

如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大,或者 start > stop , LTRIM 返回一个空列表(因为 LTRIM 已经将整个列表清空)。

如果 stop 下标比 end 下标还要大,Redis将 stop 的值设置为 end 。

# 情况 1: 常见情况, start 和 stop 都在列表的索引范围之内

redis> LRANGE alpha 0 -1       # alpha 是一个包含 5 个字符串的列表
1) "h"
2) "e"
3) "l"
4) "l"
5) "o"

redis> LTRIM alpha 1 -1        # 删除 alpha 列表索引为 0 的元素
OK

redis> LRANGE alpha 0 -1       # "h" 被删除了
1) "e"
2) "l"
3) "l"
4) "o"


# 情况 2: stop 比列表的最大下标还要大


redis> LTRIM alpha 1 10086     # 保留 alpha 列表索引 1 至索引 10086 上的元素
OK

redis> LRANGE alpha 0 -1       # 只有索引 0 上的元素 "e" 被删除了,其他元素还在
1) "l"
2) "l"
3) "o"


# 情况 3: start 和 stop 都比列表的最大下标要大,并且 start < stop

redis> LTRIM alpha 10086 123321
OK

redis> LRANGE alpha 0 -1        # 列表被清空
(empty list or set)


# 情况 4: start 和 stop 都比列表的最大下标要大,并且 start > stop

redis> RPUSH new-alpha "h" "e" "l" "l" "o"     # 重新建立一个新列表
(integer) 5

redis> LRANGE new-alpha 0 -1
1) "h"
2) "e"
3) "l"
4) "l"
5) "o"

redis> LTRIM new-alpha 123321 10086    # 执行 LTRIM
OK

redis> LRANGE new-alpha 0 -1           # 同样被清空
(empty list or set)

(12)RPOPLPUSH source destination

命令 RPOPLPUSH 在一个原子时间内,执行以下两个动作:

  • 将列表 source 中的最后一个元素(尾元素)弹出,并返回给客户端。
  • 将 source 弹出的元素插入到列表 destination ,作为 destination 列表的的头元素。

举个例子,你有两个列表 source 和 destination , source 列表有元素 a, b, c , destination 列表有元素 x, y, z ,执行 RPOPLPUSH source destination 之后, source 列表包含元素 a, b , destination 列表包含元素 c, x, y, z ,并且元素 c 会被返回给客户端。

如果 source 不存在,值 nil 被返回,并且不执行其他动作。

如果 source 和 destination 相同,则列表中的表尾元素被移动到表头,并返回该元素,可以把这种特殊情况视作列表的旋转(rotation)操作。

实例如下:

# source 和 destination 不同

redis> LRANGE alpha 0 -1         # 查看所有元素
1) "a"
2) "b"
3) "c"
4) "d"

redis> RPOPLPUSH alpha reciver   # 执行一次 RPOPLPUSH 看看
"d"

redis> LRANGE alpha 0 -1
1) "a"
2) "b"
3) "c"

redis> LRANGE reciver 0 -1
1) "d"

redis> RPOPLPUSH alpha reciver   # 再执行一次,证实 RPOP 和 LPUSH 的位置正确
"c"

redis> LRANGE alpha 0 -1
1) "a"
2) "b"

redis> LRANGE reciver 0 -1
1) "c"
2) "d"


# source 和 destination 相同

redis> LRANGE number 0 -1
1) "1"
2) "2"
3) "3"
4) "4"

redis> RPOPLPUSH number number
"4"

redis> LRANGE number 0 -1           # 4 被旋转到了表头
1) "4"
2) "1"
3) "2"
4) "3"

redis> RPOPLPUSH number number
"3"

redis> LRANGE number 0 -1           # 这次是 3 被旋转到了表头
1) "3"
2) "4"
3) "1"
4) "2"

【5】Set

Redis 的Set是string类型的无序集合,它是通过HashTable实现的。

(1)SADD key member [member …]

将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。

假如 key 不存在,则创建一个只包含 member 元素作成员的集合。

当 key 不是集合类型时,返回一个错误。

实例如下:

# 添加多个元素
127.0.0.1:6379> SADD myset 1 2
(integer) 2

# 添加重复元素
127.0.0.1:6379> SADD myset 1
(integer) 0

(2)SMEMBERS key

返回集合 key 中的所有成员。

不存在的 key 被视为空集合。

实例如下:

127.0.0.1:6379> SMEMBERS myset
1) "1"
2) "2"

(3)SISMEMBER key member

判断 member 元素是否集合 key 的成员。

返回值:
如果 member 元素是集合的成员,返回 1 。
如果 member 元素不是集合的成员,或 key 不存在,返回 0 。

实例如下:

127.0.0.1:6379> SISMEMBER myset 1
(integer) 1

127.0.0.1:6379> SISMEMBER myset 3
(integer) 0

(4)SCARD key

返回集合 key 的基数(集合中元素的数量)。

返回值:
集合的基数。
当 key 不存在时,返回 0 。

实例如下:

127.0.0.1:6379> SCARD myset
(integer) 2

(5)SREM key member [member …]

移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。

当 key 不是集合类型,返回一个错误。

返回值:
被成功移除的元素的数量,不包括被忽略的元素。

实例如下:

# 移除集合元素中的1
127.0.0.1:6379> SREM myset 1
(integer) 1

#查看剩余集合元素
127.0.0.1:6379> SMEMBERS myset
1) "2"

(6)SRANDMEMBER key [count]

如果命令执行时,只提供了 key 参数,那么返回集合中的一个随机元素。

从 Redis 2.6 版本开始, SRANDMEMBER 命令接受可选的 count 参数:

  • 如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。
  • 如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。

该操作和 SPOP 相似,但 SPOP 将随机元素从集合中移除并返回,而 SRANDMEMBER 则仅仅返回随机元素,而不对集合进行任何改动。

实例如下:

127.0.0.1:6379> SADD myset 1 3
(integer) 2
# 返回两个随机元素
127.0.0.1:6379> SRANDMEMBER myset 2
1) "2"
2) "1"

# 只给定参数key
127.0.0.1:6379> SRANDMEMBER myset
"2"

# count设置为负数,元素可能会重复出现多次
127.0.0.1:6379> SRANDMEMBER myset -3
1) "2"
2) "2"
3) "1"

(7)SPOP key

移除并返回集合中的一个随机元素。

如果只想获取一个随机元素,但不想该元素从集合中被移除的话,可以使用 SRANDMEMBER 命令。

实例如下:

127.0.0.1:6379> SPOP myset
"3"
127.0.0.1:6379> SMEMBERS myset
1) "1"
2) "2"

(8)SMOVE source destination member

将 member 元素从 source 集合移动到 destination 集合。

SMOVE 是原子性操作。

如果 source 集合不存在或不包含指定的 member 元素,则 SMOVE 命令不执行任何操作,仅返回 0 。否则, member 元素从 source 集合中被移除,并添加到 destination 集合中去。

当 destination 集合已经包含 member 元素时, SMOVE 命令只是简单地将 source 集合中的 member 元素删除。

当 source 或 destination 不是集合类型时,返回一个错误。

实例如下:

127.0.0.1:6379> SMEMBERS myset
1) "1"
2) "2"

# 从源集合myset 移动 元素1 到目标集合 myset2
127.0.0.1:6379> SMOVE myset myset2 1
(integer) 1

127.0.0.1:6379> SMEMBERS myset
1) "2"

127.0.0.1:6379> SMEMBERS myset2
1) "1"

(9)SDIFF key [key …]

返回一个集合的全部成员,该集合是所有给定集合之间的差集。

不存在的 key 被视为空集。

实例如下:

# 查看第一个集合元素
127.0.0.1:6379> SMEMBERS myset
1) "2"
# 查看第二个集合元素
127.0.0.1:6379> SMEMBERS myset2
1) "1"
# 第一个集合与第二个集合差集
127.0.0.1:6379> sdiff myset myset2
1) "2"
# 第一个集合添加元素3
127.0.0.1:6379> SADD myset 3 3
(integer) 1
# 第三个集合添加元素4
127.0.0.1:6379> SADD myset3 4
(integer) 1
# 三个集合差集
127.0.0.1:6379> SDIFF myset myset2 myset3
1) "2"
2) "3"

(10)SDIFFSTORE destination key [key …]

这个命令的作用和 SDIFF 类似,但它将结果保存到 destination 集合,而不是简单地返回结果集。

如果 destination 集合已经存在,则将其覆盖。

destination 可以是 key 本身。

返回值:结果集中的元素数量。

实例如下:

127.0.0.1:6379> SDIFFSTORE myset3 myset myset2
(integer) 2

# 将myset3集合完全覆盖(原myset3中元素将全部丢失)
127.0.0.1:6379> SMEMBERS myset3
1) "2"
2) "3"

(11)SINTER key [key …]

返回一个集合的全部成员,该集合是所有给定集合的交集。

不存在的 key 被视为空集。

当给定集合当中有一个空集时,结果也为空集(根据集合运算定律)。

实例如下:

127.0.0.1:6379> SINTER myset myset2
(empty list or set)

127.0.0.1:6379> SINTER myset myset3
1) "2"
2) "3"

(12)SINTERSTORE destination key [key …]

这个命令类似于 SINTER 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。

如果 destination 集合已经存在,则将其覆盖。

destination 可以是 key 本身。

实例如下:

127.0.0.1:6379> SINTERSTORE myset1 myset myset3
(integer) 2

127.0.0.1:6379> SMEMBERS myset1
1) "2"
2) "3"

(13)SUNION key [key …]

返回一个集合的全部成员,该集合是所有给定集合的并集。

不存在的 key 被视为空集。

实例如下:

127.0.0.1:6379> SMEMBERS myset1
1) "2"
2) "3"
127.0.0.1:6379> SMEMBERS myset
1) "2"
2) "3"
127.0.0.1:6379> SUNION myset myset1
1) "2"
2) "3"
127.0.0.1:6379> SUNION myset myset2
1) "1"
2) "2"
3) "3"

(14)SUNIONSTORE destination key [key …]

这个命令类似于 SUNION 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。

如果 destination 已经存在,则将其覆盖。

destination 可以是 key 本身。

实例如下:

127.0.0.1:6379> SUNIONSTORE myset4 myset1 myset2 myset3
(integer) 3

127.0.0.1:6379> SMEMBERS myset4
1) "1"
2) "2"
3) "3"

【6】Zset(sorted set)

Redis 的Zset和Set一样也是string类型元素的集合,且不允许重复的成员。

不同的是Zset的每个元素都会关联一个double类型的分数。

Redis正是通过分数来为集合中的成员进行从小到大的排序。

Zset的成员是唯一的,但是分数是可以重复的。

(1)ZADD key score member [[score member] [score member] …]

将一个或多个 member 元素及其 score 值加入到有序集 key 当中。

如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。

score 值可以是整数值或双精度浮点数。

如果 key 不存在,则创建一个空的有序集并执行 ZADD 操作。

当 key 存在但不是有序集类型时,返回一个错误。

实例如下:

127.0.0.1:6379> ZADD myzset 1.0 1 2.0 2
(integer) 2

(2)ZRANGE key start stop [WITHSCORES]

返回有序集 key 中,指定区间内的成员。

其中成员的位置按 score 值递增(从小到大)来排序。

具有相同 score 值的成员按字典序(lexicographical order )来排列。

如果你需要成员按 score 值递减(从大到小)来排列,请使用 ZREVRANGE 命令。

下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。

你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。

超出范围的下标并不会引起错误。

比如说,当 start 的值比有序集的最大下标还要大,或是 start > stop 时, ZRANGE 命令只是简单地返回一个空列表。

另一方面,假如 stop 参数的值比有序集的最大下标还要大,那么 Redis 将 stop 当作最大下标来处理。

可以通过使用 WITHSCORES 选项,来让成员和它的 score 值一并返回,返回列表以 value1,score1, …, valueN,scoreN 的格式表示。

客户端库可能会返回一些更复杂的数据类型,比如数组、元组等。

实例如下:

127.0.0.1:6379> ZRANGE myzset 0 -1
1) "1"
2) "2"

127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
1) "1"
2) "1"
3) "2"
4) "2"

(3)ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。

有序集成员按 score 值递增(从小到大)次序排列。

具有相同 score 值的成员按字典序(lexicographical order)来排列(该属性是有序集提供的,不需要额外的计算)。

可选的 LIMIT 参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset, count ),注意当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。

可选的 WITHSCORES 参数决定结果集是单单返回有序集的成员,还是将有序集成员及其 score 值一起返回。


  • 区间及无限

min 和 max 可以是 -inf 和 +inf ,这样一来,你就可以在不知道有序集的最低和最高 score 值的情况下,使用 ZRANGEBYSCORE 这类命令。

默认情况下,区间的取值使用闭区间 (小于等于或大于等于),你也可以通过给参数前增加 ( 符号来使用可选的开区间 (小于或大于)。

举个例子:

ZRANGEBYSCORE zset (1 5

返回所有符合条件 1 < score <= 5 的成员,而

ZRANGEBYSCORE zset (5 (10

则返回所有符合条件 5 < score < 10 的成员。

实例如下:

redis> ZADD salary 2500 jack                        # 测试数据
(integer) 0
redis> ZADD salary 5000 tom
(integer) 0
redis> ZADD salary 12000 peter
(integer) 0

redis> ZRANGEBYSCORE salary -inf +inf               # 显示整个有序集
1) "jack"
2) "tom"
3) "peter"

redis> ZRANGEBYSCORE salary -inf +inf WITHSCORES    # 显示整个有序集及成员的 score 值
1) "jack"
2) "2500"
3) "tom"
4) "5000"
5) "peter"
6) "12000"

redis> ZRANGEBYSCORE salary -inf 5000 WITHSCORES    # 显示工资 <=5000 的所有成员
1) "jack"
2) "2500"
3) "tom"
4) "5000"

redis> ZRANGEBYSCORE salary (5000 400000            # 显示工资大于 5000 小于等于 400000 的成员
1) "peter"

(4)ZREM key member [member …]

移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。

当 key 存在但不是有序集类型时,返回一个错误。

实例如下:

127.0.0.1:6379> ZRANGE myzset 0 -1
1) "1"
2) "2"
127.0.0.1:6379> ZREM myzset 1
(integer) 1
127.0.0.1:6379> ZRANGE myzset 0 -1
1) "2"

(5)ZCARD key

返回有序集 key 的基数。

实例如下:

127.0.0.1:6379> ZCARD myzset
(integer) 1
127.0.0.1:6379> ZADD myzset 3.0 3 4.0 4
(integer) 2
127.0.0.1:6379> ZCARD myzset
(integer) 3

(6)ZCOUNT key min max

返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。

实例如下:

127.0.0.1:6379> ZCOUNT myzset 1 3
(integer) 2

127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
1) "2"
2) "2"
3) "3"
4) "3"
5) "4"
6) "4"

(7)ZRANK key member

返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。

排名以 0 为底,也就是说, score 值最小的成员排名为 0 。

实例如下:

127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
1) "2"
2) "2"
3) "3"
4) "3"
5) "4"
6) "4"
127.0.0.1:6379> ZRANK myzset 1
(nil)
127.0.0.1:6379> ZRANK myzset 2
(integer) 0
127.0.0.1:6379> ZRANK myzset 3
(integer) 1

(8)ZSCORE key member

返回有序集 key 中,成员 member 的 score 值。

如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil 。

实例如下:

127.0.0.1:6379> ZSCORE myzset 3
"3"

(9)ZREVRANK key member

返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。

排名以 0 为底,也就是说, score 值最大的成员排名为 0 。

实例如下:

127.0.0.1:6379> ZRANK myzset 2
(integer) 0
127.0.0.1:6379> ZREVRANK myzset 2
(integer) 2

(10)ZREVRANGE key start stop [WITHSCORES]

返回有序集 key 中,指定区间内的成员。

其中成员的位置按 score 值递减(从大到小)来排列。

具有相同 score 值的成员按字典序的逆序(reverse lexicographical order)排列。

除了成员按 score 值递减的次序排列这一点外, ZREVRANGE 命令的其他方面和 ZRANGE 命令一样。

实例如下:

127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
1) "2"
2) "2"
3) "3"
4) "3"
5) "4"
6) "4"
127.0.0.1:6379> ZREVRANGE myzset 0 -1 withscores
1) "4"
2) "4"
3) "3"
4) "3"
5) "2"
6) "2"

(11)ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]

返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。

具有相同 score 值的成员按字典序的逆序(reverse lexicographical order )排列。

除了成员按 score 值递减的次序排列这一点外, ZREVRANGEBYSCORE 命令的其他方面和 ZRANGEBYSCORE 命令一样。

实例如下:

127.0.0.1:6379> ZADD myzset 0.5 1
(integer) 1
127.0.0.1:6379> ZRANGE myzset 0 -1 withscores
1) "1"
2) "0.5"
3) "2"
4) "2"
5) "3"
6) "3"
7) "4"
8) "4"
127.0.0.1:6379> ZRANGE myzset 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
127.0.0.1:6379> ZRANGEBYSCORE myzset 0 5 withscores
1) "1"
2) "0.5"
3) "2"
4) "2"
5) "3"
6) "3"
7) "4"
8) "4"
127.0.0.1:6379> ZREVRANGE myzset 0 -1 withscores
1) "4"
2) "4"
3) "3"
4) "3"
5) "2"
6) "2"
7) "1"
8) "0.5"

127.0.0.1:6379> ZREVRANGEBYSCORE myzset 5 0 withscores
1) "4"
2) "4"
3) "3"
4) "3"
5) "2"
6) "2"
7) "1"
8) "0.5"


Redis 的命令参考与其他 文档可以参考:

http://redisdoc.com/

Redis - 五种数据类型与常用操作详解_第1张图片


【7】使用Java测试数据操作

源码简单示例如下:

public class TestAPI {
	public static void main(String[] args) 
	{
		Jedis jedis = new Jedis("127.0.0.1",6379);
		
		jedis.set("k1","v1");
		jedis.set("k2","v2");
		jedis.set("k3","v3");
		
		
		System.out.println(jedis.get("k3"));
		
		Set sets = jedis.keys("*");
		System.out.println(sets.size());
		
	     //key
	     Set keys = jedis.keys("*");
	     for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
	       String key = (String) iterator.next();
	       System.out.println(key);
	     }
	     System.out.println("jedis.exists====>"+jedis.exists("k2"));
	     System.out.println(jedis.ttl("k1"));
	     //String
	     //jedis.append("k1","myreids");
	     System.out.println(jedis.get("k1"));
	     jedis.set("k4","k4_redis");
	     System.out.println("----------------------------------------");
	     jedis.mset("str1","v1","str2","v2","str3","v3");
	     System.out.println(jedis.mget("str1","str2","str3"));
	     //list
	     System.out.println("----------------------------------------");
	     //jedis.lpush("mylist","v1","v2","v3","v4","v5");
	     List list = jedis.lrange("mylist",0,-1);
	     for (String element : list) {
	       System.out.println(element);
	     }
	     //set
	     jedis.sadd("orders","jd001");
	     jedis.sadd("orders","jd002");
	     jedis.sadd("orders","jd003");
	     Set set1 = jedis.smembers("orders");
	     for (Iterator iterator = set1.iterator(); iterator.hasNext();) {
	       String string = (String) iterator.next();
	       System.out.println(string);
	     }
	     jedis.srem("orders","jd002");
	     System.out.println(jedis.smembers("orders").size());
	     //hash
	     jedis.hset("hash1","userName","lisi");
	     System.out.println(jedis.hget("hash1","userName"));
	     Map map = new HashMap();
	     map.put("telphone","1245786875");
	     map.put("address","jane");
	     map.put("email","[email protected]");
	     jedis.hmset("hash2",map);
	     List result = jedis.hmget("hash2", "telphone","email");
	     for (String element : result) {
	       System.out.println(element);
	     }
	     //zset
	     jedis.zadd("zset01",60d,"v1");
	     jedis.zadd("zset01",70d,"v2");
	     jedis.zadd("zset01",80d,"v3");
	     jedis.zadd("zset01",90d,"v4");
	     
	     Set s1 = jedis.zrange("zset01",0,-1);
	     for (Iterator iterator = s1.iterator(); iterator.hasNext();) {
	       String string = (String) iterator.next();
	       System.out.println(string);
	     }
	}
}

你可能感兴趣的:(Redis/Memcache)