Redis:数据类型
跳到导航
跳到搜索
关于
Redis 以 key-value 存储数据,“key”为 String,其“数据类型”是指“value 的类型”;
Redis 支持五种数据类型:
数据类型 说明 string 字符串类型 list 列表类型 hash 哈希类型 set 集合类型 zset(sorted set) 有序集合类型
Redis 的 5 种数据类型
String
String 类型是 Redis 中最简单的数据结构。它既可以存储文字(例如"hello world"),又可以存储数字(例如整数 10086 和浮点数 3.14),还可以存储二进制数据(例如 10010100)。
字符串类型:字符串类型是Redis中最基本的数据类型;
- 它能存储任何形式的字符串,包括二进制数据,序列化后的数据,JSON化的对象甚至是一张图片。
命令 | 说明 |
---|---|
append <key> <value> | 如果 key 存在且是字符串, 则将 value 追加到 key 原来旧值的末尾;
|
strlen <key> | 返回 key 所储存的字符串值的长度; |
get <key> | 获取 key 中设置的字符串值; |
set <key> <value> | 将字符串值 value 设置到 key 中; |
mget <key> [<key>] | 获取所有(一个或多个)给定 key 的值 |
mset <key> <value> [<key> <value>] | 同时设置一个或多个 key-value 对 |
setnx <key> <value> | setnx 是“set if not exists”的简写,如果key不存在,则设置值,存在则不设置值; |
msetnx <key> <value> [<key> <value>] | 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在时才能设置成功,否则只要有一个key存在都会失败 |
getbit <key> offset | 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。 |
setbit <key> offset <value> | 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。 |
getrange <key> <start> <end> | 获取 key 中字符串值从 start 开始 到 end 结束 的子字符串; |
setrange <key> <offset> <value> | 从指定的位置开始将 key 的值替换为新的字符串; |
setex <key> <seconds> <value> | “set expire”的简写,设置 key 的值 ,并将 key 的生存时间设为 seconds (以秒为单位) ; |
psetex <key> milliseconds <value> | 这个命令和 setex 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 setex 命令那样,以秒为单位。 |
getset <key> <value> | 设置 key 的值为 value ,并返回 key 的旧值; |
incr <key> | 将 key 中储存的数字值加 1;
|
decr <key> | 将 key 中储存的数字值减 1;
|
incrby <key> <increment> | 将 key 所储存的值加上增量值;
|
decrby <key> <decrement> | 将 key 所储存的值减去减量值;
|
incrbyfloat <key> <increment> | 为 key 中所储存的值加上浮点数增量 increment;
|
bitcount <key> <start> <end> | 计算给定字符串中,被设置为 1 的比特位的数量;
|
bitop <operation> <destkey> <key> [<key> ...] | 对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上;
|
List
Redis 的 List 类型是基于【双向链表】实现的,可以支持正向、反向查找和遍历。从用户角度来说,List列表是简单的字符串列表,字符串按照添加的顺序排序。可以添加一个元素到List列表的头部(左边)或者尾部(右边)。一个List列表最多可以包含232-1个元素(最多可超过 40亿 个元素)。 List列表的典型应用场景: 网络社区中最新的发帖列表、简单的消息队列、最新新闻的分页列表、博客的评论列表、排队系统等等。 举个具体的例子,在“双11”秒杀、抢购这样的大型活动中,短时间内有大量的用户请求发向服务器,而后台的程序不可能立刻响应每一个用户的请求,有什么好的办法来解决这个问题呢? 我们需要一个排队系统。根据用户的请求时间,将用户的请求放入 List 队列中,后台程序依次从队列中获取任务,处理并将结果返回到结果队列。换句话说,通过List队列,可以将并行的请求转换成串行的任务队列,之后依次处理。
列表类型:简单的字符串列表,按照插入顺序排序。
- 可以添加一个元素到列表的头部(左边)或者尾部(右边);
- 一个列表最多可以包含 2^32 - 1 (40多亿)个元素。
- List 列表的下标是从 0 开始的,index 为负的时候是从后向前数(-1 表示最后一个元素)。当下标超出边界时,会返回 nil。
命令 | 说明 |
---|---|
lpush <key> <value> [<value>] | 将一个或多个值 value 插入到列表 key 的表头(最左边) |
rpush <key> <value> [<value>] | 将一个或多个值 value 插入到列表 key 的表尾(最右边) |
lpushx <key> <value> | 将一个值插入到已存在的列表头部,当且仅当 key 存在并且是一个列表
|
rpushx <key> <value> | 为已存在的列表添加值,当且仅当 key 存在并且是一个列表
|
lpop <key> | 从左边获取列表 key 的一个元素,并将该元素移除 |
rpop <key> | 从右边获取列表 key 的一个元素,并将该元素移除 |
blpop <key> [<key>] timeout | 移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
|
brpop <key> [<key>] timeout | 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。
|
rpoplpush <source> <destination> | 将列表 source 中的最后一个元素(尾元素)弹出插入到目标列表(destination),作为目标列表的的头元素 |
brpoplpush <source> <destination> timeout | 从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回它; 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
llen <key> | 获取列表 key 的长度 |
lindex <key> <index> | 获取列表 key 中下标为指定 index 的元素 |
lset <key> <index> <value> | 将列表 key 下标为 index 的元素的值设置为 value |
linsert <key> BEFORE|AFTER <pivot> <value> | 将值 value 插入到列表 key 当中位于值 pivot 之前或之后的位置 |
lrange <key> <start> <stop> | 获取列表 key 中指定区间内的元素
|
lrem <key> <count> <value> | 从左到右删除列表中指定个数(count)的“与指定value值相等的”value |
ltrim <key> <start> <stop> | 删除指定区域外的元素,比如“LTRIM list 0 2” ,表示只保留列表 list 的前三个元素,其余元素全部删除 |
Hash
Redis 中的 Hash 哈希表是一个 String 类型的 Field 字段和 Value 值之间的映射表,类似于 Java 中的 HashMap。 一个哈希表由多个“字段-值”对(Field-Value Pair)组成,Value 值可以是文字、整数、浮点数或者二进制数据。 在同一个 Hash 哈希表中,每个 Field 字段的名称必须是唯一的。这一点和 Java 中 HashMap 的 Key 键的规范要求也是八九不离十的。
哈希类型:是一个 String 类型的 field 和 value 的映射表;
- Hash 特别适合用于存储对象。
- 每个 hash 可以存储 2^32 - 1 (40多亿)个键值对。
命令 | 说明 |
---|---|
hget <key> <field> | 获取哈希表 key 中给定域 field 的值 |
hgetall <key> | 获取哈希表 key 中所有的域和值 |
hset <key> <field> <value> | 将哈希表 key 中的域 field 的值设为 value |
hsetnx <key> <field> <value> | 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在的时候才设置,否则不设置 |
hmset <key> <field> <value> [<field> <value>] | 同时将多个 field-value (域-值)对设置到哈希表 key 中 |
hmget <key> <field> [<field>] | 获取哈希表 key 中一个或多个给定域的值 |
hkeys <key> | 查看哈希表 key 中的所有 field 域 |
hvals <key> | 查看哈希表 key 中所有域的值 |
hexists <key> <field> | 查看哈希表 key 中,给定域 field 是否存在 |
hlen <key> | 获取哈希表 key 中域 field 的个数 |
hdel <key> <field> [<field>] | 删除哈希表 key 中的一个或多个指定域 field |
hincrby <key> <field> <increment> | 为哈希表 key 中的域 field 的值加上增量 increment |
hincrbyfloat <key> <field> <increment> | 为哈希表 key 中的域 field 加上浮点数增量 increment |
hscan <key> cursor [MATCH pattern] [COUNT count] | 迭代哈希表中的键值对【???】
|
Set
Set 集合也是一个列表,不过它的特殊之处在于它是可以自动去掉重复元素的。 Set 集合类型的使用场景是:当需要存储一个列表,而又不希望有重复的元素(例如ID的集合)时,使用 Set 是一个很好的选择。 特点: 1、Set 类型拥有一个命令,它可用于判断某个元素是否存在,而 List 类型并没有这种功能的命令。 2、通过 Set 集合类型的命令可以快速地向集合添加元素,或者从集合里面删除元素,也可以对多个 Set 集合进行集合运算,例如并集、交集、差集。
集合类型:String 类型的无序集合,集合成员(member)是唯一的,即集合中不能出现重复的数据;
- Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
- 集合中最大的成员数为 2^32 - 1 (40多亿)。
命令 | 说明 |
---|---|
sadd <key> <member> [<member>] | 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将不会再加入 |
srem <key> <member> [<member>] | 删除集合 key 中的一个或多个 member 元素 |
spop <key> [count] | 随机从集合中删除一个元素 |
smove <source> <destination> <member> | 将 member 元素从一个集合移动到另一个集合 |
scard <key> | 获取集合里面的元素个数 |
smembers <key> | 获取集合 key 中的所有成员元素 |
sismember <key> <member> | 判断 member 元素是否是集合 key 的成员 |
srandmember <key> [count] | 随机返回集合中的一个元素 |
sdiff <key> [<key>] | 返回第一个集合与其他集合之间的差异。 |
sdiffstore <destination> <key> [<key>] | 返回给定所有集合的差集并存储在 destination 中 |
sinter <key> [<key>] | 返回给定所有集合的交集 |
sinterstore <destination> <key> [<key>] | 返回给定所有集合的交集并存储在 destination 中 |
sunion <key> [key2] | 返回所有给定集合的并集 |
sunionstore <destination> <key> [<key>] | 所有给定集合的并集存储在 destination 集合中 |
sscan <key> cursor [MATCH pattern] [COUNT count] | 迭代集合中的元素
|
Zset(sorted set)
Zset 有序集合和 Set 集合的使用场景类似,区别是有序集合会根据提供的 score 参数来进行自动排序。 当需要一个不重复的且有序的集合列表,那么就可以选择Zset有序集合类型。常用案例:游戏中的排行榜。 Zset 有序集合和 Set 集合不同的是,有序集合的每个元素,都关联着一个分值(Score),这是一个浮点数格式的关联值。Zset 有序集合会按照分值(Score),按从小到大的顺序来排列有序集合中的各个元素。
有序集合类型:(有序的Set)不同的是 Zset 的每个元素(member)都会关联一个分数(score,分数可以重复),Redis 通过分数来为集合中的成员进行从小到大的排序。
- 有序集合的成员是唯一的,但分数(score)却可以重复。
- 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
- 集合中最大的成员数为 2^32 - 1 (40多亿)。
命令 | 说明 |
---|---|
zadd <key> [NX|XX] [CH] [INCR] <score> <member> [<score> <member>] | 将一个或多个 member 元素及其 score 值加入到有序集合 key 中 |
zscore <key> <member> | 返回有序集中,成员的分数值 |
zincrby <key> <increment> <member> | 有序集合中对指定成员的分数加上增量 increment |
zcard <key> | 获取有序集合的成员数 |
zcount <key> <min> <max> | 计算在有序集合中指定分数区间的成员数
|
zlexcount <key> <min> <max> | 计算在有序集合中指定字典区间的成员数 |
zrank <key> <member> | 返回有序集合中指定成员的索引 |
zrevrank <key> <member> | 返回有序集合中指定成员的索引【rev:有序集成员按分数值递减(从大到小)排序】 |
zrange <key> <start> <stop> [WITHSCORES] | 返回有序集中指定索引区间内的成员 |
zrevrange <key> <start> <stop> [WITHSCORES] | 返回有序集中指定索引区间内的成员【rev:有序集成员按分数值递减(从大到小)排序】 |
zrangebylex <key> <min> <max> [LIMIT <offset> <count>] | 返回有序集中指定字典区间内的成员 |
zrangebyscore <key> <min> <max> [WITHSCORES] [LIMIT <offset> <count>] | 返回有序集中指定分数区间内的成员 |
zrevrangebyscore <key> <min> <max> [WITHSCORES] [LIMIT <offset> count>] | 返回有序集中指定分数区间内的成员【rev:有序集成员按分数值递减(从大到小)排序】 |
zrem <key> <member> [<member>] | 移除有序集合 key 中的一个或多个成员 |
zremrangebylex <key> <min> <max> | 移除有序集合中给定的字典区间的所有成员 |
zremrangebyrank <key> <start> <stop> | 移除有序集合中给定的排名区间的所有成员 |
zremrangebyscore <key> <min> <max> | 移除有序集合中给定的分数区间的所有成员 |
zinterstore <destination> <numkeys> <key> [<key>...] [WEIGHTS <weight> [<weight>...]] [AGGREGATE SUM|MIN|MAX] | 计算给定的一个或多个有序集的交集,并存储在新的 key(destination)中
|
zunionstore <destination> <numkeys> <key> [<key>...] [WEIGHTS <weight> [<weight>...]] [AGGREGATE SUM|MIN|MAX] | 计算给定的一个或多个有序集的并集,并存储在新的 key(destination)中
|
zscan <key> cursor [MATCH <pattern>] [COUNT <count>] | 迭代有序集合中的元素(包括元素成员和元素分值)
|
示例:
- “zinterstore”:
redis > ZADD mid_test 70 "Li Lei" (integer) 1 redis > ZADD mid_test 70 "Han Meimei" (integer) 1 redis > ZADD mid_test 99.5 "Tom" (integer) 1 redis > ZADD fin_test 88 "Li Lei" (integer) 1 redis > ZADD fin_test 75 "Han Meimei" (integer) 1 redis > ZADD fin_test 99.5 "Tom" (integer) 1 redis > ZINTERSTORE sum_point 2 mid_test fin_test (integer) 3 redis > ZRANGE sum_point 0 -1 WITHSCORES # 显示有序集内所有成员及其 score 值 1) "Han Meimei" 2) "145" 3) "Li Lei" 4) "158" 5) "Tom" 6) "199"
- “zunionstore”:
redis> ZRANGE programmer 0 -1 WITHSCORES 1) "peter" 2) "2000" 3) "jack" 4) "3500" 5) "tom" 6) "5000" redis> ZRANGE manager 0 -1 WITHSCORES 1) "herry" 2) "2000" 3) "mary" 4) "3500" 5) "bob" 6) "4000" redis> ZUNIONSTORE salary 2 programmer manager WEIGHTS 1 3 # 公司决定加薪。。。除了程序员(programmer 的 WEIGHTS 为 1)。。。 (integer) 6 redis> ZRANGE salary 0 -1 WITHSCORES 1) "peter" 2) "2000" 3) "jack" 4) "3500" 5) "tom" 6) "5000" 7) "herry" 8) "6000" 9) "mary" 10) "10500" 11) "bob" 12) "12000"
FAQ
单个“Key”和“Value”数据大小
512 M、512 M、512 M!并非“1 G”。
- Key 的大小上限为 512 M。
- 建议 key 的大小不超过 1 KB,这样既节约存储空间,也利于 Redis 进行检索。
- String 类型的 value 值上限为 512 M。
- 集合、链表、哈希等 key 类型,单个元素的 value 上限为 512 M。
- 事实上,集合、链表、哈希都可以看成由 String 类型的 key 按照一定的映射关系组合而成。
使用 Hash 的好处
应该尽量使用 Hash 哈希表而不是字符串键来缓存 Key-Value(“键-值对”)数据,优势为:方便管理、能够避免键名冲突、并且还能够节约内存。
- 将数据集中存放。
- 通过 Hash 哈希表,可以将一些相关的信息存储在同一个缓存 Key 键中,不仅方便了数据管理,还可以尽量避免误操作的发生。
- 避免键名冲突。
- 在介绍缓存 Key 的命名规范时,可以在命名键的时候,使用冒号分割符来避免命名冲突,但更好的避免冲突的办法是直接使用哈希键来存储“键-值对”数据。
- 减少 Key 键的内存占用。
- 在一般情况下,保存相同数量的“键-值对”信息,使用哈希键比使用字符串键更节约内存。
- 因为 Redis 创建一个 Key 键都带有很多的附加管理信息(例如:这个 Key 键的类型、最后一次被访问的时间等),所以缓存的 Key 键越多,耗费的内存就越多,花在管理数据库 Key 键上的 CPU 也会越多。
Set、Zset 的实现
Set、Zset 都是通过 Hash 实现的:“field - value”中“value”为空的 Hash。