温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

常见Redis数据结构有哪些

发布时间:2021-12-06 10:06:30 阅读:224 作者:iii 栏目:关系型数据库
开发者测试专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>
# 常见Redis数据结构详解

## 一、Redis数据结构概述

Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它支持多种数据结构,这使得Redis不仅仅是一个简单的键值存储,而是一个功能丰富的数据结构服务器。Redis的数据结构设计是其核心优势之一,每种数据结构都针对特定场景进行了优化,提供了高效的操作性能。

### 1.1 Redis数据结构的重要性

Redis之所以在众多NoSQL数据库中脱颖而出,很大程度上得益于其丰富的数据结构支持:

- **性能卓越**:内存存储+高效数据结构实现,使Redis能达到极高的吞吐量
- **操作原子性**:所有单个命令都是原子操作,无需担心并发问题
- **多功能性**:不同数据结构支持不同业务场景,从缓存到消息队列都能胜任
- **扩展性**:通过组合基本数据结构,可以构建更复杂的数据模型

### 1.2 Redis数据模型特点

Redis的数据模型具有以下显著特点:

1. **键值存储**:所有数据都通过唯一的key访问
2. **类型丰富**:value支持多种数据结构类型
3. **单线程模型**:命令顺序执行,避免锁竞争
4. **持久化支持**:可将内存数据保存到磁盘
5. **过期机制**:支持设置键的生存时间

## 二、String(字符串)

### 2.1 基本概念

String是Redis最基本的数据类型,可以存储任何形式的数据,包括文本、序列化的对象或二进制数据。一个String类型的值最大能存储512MB的内容。

**主要特性**- 二进制安全,可以包含任何数据
- 支持丰富的操作命令
- 常用于缓存、计数器等场景

### 2.2 常用命令

```redis
SET key value [EX seconds] [PX milliseconds] [NX|XX]
GET key
INCR key
DECR key
APPEND key value
STRLEN key
GETRANGE key start end
SETRANGE key offset value
MSET key1 value1 [key2 value2 ...]
MGET key1 [key2 ...]

2.3 应用场景

  1. 缓存系统:存储热点数据

    SET user:1001 "{name:'John', age:25}"
    GET user:1001
    
  2. 计数器:实现原子递增/递减

    INCR article:1001:views
    DECR inventory:product1001
    
  3. 分布式锁:利用SETNX实现

    SETNX lock:order123 true
    EXPIRE lock:order123 30
    
  4. 位操作:实现位图功能

    SETBIT user:1001:login 5 1
    GETBIT user:1001:login 5
    

2.4 内部实现

Redis的String类型在底层通过简单动态字符串(SDS, Simple Dynamic String)实现,相比C字符串有以下优势:

  1. O(1)时间复杂度获取字符串长度
  2. 杜绝缓冲区溢出
  3. 减少修改字符串时带来的内存重分配次数
  4. 二进制安全
  5. 兼容部分C字符串函数

三、List(列表)

3.1 基本概念

Redis的List是一个双向链表结构,可以高效地在两端进行插入和删除操作,最大长度为2^32-1个元素。

主要特性: - 插入和删除操作高效 - 支持范围查询 - 可用于实现多种数据结构

3.2 常用命令

LPUSH key value1 [value2 ...]
RPUSH key value1 [value2 ...]
LPOP key
RPOP key
LRANGE key start stop
LLEN key
LINDEX key index
LINSERT key BEFORE|AFTER pivot value
LREM key count value
LTRIM key start stop

3.3 应用场景

  1. 消息队列:实现简单的生产者消费者模型

    # 生产者
    LPUSH queue task1
    # 消费者
    RPOP queue
    
  2. 最新消息排行:如朋友圈时间线

    LPUSH user:1001:timeline "New post"
    LRANGE user:1001:timeline 0 9
    
  3. 历史记录:存储用户最近浏览

    LPUSH history:user1001 item123
    LTRIM history:user1001 0 49
    
  4. 栈/队列:通过不同命令组合实现

    # 栈 (LPUSH+LPOP)
    # 队列 (LPUSH+RPOP)
    

3.4 内部实现

Redis的List在底层有两种实现方式:

  1. 压缩列表(ziplist):当元素数量较少且元素较小时使用,是一块连续的内存空间

    • 节省内存
    • 适合小列表
    • 插入删除需要重新分配内存
  2. 双向链表(linkedlist):元素较多时使用

    • 内存不连续
    • 插入删除效率高
    • 需要额外存储前后指针

Redis 3.2后引入quicklist,结合了ziplist和linkedlist的优点,是默认实现。

四、Hash(哈希表)

4.1 基本概念

Redis的Hash是一个string类型的field和value的映射表,特别适合存储对象。

主要特性: - 适合存储对象 - 可以单独操作字段 - 高效存储和访问

4.2 常用命令

HSET key field value
HGET key field
HDEL key field1 [field2 ...]
HEXISTS key field
HGETALL key
HKEYS key
HVALS key
HINCRBY key field increment
HLEN key
HMSET key field1 value1 [field2 value2 ...]
HMGET key field1 [field2 ...]

4.3 应用场景

  1. 对象存储:存储用户信息等结构化数据

    HSET user:1001 name "John" age 25 email "john@example.com"
    HGET user:1001 name
    
  2. 商品属性:存储商品的不同属性

    HMSET product:1001 name "Phone" price 599 stock 100
    HINCRBY product:1001 stock -1
    
  3. 配置管理:存储系统配置项

    HSET config:system timeout 30 max_connections 1000
    HGETALL config:system
    
  4. 计数器组合:多个相关计数器

    HINCRBY article:1001 stats views 1
    HINCRBY article:1001 stats likes 1
    

4.4 内部实现

Redis的Hash类型有两种底层实现:

  1. ziplist:当哈希元素较少且元素较小时使用

    • 所有键值对连续存储
    • 节省内存
    • 查询效率相对较低
  2. hashtable:元素较多时使用

    • 使用字典实现
    • 查询效率高
    • 需要额外内存存储指针

Redis会根据以下配置自动切换实现: - hash-max-ziplist-entries (默认512) - hash-max-ziplist-value (默认64字节)

五、Set(集合)

5.1 基本概念

Redis的Set是string类型的无序集合,通过哈希表实现,不允许重复元素。

主要特性: - 元素唯一性 - 支持集合运算 - 高效的成员检查 - 无序存储

5.2 常用命令

SADD key member1 [member2 ...]
SREM key member1 [member2 ...]
SMEMBERS key
SCARD key
SISMEMBER key member
SRANDMEMBER key [count]
SPOP key [count]
SINTER key1 [key2 ...]
SUNION key1 [key2 ...]
SDIFF key1 [key2 ...]

5.3 应用场景

  1. 标签系统:给对象打标签

    SADD article:1001:tags tech redis database
    SADD tag:redis:articles 1001
    
  2. 好友关系:存储共同好友

    SADD user:1001:friends 1002 1003
    SADD user:1002:friends 1001 1003
    SINTER user:1001:friends user:1002:friends
    
  3. 唯一计数器:统计独立IP

    SADD website:visitors 192.168.1.1
    SCARD website:visitors
    
  4. 随机元素:抽奖系统

    SADD lottery:users user1 user2 user3
    SRANDMEMBER lottery:users 1
    

5.4 内部实现

Redis的Set底层有两种实现:

  1. intset:当集合中所有元素都是整数且元素数量较少时使用

    • 有序数组存储
    • 二分查找
    • 节省内存
  2. hashtable:默认实现

    • 字典实现,value为NULL
    • O(1)时间复杂度操作
    • 需要更多内存

转换条件由以下配置控制: - set-max-intset-entries (默认512)

六、Sorted Set(有序集合)

6.1 基本概念

Sorted Set是Redis中最复杂也最强大的数据结构之一,它在Set的基础上为每个元素关联了一个分数(score),使得元素可以按分数排序。

主要特性: - 元素唯一 - 按分数排序 - 支持范围查询 - 高效的元素排名查询

6.2 常用命令

ZADD key [NX|XX] [CH] [INCR] score1 member1 [score2 member2 ...]
ZREM key member [member ...]
ZRANGE key start stop [WITHSCORES]
ZREVRANGE key start stop [WITHSCORES]
ZRANK key member
ZREVRANK key member
ZSCORE key member
ZCOUNT key min max
ZCARD key
ZINCRBY key increment member
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

6.3 应用场景

  1. 排行榜系统:游戏积分排行

    ZADD leaderboard 1000 player1 2000 player2
    ZREVRANGE leaderboard 0 9 WITHSCORES
    
  2. 带权重的队列:优先级任务队列

    ZADD tasks 1 "task1" 3 "urgent_task" 2 "task2"
    ZRANGE tasks 0 0 WITHSCORES
    
  3. 范围查询:时间线数据

    ZADD user:1001:posts 1625097600 "post1" 1625184000 "post2"
    ZRANGEBYSCORE user:1001:posts 1625097600 1625184000
    
  4. 延迟队列:使用时间戳作为score

    ZADD delay_queue <future_timestamp> "task_data"
    # 定期查询到期任务
    ZRANGEBYSCORE delay_queue 0 <current_timestamp>
    

6.4 内部实现

Sorted Set底层使用两种数据结构组合实现:

  1. 跳跃表(skiplist)

    • 支持平均O(logN)复杂度的插入、删除和查找
    • 支持范围操作
    • 存储元素和score的映射关系
  2. 字典(hashtable)

    • 存储member到score的映射
    • 保证O(1)复杂度的member查询

同时,当元素较少时,Redis会使用ziplist来节省内存,由以下配置控制: - zset-max-ziplist-entries (默认128) - zset-max-ziplist-value (默认64字节)

七、其他数据结构

除了五种基本数据结构外,Redis还支持一些特殊的数据结构:

7.1 Bitmaps(位图)

本质:实际上是String类型的扩展,提供位级别操作

常用命令

SETBIT key offset value
GETBIT key offset
BITCOUNT key [start end]
BITOP operation destkey key [key ...]
BITPOS key bit [start] [end]

应用场景: - 用户签到记录 - 活跃用户统计 - 布隆过滤器实现

示例

# 记录用户1001第5天签到
SETBIT user:1001:sign 5 1
# 统计本月签到次数
BITCOUNT user:1001:sign 0 30

7.2 HyperLogLog

本质:用于基数统计的概率算法

常用命令

PFADD key element [element ...]
PFCOUNT key [key ...]
PFMERGE destkey sourcekey [sourcekey ...]

特点: - 极小的空间计算极大基数 - 标准误差0.81% - 不存储实际元素

应用场景: - 网站UV统计 - 大规模去重计数

示例

PFADD visitors 192.168.1.1 192.168.1.2
PFCOUNT visitors

7.3 Geospatial(地理空间)

本质:基于Sorted Set实现的地理位置功能

常用命令

GEOADD key longitude latitude member [longitude latitude member ...]
GEODIST key member1 member2 [unit]
GEOPOS key member [member ...]
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC]

应用场景: - 附近的人 - 地理位置查询 - 距离计算

示例

GEOADD cities 116.405285 39.904989 "Beijing"
GEOADD cities 121.474490 31.230416 "Shanghai"
GEODIST cities Beijing Shanghai km

7.4 Streams(流)

引入版本:Redis 5.0

本质:类似日志的数据结构,用于实现消息队列

常用命令

XADD key [NOMKSTREAM] [MAXLEN|MINID [=|~] threshold [LIMIT count]] *|ID field value [field value ...]
XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key ...] ID [ID ...]
XRANGE key start end [COUNT count]
XREVRANGE key end start [COUNT count]
XGROUP CREATE key groupname ID|$ [MKSTREAM]
XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key ...] ID [ID ...]

特点: - 消息持久化 - 消费者组支持 - 消息回溯 - 阻塞读取

应用场景: - 消息队列 - 事件溯源 - 日志收集

示例

# 生产者
XADD mystream * sensor-id 1234 temperature 19.8
# 消费者
XREAD BLOCK 0 STREAMS mystream $

八、数据结构选择指南

8.1 选择数据结构的考虑因素

  1. 数据特征

    • 是否需要唯一性
    • 是否需要排序
    • 是否需要范围查询
  2. 操作模式

    • 主要操作类型(读/写/更新)
    • 是否需要原子操作
    • 是否频繁修改
  3. 性能需求

    • 预期QPS
    • 响应时间要求
    • 并发访问量
  4. 内存效率

    • 数据量大小
    • 是否需要压缩存储
    • 内存优化需求

8.2 数据结构对比表

数据结构 时间复杂度 主要优势 典型应用场景
String O(1) 简单键值、位操作 缓存、计数器
List 头尾操作O(1) 顺序性、双端操作 队列、时间线
Hash O(1) 结构化数据存储 对象存储、配置
Set O(1) 唯一性、集合运算 标签、好友关系
Sorted Set O(logN) 排序、范围查询 排行榜、优先级队列
Bitmap O(1) 位操作、节省空间 签到、特征标记
HyperLogLog O(1) 基数统计、极小空间 UV统计
Geo O(logN) 地理位置查询 附近的人
Stream O(1)添加 O(N)读取 消息持久化、消费者组 消息队列

8.3 最佳实践建议

  1. String

    • 存储简单键值对
    • 需要原子递增时
    • 二进制数据存储
  2. List

    • 需要保持插入顺序时
    • 实现简单队列或栈
    • 固定长度的历史记录
  3. Hash

    • 存储对象属性
    • 需要单独访问字段时
    • 减少键数量节省内存
  4. Set

    • 需要保证元素唯一性
    • 需要集合运算时
    • 随机获取元素
  5. Sorted Set

    • 需要按分数排序时
    • 需要范围查询
    • 优先级队列实现
  6. Bitmap

    • 布尔型大数据量标记
    • 节省空间的二进制标记
    • 位运算场景
  7. HyperLogLog

    • 大数据量去重计数
    • 允许一定误差的统计场景
  8. Geo

    • 地理位置相关应用
    • 距离计算和范围查询
  9. Stream

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×