Redis数据类型全解析:从基础到高级应用

Redis作为高性能的键值存储系统,提供了丰富的数据类型来满足不同场景的需求。下面我将详细介绍Redis的9种核心数据类型及其典型应用场景。

一、基础数据类型

1. String(字符串)

特点

  • 二进制安全,可存储文本、序列化数据或二进制
  • 最大512MB
  • 支持原子增减操作

常用命令

SET key value [EX seconds]  # 设置值,可带过期时间
GET key                    # 获取值
INCR key                   # 原子+1
DECRBY key decrement       # 原子减指定值
APPEND key value           # 追加内容
GETRANGE key start end     # 获取子串

应用场景

  • 缓存HTML片段
  • 计数器(文章阅读量)
  • 分布式锁
  • 存储序列化对象

示例

> SET article:1001:views 0
> INCR article:1001:views  # 阅读量+1
> GET article:1001:views
"1"

2. Hash(哈希表)

特点

  • 字段值对集合
  • 适合存储对象
  • 每个hash可存储2³²-1个字段

常用命令

HSET key field value       # 设置字段值
HGET key field             # 获取字段值
HGETALL key                # 获取所有字段值
HINCRBY key field increment # 字段原子增加
HDEL key field             # 删除字段

应用场景

  • 用户属性存储
  • 商品信息缓存
  • 聚合统计数据

示例

> HSET user:1001 name "张三" age 28
> HGET user:1001 name
"张三"
> HINCRBY user:1001 age 1  # 年龄+1

3. List(列表)

特点

  • 双向链表结构
  • 元素可重复
  • 最大长度2³²-1

常用命令

LPUSH key value            # 左侧插入
RPUSH key value            # 右侧插入
LPOP key                   # 左侧弹出
RPOP key                   # 右侧弹出
LRANGE key start stop      # 获取范围元素
BLPOP key timeout          # 阻塞式左侧弹出

应用场景

  • 消息队列
  • 最新消息排行
  • 记录用户操作历史

示例

> LPUSH news:latest "新闻A"
> LPUSH news:latest "新闻B"
> LRANGE news:latest 0 1
1) "新闻B"
2) "新闻A"

4. Set(集合)

特点

  • 无序唯一元素集合
  • 支持交并差运算
  • 最大成员数2³²-1

常用命令

SADD key member            # 添加成员
SMEMBERS key               # 获取所有成员
SISMEMBER key member       # 判断成员是否存在
SINTER key1 key2           # 集合交集
SUNION key1 key2           # 集合并集

应用场景

  • 标签系统
  • 共同好友
  • 唯一IP统计

示例

> SADD article:1001:tags "科技" "数据库"
> SADD article:1002:tags "科技" "AI"
> SINTER article:1001:tags article:1002:tags
1) "科技"

5. Sorted Set(有序集合)

特点

  • 唯一成员关联分数(score)
  • 按分数自动排序
  • 相同分数按字典序

常用命令

ZADD key score member      # 添加成员
ZRANGE key start stop      # 按索引范围获取
ZREVRANGE key start stop   # 逆序获取
ZRANK key member           # 获取成员排名
ZSCORE key member          # 获取成员分数

应用场景

  • 排行榜
  • 带权重的消息队列
  • 范围查询

示例

> ZADD leaderboard 100 "玩家A" 200 "玩家B"
> ZREVRANGE leaderboard 0 1 WITHSCORES
1) "玩家B"
2) "200"
3) "玩家A"
4) "100"

二、高级数据类型

6. Bitmaps(位图)

本质:String类型的位操作扩展

常用命令

SETBIT key offset value    # 设置位
GETBIT key offset          # 获取位
BITCOUNT key [start end]   # 统计置1位数
BITOP operation destkey key [key...] # 位运算

应用场景

  • 用户签到记录
  • 活跃用户统计
  • 布隆过滤器

示例

> SETBIT user:sign:1001 0 1  # 第1天签到
> SETBIT user:sign:1001 1 1  # 第2天签到
> BITCOUNT user:sign:1001
(integer) 2

7. HyperLogLog(基数统计)

特点

  • 用于估计集合基数
  • 误差率约0.81%
  • 固定使用12KB内存

常用命令

PFADD key element [element...] # 添加元素
PFCOUNT key [key...]         # 估算基数
PFMERGE destkey sourcekey [sourcekey...] # 合并多个HLL

应用场景

  • 网站UV统计
  • 大规模去重计数

示例

> PFADD visitors 192.168.1.1 192.168.1.2
> PFCOUNT visitors
(integer) 2

8. Geospatial(地理空间)

本质:基于Sorted Set实现

常用命令

GEOADD key longitude latitude member # 添加位置
GEODIST key member1 member2 [unit] # 计算距离
GEORADIUS key longitude latitude radius unit # 查找范围内成员

应用场景

  • 附近的人
  • 地理位置搜索
  • 配送范围计算

示例

> GEOADD cities 116.40 39.90 "北京" 121.47 31.23 "上海"
> GEODIST cities 北京 上海 km
"1067.9888"

9. Stream(流)

特点

  • Redis 5.0引入
  • 消息队列增强版
  • 支持消费者组

常用命令

XADD key ID field value [field value...] # 添加消息
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key...] ID [ID...] # 读取消息
XGROUP CREATE key groupname ID # 创建消费者组

应用场景

  • 消息队列
  • 事件溯源
  • 日志收集

示例

> XADD mystream * sensor-id 1234 temperature 19.8
"1609459200000-0"
> XREAD COUNT 2 STREAMS mystream 0
1) 1) "mystream"
   2) 1) 1) "1609459200000-0"
         2) 1) "sensor-id"
            2) "1234"
            3) "temperature"
            4) "19.8"

三、数据类型选择指南

数据类型适用场景不适用场景
String简单键值、计数器需要存储结构化数据
Hash对象属性、频繁部分更新需要单独过期字段
List队列、最新列表随机访问中间元素
Set无序唯一集合、关系运算需要排序的场景
Sorted Set排行榜、范围查询内存敏感场景
Bitmap布尔统计、位操作非二进制标记场景
HyperLogLog大数据去重统计需要精确结果的场景
Geo地理位置应用非地理数据
Stream消息队列、事件流简单队列需求

四、内存优化技巧

  1. 小Hash优化

    • 当field数量较少时,Redis使用ziplist编码
    • 配置阈值:hash-max-ziplist-entries 512
  2. Int编码优化

    SET counter 100         # 使用int编码
    OBJECT ENCODING counter
    "int"
    
  3. 共享对象

    • Redis会共享0-9999的整数对象
    • 配置:redis.hz 10 (影响回收频率)
  4. 内存碎片整理

    CONFIG SET activedefrag yes
    

五、数据类型底层实现

5.1 编码方式

数据类型可能编码条件
Stringint/embstr/raw值长度≤39字节用embstr
Hashziplist/hashtablefield数≤512且值≤64字节用ziplist
Listziplist/linkedlist/quicklistRedis 3.2后默认quicklist
Setintset/hashtable元素全为整数且数量≤512用intset
Sorted Setziplist/skiplist元素数≤128且值≤64字节用ziplist

5.2 内存占用对比

存储1百万个简单键值(测试结果):

类型内存占用特点
String~85MB每个键独立存储
Hash~50MB字段紧凑存储
Set~65MB哈希表开销
ZSet~90MB跳表+哈希表

六、实战应用案例

6.1 电商系统设计

# 商品缓存
HMSET product:1001 id 1001 name "iPhone13" price 6999 stock 100

# 购物车
HSET cart:user1001 product:1001 2  # 商品ID:数量

# 秒杀库存
SET inventory:seckill:1001 100
DECR inventory:seckill:1001

# 用户标签
SADD user:tags:1001 "高消费" "数码爱好者"

6.2 社交网络系统

# 关注关系
SADD following:1001 1002 1003  # 用户1001的关注
SADD followers:1002 1001       # 用户1002的粉丝

# 共同关注
SINTER following:1001 following:1002

# 时间线
LPUSH timeline:1001 "post:923"
LPUSH timeline:1001 "post:924"

6.3 实时监控系统

# 设备状态
HSET device:temp:sensor01 last_value 23.5 update_time 1630000000

# 报警阈值
ZADD device:alerts 50 "sensor01" 60 "sensor02"

# 地理位置
GEOADD devices:geo 116.404 39.915 "sensor01"
GEORADIUS devices:geo 116.404 39.915 10 km

七、常见问题解答

Q1:Redis的List和Java的LinkedList有什么区别?

A

  • Redis List是双向链表+ziplist的混合实现
  • 当元素少时使用ziplist压缩存储
  • 支持阻塞操作(BLPOP)
  • 可持久化到磁盘

Q2:Sorted Set如何实现范围查询?

A

  • 内部使用跳表(skiplist)和哈希表组合实现
  • 跳表支持O(logN)复杂度的范围查询
  • 哈希表保证O(1)的单元素访问

Q3:为什么Redis不提供树结构?

A

  • 跳表已能满足排序需求且实现更简单
  • 树结构的平衡操作影响性能
  • 可通过Sorted Set实现大多数树结构功能

Redis丰富的数据类型使其能够灵活应对各种场景,从简单的缓存到复杂的实时系统。理解每种类型的特点和底层实现,可以帮助开发者做出最优的技术选型和设计决策。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北辰alk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值