五大数据类型
Redis-Key
127.0.0.1:6379[1]> flushall # 清空所有数据库中的所有键
OK
127.0.0.1:6379[1]> flushdb # 清空当前数据库中的所有键
OK
127.0.0.1:6379[1]> keys * # 查看所有的key
(empty array)
127.0.0.1:6379[1]> set name czar # set key
OK
127.0.0.1:6379[1]> set age 1
OK
127.0.0.1:6379[1]> keys *
1) "name"
2) "age"
127.0.0.1:6379[1]> type age # 查看当前key的数据类型
string
127.0.0.1:6379[1]> exists name # 判断当前的key是否存在
(integer) 1
127.0.0.1:6379[1]> move name 0 # 将当前的key移到指定数据库
(integer) 1
127.0.0.1:6379[1]> keys *
1) "age"
127.0.0.1:6379[1]> select 0 # 切换数据库
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> get name # 获取value
"czar"
127.0.0.1:6379> expire name 10 # 设置key的过期时间,单位秒
(integer) 1
127.0.0.1:6379> ttl name # 查看当前key的剩余时间
(integer) 7
127.0.0.1:6379> ttl name # 为-2时就是过期了
(integer) -2
127.0.0.1:6379> keys *
(empty array)
String
特点
- 值可以是字符串,数字(整数或浮点数)甚至是序列化的对象(如JSON,XML)
- 最大能存储512MB的数据
- 二进制安全
- 常用于存储计数器(配合INCR/DECR原子操作)
内部实现:简单动态字符串(Simple Dynamic String, SDS),相比C语言原生字符串更安全,高效
常用命令
设置/获取:
SET key value
:设置键的值。SETEX key second value
:设置键的值和过期时间SETNX key value
: 仅当键不存在时设置GET key
:获取键的值。GETSET key value
:设置新值并返回旧值。MSET key value [key value ...]
:批量设置键值对。MGET key [key ...]
:批量获取键的值。
计数与增减(原子操作):
INCR key
:将键的整数值加1。DECR key
:将键的整数值减1。INCRBY key increment
:将键的整数值增加指定的increment
。DECRBY key decrement
:将键的整数值减少指定的decrement
。INCRBYFLOAT key increment
:将键的浮点数值增加指定的increment
。
字符串操作:
APPEND key value
:将value
追加到键的原值的末尾。STRLEN key
:返回键值的长度。GETRANGE key start end
:获取键值的子字符串(索引从0开始,包含start和end. (0, -1)为整个字符串的长度)。SETRANGE key offset value
:用value
覆盖键值从offset
开始的部分。
典型应用场景
-
缓存:缓存用户信息、配置信息、查询结果、HTML片段等。
-
计数器:网站访问量、文章阅读数、点赞数、API调用次数。
-
分布式锁:利用
SET key value NX EX seconds
实现。 -
Session共享:在分布式Web应用中存储Session信息。
-
存储简单配置信息。
List
特点
- 元素可以重复
- 可以在列表的头部(左边)或尾部(右边)添加元素
- 获取指定范围的元素列表
- 列表最大长度为2^32^−1个元素
- 常用于实现消息队列或栈
内部实现:早期版本是双向链表或压缩链表(ziplist),Redis3.2后引入quicklist(结合了ziplist和双向链表的优点)
常用命令
添加元素:
LPUSH key element [element ...]
:将一个或多个元素插入到列表头部。RPUSH key element [element ...]
:将一个或多个元素插入到列表尾部。LINSERT key BEFORE|AFTER pivot element
:在pivot
元素前或后插入element
。
移除元素:
LPOP key [count]
:移除并返回列表头部的count
个元素(默认为1)。RPOP key [count]
:移除并返回列表尾部的count
个元素(默认为1)。LREM key count element
:根据count
值移除列表中与element
相等的元素。count > 0
:从头向尾移除count
个元素。count < 0
:从尾向头移除-count
个元素。count = 0
:移除所有。
获取元素/信息:
LLEN key
:返回列表长度。LRANGE key start stop
:获取列表指定范围内的元素(索引从0开始,-1表示最后一个.(0, -1)为全部元素)。LINDEX key index
:通过索引获取列表中的元素。
修改元素:
LSET key index element
:通过索引设置列表元素的值。
裁剪列表:
LTRIM key start stop
:只保留指定区间内的元素,其余删除。
阻塞操作 (常用于消息队列):
BLPOP key [key ...] timeout
:阻塞式地从列表头部弹出元素,timeout
为0表示无限阻塞。BRPOP key [key ...] timeout
:阻塞式地从列表尾部弹出元素。BRPOPLPUSH source destination timeout
:原子地从source
尾部弹出一个元素,插入到destination
头部,并返回该元素(阻塞版本)。
典型应用场景
-
消息队列/任务队列:利用
LPUSH
生产消息,RPOP
(或LPOP
)消费消息。BLPOP
/BRPOP
实现可靠消息消费。 -
时间线/最新动态 (Timeline):如微博、朋友圈的关注人动态,将最新动态
LPUSH
进去,用LRANGE
获取最新的N条。 -
栈 (LIFO):
LPUSH
+LPOP
。 -
文章/商品分页列表:结合
LRANGE
实现。
Set
特点
- 成员是唯一的
- 无序的
- 支持集合间的交集,并集,差集等运算
- 集合最大成员数为2^32^ - 1
内部实现:当元素都是整数且数量不多时使用intset
,否则使用hashtable
(value为null).
常用命令
添加/移除成员:
SADD key member [member ...]
:向集合添加一个或多个成员。SREM key member [member ...]
:移除集合中一个或多个成员。
获取信息/成员:
SMEMBERS key
:返回集合中的所有成员。SISMEMBER key member
:判断member
是否是集合的成员。SCARD key
:获取集合的成员数(基数)。SRANDMEMBER key [count]
:随机返回集合中count
个成员(不删除)。SPOP key [count]
:随机移除并返回集合中count
个成员。
集合运算:
SINTER key [key ...]
:返回所有给定集合的交集。SINTERSTORE destination key [key ...]
:将交集存储到destination
。SUNION key [key ...]
:返回所有给定集合的并集。SUNIONSTORE destination key [key ...]
:将并集存储到destination
。SDIFF key [key ...]
:返回第一个集合与其他集合的差集。SDIFFSTORE destination key [key ...]
:将差集存储到destination
。
扫描:
SSCAN key cursor [MATCH pattern] [COUNT count]
:迭代集合中的元素。
典型应用场景
-
标签系统:给用户或文章打标签,一个标签是一个集合,存储用户ID或文章ID。
-
共同好友/共同兴趣:利用
SINTER
。 -
抽奖系统:将参与用户ID存入Set,用
SPOP
或SRANDMEMBER
抽取。 -
唯一访客统计 (UV):利用Set成员唯一性。
-
黑名单/白名单。
-
数据去重。
Hash
特点
- 特别适合用于存储对象
- 字段(field)是唯一的
- 一个哈希可以包含多达2^32^-1个键值对
内部实现:当字段较少且值较短时使用ziplist
,否则使用hashtable
常用命令
设置/获取字段:
HSET key field value [field value ...]
:设置哈希中一个或多个字段的值。HGET key field
:获取哈希中指定字段的值。HMSET key field value [field value ...]
:(已废弃,推荐用HSET
替代) 批量设置字段值。HMGET key field [field ...]
:批量获取字段的值。HGETALL key
:获取哈希中所有字段和值。
删除字段:
HDEL key field [field ...]
:删除哈希中一个或多个字段。
获取信息:
HLEN key
:获取哈希中字段的数量。HEXISTS key field
:判断哈希中指定字段是否存在。HKEYS key
:获取哈希中所有字段名。HVALS key
:获取哈希中所有值。HSTRLEN key field
:返回哈希表中指定字段所存储值的字符串长度。
数值增减:
HINCRBY key field increment
:为哈希中指定字段的整数值增加increment
。HINCRBYFLOAT key field increment
:为哈希中指定字段的浮点数值增加increment
。
扫描:
HSCAN key cursor [MATCH pattern] [COUNT count]
:迭代哈希表中的键值对。
应用场景
-
存储对象信息:如用户信息(ID、用户名、密码、邮箱等)、商品信息。
-
购物车:以用户ID为key,商品ID为field,商品数量为value。
-
缓存结构化数据:比将整个对象序列化成JSON字符串存入String类型更灵活,可以单独修改某个属性。
Zset
特点
-
成员唯一,但分数(score)可以重复。
-
有序(根据score排序,score相同则按字典序)。
-
支持按分数范围或成员排名范围获取元素。
内部实现:当元素较少且成员较短时使用ziplist
,否则使用skiplist
(跳跃表)和dict
(哈希表)结合的方式。skiplist
保证有序和范围查找,dict
保证O(1)查找成员分数。
常用命令
添加/更新成员:
-
ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
:添加或更新成员及其分数。
NX
:只添加新成员。XX
:只更新已存在成员。CH
:返回实际修改的成员数量。INCR
:对成员的分数进行自增。
移除成员:
ZREM key member [member ...]
:移除一个或多个成员。ZREMRANGEBYRANK key start stop
:按排名范围移除成员。ZREMRANGEBYSCORE key min max
:按分数范围移除成员。
获取信息/成员:
ZCARD key
:获取成员数量。ZSCORE key member
:获取指定成员的分数。ZCOUNT key min max
:获取指定分数区间的成员数量(min
和max
前可加(
表示开区间)。ZRANK key member
:获取指定成员的排名(升序,从0开始)。ZREVRANK key member
:获取指定成员的排名(降序,从0开始)。
按排名范围获取:
ZRANGE key start stop [WITHSCORES]
:按排名升序获取成员(可带分数)。ZREVRANGE key start stop [WITHSCORES]
:按排名降序获取成员(可带分数)。
按分数范围获取:
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
:按分数升序获取成员。ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]
:按分数降序获取成员。
数值增减:
ZINCRBY key increment member
:为指定成员的分数增加increment
。
集合运算 (高级):
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS w [w ...]] [AGGREGATE SUM|MIN|MAX]
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS w [w ...]] [AGGREGATE SUM|MIN|MAX]
扫描:
ZSCAN key cursor [MATCH pattern] [COUNT count]
:迭代有序集合中的元素。
应用场景
-
排行榜:游戏积分榜、文章热度榜、商品销量榜等。
-
带权重的任务队列/延时队列:score可以表示优先级或执行时间。
-
范围查找:如查找积分在某个区间的用户。
-
Top N问题:获取排名最高或最低的N个元素。
-
用户点赞/投票排序:根据点赞数或投票数排序。
三种特殊数据类型
Geo
定义与特点
本质: 专门用于存储地理位置信息(经度、纬度)并支持对这些位置进行查询的数据结构。
特点:
- 可以将成员(通常是某个地点的名称或ID)和其对应的经纬度坐标关联起来。
- 支持查找指定坐标点附近(按半径)的成员。
- 支持计算两个成员之间的距离。
- 底层通常使用Sorted Set实现,结合Geohash算法。Geohash将二维的经纬度编码成一维的字符串(或数字),这个编码后的值作为Sorted Set的score。
注意: Redis GEO功能在 Redis 3.2 版本引入。
常用命令
GEOADD key longitude latitude member [longitude latitude member ...]
:将一个或多个指定成员的地理空间位置(经度和纬度)添加到指定的键中。
- 例如:
GEOADD cities 116.407395 39.904211 Beijing 121.473701 31.230416 Shanghai
GEOPOS key member [member ...]
:从键里面返回所有指定名称的成员的位置(经度和纬度)。
- 例如:
GEOPOS cities Beijing
GEODIST key member1 member2 [unit]
:返回两个给定位置之间的距离。unit
可以是 m
(米,默认), km
(千米), mi
(英里), ft
(英尺)。
- 例如:
GEODIST cities Beijing Shanghai km
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count [ANY]] [ASC|DESC] [STORE key] [STOREDIST key]
:以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
WITHCOORD
:在返回位置元素的同时, 将位置元素的经纬度也一并返回。WITHDIST
:在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。WITHHASH
:在返回位置元素的同时, 将位置元素的Geohash值也一并返回。COUNT count [ANY]
:限制返回结果的数量。ANY
表示找到足够数量后立即返回,不保证是最近的。ASC|DESC
:按距离中心点从近到远或从远到近排序。STORE key
/STOREDIST key
:将结果(或结果的距离)存储到新的键中。- 例如:
GEORADIUS cities 116.40 39.90 200 km WITHDIST COUNT 5 ASC
(查找北京附近200公里内最近的5个城市并显示距离)
GEORADIUSBYMEMBER key member radius m|km|ft|mi ...
:和 GEORADIUS
类似,但中心点不是给定的经纬度,而是键中已存在的某个成员的位置。
- 例如:
GEORADIUSBYMEMBER cities Beijing 200 km WITHDIST
GEOHASH key member [member ...]
:返回一个或多个位置元素的Geohash表示。
GEOSEARCH key [FROMMEMBER member | FROMLONLAT longitude latitude] [BYRADIUS radius unit | BYBOX width height unit] [ASC|DESC] [COUNT count [ANY]] [WITHCOORD] [WITHDIST] [WITHHASH]
(Redis 6.2+): 更强大和灵活的搜索命令,可以按成员、经纬度搜索,按半径或矩形区域搜索。
GEOSEARCHSTORE destination source ...
(Redis 6.2+): 将 GEOSEARCH
的结果存储起来。
应用场景
-
“附近的人/地点”功能: 如查找附近的餐馆、酒店、共享单车、朋友等。
-
LBS(Location Based Service)应用: 基于位置的服务,如滴滴打车派单,美团外卖商家筛选。
-
计算两点间距离。
-
地理围栏: 判断某个点是否在指定区域内。
HyperLogLog
定义与特点
本质: 一种概率数据结构,用于对一个集合中的唯一元素数量(基数)进行估算。
特点:
- 极省空间: 估算非常大的数据集的基数时,只需要固定且很小的内存(Redis中每个HLL键只需要12KB)。
- 估算值: 结果不是精确的,但有可控的误差率(标准误差约为0.81%)。
- 不可逆: 不能获取到具体的元素是哪些,只能得到不重复元素的近似数量。
- 合并方便: 多个HLL可以合并,合并后的HLL的基数估算值是原来各个集合并集后的基数估算值。
常用命令
PFADD key element [element ...]
:向指定的HyperLogLog键添加一个或多个元素。如果元素已存在,则不会重复计数(HLL内部处理)。
- 例如:
PFADD daily_unique_visitors:20250507 user1_ip user2_ip user3_ip user1_ip
PFCOUNT key [key ...]
:返回一个或多个HyperLogLog键的基数估算值。如果指定多个键,返回的是它们并集的基数估算。
- 例如:
PFCOUNT daily_unique_visitors:20250507
(估算当天的独立访客数) - 例如:
PFCOUNT daily_unique_visitors:20250507 daily_unique_visitors:20250506
(估算这两天总的独立访客数,注意这里是并集)
PFMERGE destkey sourcekey [sourcekey ...]
:将一个或多个源HyperLogLog键合并到目标键 destkey
中。合并后的 destkey
的基数估算值将是所有源键对应集合的并集的基数估算。
- 例如:
PFMERGE weekly_unique_visitors:2025w18 daily_unique_visitors:20250505 daily_unique_visitors:20250506 ... daily_unique_visitors:20250511
应用场景
-
网站/App独立访客数(UV)统计: 统计每天、每周、每月的独立访客数量。
-
统计用户搜索的独立查询词数量。
-
统计社交网络中帖子的独立阅读用户数。
-
大数据场景下需要快速估算唯一项数量的场景,且对内存占用有严格要求。
Bitmaps
定义与特点
本质: 位图本身并不是一个独立的数据类型,而是基于String类型的一系列面向位的操作。你可以把一个String类型的值看作是一个由很多个0或1组成的位序列(bit sequence)。
特点:
- 空间效率高: 用一个bit位来表示某个元素某个状态(是/否,存在/不存在),非常节省空间。例如,记录1亿用户的每日登录状态,如果用传统的键值对(如
user:1001:20250507_logged_in true
)会非常多,而用位图,每天只需要大约 1亿 bits / 8 / 1024 / 1024 ≈ 12MB 的空间。 - 操作高效: 位操作通常非常快。
- 动态扩展: 如果你设置了一个偏移量(offset)很大的位,Redis会自动扩展字符串的长度。
常用命令
SETBIT key offset value
:设置键key
在offset
(偏移量,从0开始) 处的位的值(value 只能是 0 或 1)。如果 offset 超出现有字符串长度,会自动用0填充中间的位。- 例如:
SETBIT user:login:status:20250507 1001 1
(表示用户ID为1001在20250507这天登录了)
- 例如:
GETBIT key offset
:获取键 key 在 offset 处的位的值。- 例如:
GETBIT user:login:status:20250507 1001
- 例如:
BITCOUNT key [start end]
:统计字符串中被设置为1的位的数量。start 和 end 参数是字节的偏移量(不是位的偏移量),可以用来统计一个范围内的位数。- 例如:
BITCOUNT user:login:status:20250507
(统计当天登录用户数)
- 例如:
BITPOS key bit [start end]
:返回字符串中第一个被设置为 bit (0或1) 的位的位置。start 和 end 同样是字节偏移量。- 例如:
BITPOS user:login:status:20250507 1
(找到第一个登录的用户ID)
- 例如:
BITOP operation destkey key [key ...]
:对一个或多个位图(源键)进行位运算(AND, OR, XOR, NOT),并将结果保存到目标键 destkey。- 例如:
BITOP AND active_last_3days user:login:status:20250507 user:login:status:20250506 user:login:status:20250505
(计算连续三天都登录的用户)
- 例如:
应用场景
-
用户签到/活跃状态统计: 用每个用户ID作为offset,记录用户每天/每月是否签到或活跃。
-
在线状态跟踪: 记录大量用户是否在线(1表示在线,0表示离线)。
-
布隆过滤器(Bloom Filter)的底层实现之一: 虽然Redis有专门的Bloom Filter模块,但理解Bitmap有助于理解其原理。
-
特征标记/权限控制: 用位表示用户是否拥有某个权限或具备某个特征。
-
人口统计学数据: 例如,统计符合特定组合条件的用户(如:男性 AND 居住在北京 AND 订阅了邮件)。
评论区
请登录后发表评论