001_Redis 数据类型
·
前言
- 基于内存操作的字典型数据库,查询时间复杂度为o(1)
- 可用作数据库、缓存、流式处理引擎、消息代理等等
数据类型
String
- 最基本的数据类型,它是二进制安全的,可以存文本、序列化后的对象(JSON),甚至是一张图片的二进制数据
- 最大存储512MB
set key value ex 1000 nx # 同时包含以下2个操作(可以用作简单的分布式锁)
# setnx key value # key不存在时才可以添加
# setex key 1000 value # 添加key并指定value并设置过期时间为1秒
incr key # 将key中储存的数字值增1
incrby key 2# 将key中储存的数字值增2
#
decy key # 将key中储存的数字值减1
decyby key 2# 将key中储存的数字值减2
get key value # 查询指定key对于的value
Hash
- 类似于Java 的 HashMap 或 Python 的字典,是一个String类型的field和value的映射表
- 适合存储对象,比把对象序列化成String存起来更省内存,且支持按字段读写

List(按照插入顺序排列的字符串列表)(支持双端操作)(可实现简单的生产者-消费者)
lpush stuNos 310110 310111 310112 310113 # 4【依次从左侧添加数据】
llen stuNos # 4
lrange stuNos 0 3 # [310113, 310112, 310111, 310110]
- 队列操作
# 【从右边开始:移除列表的最后一个元素并返回,如果列表没有元素则返回null】
rpop stuNos # 310110
# 【从右边开始:移除列表的最后一个元素并返回,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止】
brpop stuNos 1000 # 310111
- 栈操作
# 【从左边开始:移除列表的最后一个元素并返回,如果列表没有元素则返回null】
lpop stuNos # 310113
# 【从左边开始:移除列表的最后一个元素并返回,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止】
blpop stuNos 1000 # 310111
Set(无序且唯一的字符串集合)(支持集合间的交集、并集、差集运算)
smembers key # 查询集合列表
- 场景1:商品点赞和取赞
sadd key value # 添加元素(对商品进行点赞)
srem key value # 删除元素(对商品进行取赞)
scard key # 查询集合大小 (获取商品的点赞数量)
- 场景2:获取随机数
srandmember key # 随机获取1个元素并返回
- 场景3:抽奖
spop key # 随机删除1个元素并返回
Zset(Set基础上给每个成员设置了一个Score,根据Score实现自动排序)
zadd key score value # 添加元素
- 场景1:排行榜
zincrby key 1 value # 为集合key中成员value的score自增1
zrevrange key 0 -1 withscores # 按照score倒序排列(按照score倒序排列元素,门店销售量排行榜)
【特殊类型1:】Bitmap(位操作,适合签到统计、活跃用户统计)
通过bit(1b = 8bit)来存储数据,每个value只能为0或1
插入元素的时间复杂度为O(1),无论插入的数据量怎么变化,插入元素的耗时、耗空间都是一样的
查询元素的时间复杂度为O(N),随着数据量的增大,查询的时间越久
【特殊类型2:】Hyperloglogs(基数统计,适合超大规模UV统计,有0.81% 误差,但极省内存)
- 一种概率型数据结构,用于统计一组数据中不重复元素的个数,具有内存占用极小(固定 12KB/键)和计算高效特点
- 应用场景
UV 统计:日活、月活
流量监控:页面的独立 IP 访问数、广告的独立曝光用户数
用户行为分析:商品被不同用户浏览的次数、搜索关键词的去重搜索量
- 添加【0726号】的用户UV
pfadd uv:0726 "u001" "u002" # 1表示添加成功
pfadd uv:0726 "u001" # 0表示添加失败,已存在该元素
pfcount uv:0726 # 2表示基数
- 添加【0727号】的UV
pfadd uv:0727 "u003" "u004" # 1表示添加成功
pfcount uv:0727 # 2表示基数
- 合并【0726号】和【0727号】的用户UV
pfmerge uv:072627 uv:0726 uv:0727 # OK表示合并成功(合并uv:0726和uv:0727到uv:072627)
pfcount uv:072627 # 4表示基数
【特殊类型3:】Geospatial 地理位置(附近的人、附近的店铺、计算两点距离)
- 用于存储和操作地理位置数据,支持存储经纬度坐标,并提供了丰富的查询能力(如附近点查询、距离计算、矩形区域检索等)
- 特点
存储高效:每个地理位置仅需存储经纬度(双精度浮点数,占 16 字节)和关联数据(如地点名称),内存占用低
查询快速:利用 ZSET 的有序性,通过几何计算快速筛选符合条件的位置(如“附近 1 公里内的餐厅”)
功能丰富:支持距离计算、范围查询、地理哈希(Geohash)编码等操作
- 添加地理位置
geoadd cities 116.4074 39.9042 beijing # 北京(经度 116.4074,纬度 39.9042)
geoadd cities 121.4737 31.2304 shanghai # 上海
geoadd cities 113.2644 23.1291 guangzhou # 广州
- 查询地理位置
geopos cities beijing
- 计算地理位置之间的直线距离
geodist cities beijing shanghai km # 返回约 1067.376 km
- 查询附近地点:GEORADIUS 和 GEORADIUSBYMEMBER
- 使用场景
附近的人/商家:如外卖 App 中“附近的餐厅”、社交 App 中“附近的用户”
物流追踪:实时查询配送车辆是否在目标区域(如仓库周边 5 公里内)
地理围栏:监控设备是否进入/离开指定矩形或圆形区域(如车辆越界报警)
位置签到:记录用户签到位置,并统计某区域内的签到人数
- 参数说明
withcoord:返回地点的经纬度
withdist:返回地点到中心的距离
withhash:返回地点的 Geohash 编码
asc|desc:按距离升序/降序排序
count ${count}:限制返回的结果数量
- 以北京为中心,查询 10000 公里内的城市
georadiusbymember cities beijing 10000 km asc withhash withcoord withdist
- 以固定经纬度为中心,查询 50 公里内的城市
georadius cities 121.4737 31.2304 50 km asc withcoord withdist
- 删除指定坐标
zrem cities beijing
【特殊类型4:】Streams(消息流)
- Streams是Redis5.0引入的一种数据类型,借鉴了Kafka的设计理念,它是一个仅限追加(Append-only)的日志数据结构
- 相比于Redis早期的消息队列(如List的BLPOP 或 Pub/Sub),Streams 具备以下特性:
持久化与消息ID:
每条消息都有一个唯一的、单调递增的ID(时间戳-序列号),即使Redis重启消息也不会丢失(取决于AOF/RDB配置)
消费者组(Consumer Groups):允许一组中所有的消费者共同消费一个消息流,Redis会自动处理消息的分配,实现消费者的负载均衡
消息确认机制(ACK):
消费者处理完消息后需要发送XACK。如果某个消费者宕机了没被ACK的消息会留在PEL(Pending Entries List)中,PEL中的消息可以被重新分配,保证消息至少被消费一次
阻塞与扇出:
支持阻塞读取(XREAD BLOCK),同时也支持多个消费者组同时订阅同一个Stream(类似广播)
消息回溯:
消息是持久化存储的,你可以通过ID范围查询(XRANGE)来读取历史消息,而不是读完就消失
List: 消息读了就丢,消费者宕机,消息直接人间蒸发
Pub/Sub: 消费者不在线,消息直接发空炮
Streams: 消息永远在日志里,读了没确认就进PEL,支持超时重认领,真正做到了数据不丢失
XREAD 和 XREADGROUP
- XREAD(简单读取,非组模式)
工作模式:扇出(Fan-out)。如果有多个客户端执行同一个XREAD,他们都会收到相同的消息副本
位点管理:客户端需要自己记录上一次读到的ID,下次请求时带上这个ID
- XREADGROUP(消费者组读取)
工作模式:同一消费者组内的多个消费者共同分担Stream内的消息,且一条消息只会被组内的一个消费者抓取。
如果有多个消费者组,则每个组都会消费Stream内的消息
消息确认(ACK):消息读走后会进入该消费者的PEL(Pending Entries List)。只有发送XACK之后,Redis才认为这条消息处理完了
位点管理: Redis自动维护。组内有一个last_delivered_id,记录了小组目前整体分发到了哪里
- Stream中的消息被消费且ACK后,会从组的pending列表移除(消费状态为完成),但依然存在于Stream中(这是设计特性)
可以被XRANGE/range()看到(用于审计、调试)
但不会被readGroup()再次读(消费组保证只处理一次)
如需真正删除Stream中已处理的消息,则需手动调用stream.remove(),或使用stream.trim()限制Stream长度,或在生产时配置自动清理策略
XPENDING 和 XCLAIM
- 当消费者宕机后,如何使用 XPENDING 和 XCLAIM 来"抢救"那些没被处理的消息:
第一步:发现遗失的消息 (XPENDING)
# 查看mystream流中mygroup组下闲置超过5000毫秒的前10条待处理消息
XPENDING mystream mygroup IDLE 5000 - + 10
第二步:抢救/重分配消息 (XCLAIM);Redis6.2开始可以使用XAUTOCLAIM自动扫描并转移那些过期的待处理消息
# 强行myconsumer消费者从mygroup组中认领ID为1526569208039-0的消息
# 前提是该消息已经闲置(Idle)超过10000毫秒
XCLAIM mystream mygroup myconsumer 10000 1526569208039-0
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)