前言

  • 基于内存操作字典型数据库,查询时间复杂度为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
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐