Redis 数据类型及相关命令

Redis 数据类型及相关命令详解

Redis (Remote Dictionary Server) 是一个开源的、基于内存的、键值对存储数据库,它以其高性能、丰富的数据类型和原子操作而闻名。Redis 不仅仅是一个简单的键值存储,它更像一个数据结构服务器,支持字符串(String)、列表(List)、集合(Set)、有序集合(Sorted Set)、哈希(Hash)、位图(Bitmap)、HyperLogLog 和地理空间索引(Geospatial Index)等多种数据类型。

本文将深入探讨 Redis 的各种数据类型,详细介绍每种类型的特性、常用命令及其使用场景,帮助读者全面理解和掌握 Redis 的强大功能。

1. 字符串 (String)

字符串是 Redis 中最基本的数据类型,它是二进制安全的,这意味着它可以存储任何类型的数据,例如文本、数字、序列化对象,甚至是图片。字符串类型的最大长度为 512MB。

常用命令:

  • SET key value [EX seconds|PX milliseconds] [NX|XX]:设置键值对。
    • EX seconds:设置过期时间,单位为秒。
    • PX milliseconds:设置过期时间,单位为毫秒。
    • NX:仅当键不存在时设置。
    • XX:仅当键已存在时设置。
  • GET key:获取键对应的值。
  • MSET key value [key value ...]:一次设置多个键值对。
  • MGET key [key ...]:一次获取多个键的值。
  • INCR key:将键的值递增 1,如果键不存在,则创建并初始化为 0,然后递增。
  • INCRBY key increment:将键的值递增指定的整数。
  • DECR key:将键的值递减 1。
  • DECRBY key decrement:将键的值递减指定的整数。
  • APPEND key value:将值追加到键的现有值末尾。
  • STRLEN key:获取键的值的长度。
  • GETRANGE key start end:获取键的值的子字符串。
  • SETRANGE key offset value:从指定的偏移量开始,用新值覆盖键的值的一部分。
  • GETSET key value:设置键的新值,并返回旧值。

使用场景:

  • 缓存: 将经常访问的数据(如用户信息、配置信息)存储在 Redis 中,减少数据库访问次数,提高应用性能。
  • 计数器: 利用 INCRDECR 命令实现各种计数功能,如网站访问量、点赞数、下载量等。
  • 分布式锁: 利用 SETNX 命令(SET 命令的 NX 选项)实现简单的分布式锁。
  • 会话管理: 将用户会话信息存储在 Redis 中,实现快速的会话读取和更新。
  • 全局ID: 利用INCR,保证生成的ID是唯一且递增的.

示例:

```

设置键值对

SET mykey "Hello Redis"

获取键的值

GET mykey # 输出: "Hello Redis"

设置过期时间为 10 秒

SET mykey "Hello Redis" EX 10

递增计数器

INCR counter

批量设置键值对

MSET key1 "value1" key2 "value2"

批量获取键的值

MGET key1 key2 # 输出: 1) "value1" 2) "value2"
```

2. 列表 (List)

列表是一个有序的字符串集合,允许重复元素。Redis 的列表底层实现为双向链表,这意味着在列表两端插入和删除元素的操作非常快(O(1) 时间复杂度),但根据索引访问元素的速度较慢(O(N) 时间复杂度)。

常用命令:

  • LPUSH key value [value ...]:将一个或多个值插入到列表头部。
  • RPUSH key value [value ...]:将一个或多个值插入到列表尾部。
  • LPOP key:移除并返回列表头部的元素。
  • RPOP key:移除并返回列表尾部的元素。
  • LINDEX key index:获取列表指定索引位置的元素。
  • LLEN key:获取列表的长度。
  • LRANGE key start stop:获取列表指定范围内的元素。
  • LINSERT key BEFORE|AFTER pivot value:在列表的指定元素之前或之后插入新元素。
  • LREM key count value:从列表中移除指定数量的指定元素。
    • count > 0:从头部开始移除。
    • count < 0:从尾部开始移除。
    • count = 0:移除所有匹配的元素。
  • LTRIM key start stop:修剪列表,只保留指定范围内的元素。
  • BLPOP key [key ...] timeout:阻塞式地移除并返回列表头部的元素,如果列表为空,则阻塞直到有元素可用或超时。
  • BRPOP key [key ...] timeout:阻塞式地移除并返回列表尾部的元素。

使用场景:

  • 消息队列: 利用 LPUSHBRPOP 命令实现简单的消息队列,生产者将消息推入列表,消费者阻塞式地从列表尾部取出消息。
  • 最新动态: 存储用户发布的最新动态,例如微博、朋友圈等,可以使用LRANGE命令分页显示.
  • 任务队列: 存储待处理的任务,多个工作进程可以并发地从任务队列中获取任务。
  • 历史记录: 存储用户的操作历史记录,例如浏览记录、搜索记录等。

示例:

```

将元素插入列表头部

LPUSH mylist "world"
LPUSH mylist "hello"

获取列表所有元素

LRANGE mylist 0 -1 # 输出: 1) "hello" 2) "world"

从列表尾部弹出一个元素

RPOP mylist # 输出: "world"

阻塞式地从列表头部获取元素,超时时间为 10 秒

BLPOP mylist 10
```

3. 集合 (Set)

集合是一个无序的、不重复的字符串集合。Redis 的集合底层实现为哈希表,因此添加、删除和查找元素的操作都非常快(O(1) 时间复杂度)。

常用命令:

  • SADD key member [member ...]:向集合添加一个或多个成员。
  • SREM key member [member ...]:从集合中移除一个或多个成员。
  • SMEMBERS key:获取集合的所有成员。
  • SISMEMBER key member:判断成员是否属于集合。
  • SCARD key:获取集合的成员数量。
  • SINTER key [key ...]:返回多个集合的交集。
  • SUNION key [key ...]:返回多个集合的并集。
  • SDIFF key [key ...]:返回第一个集合与其他集合的差集。
  • SRANDMEMBER key [count]:随机返回集合中的一个或多个成员。
  • SPOP key [count]:随机移除并返回集合中的一个或多个成员。
  • SMOVE source destination member: 将member元素从source集合移动到destination集合.

使用场景:

  • 标签系统: 为对象添加标签,例如为文章添加“科技”、“互联网”、“新闻”等标签,可以方便地进行标签搜索和统计。
  • 好友关系: 存储用户的好友关系,可以快速查找共同好友、判断是否为好友等。
  • 黑名单/白名单: 存储 IP 地址黑名单或白名单,用于访问控制。
  • 唯一值过滤: 利用集合的去重特性,过滤重复的数据,例如统计独立访客(UV)。
  • 抽奖系统: 利用SRANDMEMBERSPOP 命令实现.

示例:

```

向集合添加成员

SADD myset "apple"
SADD myset "banana"
SADD myset "apple" # 重复添加会被忽略

获取集合所有成员

SMEMBERS myset # 输出: 1) "banana" 2) "apple"

判断成员是否属于集合

SISMEMBER myset "orange" # 输出: 0 (false)

计算两个集合的交集

SADD otherset "banana"
SADD otherset "cherry"
SINTER myset otherset # 输出: 1) "banana"
```

4. 有序集合 (Sorted Set)

有序集合与集合类似,也是一个不重复的字符串集合,但每个成员都关联一个分数(score),Redis 根据分数对成员进行排序。有序集合的底层实现结合了哈希表和跳跃表(Skip List),因此在查找、添加、删除和更新元素时都能保持较好的性能(O(log N) 时间复杂度)。

常用命令:

  • ZADD key [NX|XX] [CH] [INCR] score member [score member ...]:向有序集合添加一个或多个成员,或更新已存在成员的分数。
    • NX:仅当成员不存在时添加。
    • XX:仅当成员已存在时更新。
    • CH:返回修改的成员数量,包括添加的和更新的。
    • INCR:将成员的分数增加指定的值,类似于 ZINCRBY 命令。
  • ZREM key member [member ...]:从有序集合中移除一个或多个成员。
  • 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]:获取有序集合分数在指定范围内的成员,按分数从大到小排序。
  • ZSCORE key member:获取成员的分数。
  • ZRANK key member:获取成员的排名(从小到大)。
  • ZREVRANK key member:获取成员的排名(从大到小)。
  • ZCARD key:获取有序集合的成员数量。
  • ZCOUNT key min max:计算有序集合分数在指定范围内的成员数量。
  • ZINCRBY key increment member:将成员的分数增加指定的值。
  • ZREMRANGEBYRANK key start stop:移除有序集合指定排名范围内的成员。
  • ZREMRANGEBYSCORE key min max:移除有序集合分数在指定范围内的成员。

使用场景:

  • 排行榜: 存储游戏玩家的得分、文章的阅读量、商品的销量等,可以实时更新排行榜。
  • 带权重的任务队列: 为任务分配不同的优先级(分数),优先级高的任务先被处理。
  • 延迟队列: 将任务的执行时间作为分数,定期检查分数最小的任务是否到期,如果到期则执行。
  • 范围查询: 按照分数范围查找,例如查找价格在某个区间的商品

示例:

```

向有序集合添加成员

ZADD leaderboard 100 "player1"
ZADD leaderboard 80 "player2"
ZADD leaderboard 120 "player3"

获取排行榜前两名(按分数从大到小)

ZREVRANGE leaderboard 0 1 WITHSCORES

输出:

1) "player3"

2) "120"

3) "player1"

4) "100"

获取玩家 "player2" 的分数

ZSCORE leaderboard "player2" # 输出: 80

将玩家 "player2" 的分数增加 10

ZINCRBY leaderboard 10 "player2"
```

5. 哈希 (Hash)

哈希是一个键值对集合,其中每个键都关联一个或多个字段(field)和值(value)。哈希非常适合存储对象,可以将对象的多个属性存储在同一个哈希中。

常用命令:

  • HSET key field value [field value ...]:设置哈希中一个或多个字段的值。
  • HGET key field:获取哈希中指定字段的值。
  • HMSET key field value [field value ...]:一次设置哈希中多个字段的值。
  • HMGET key field [field ...]:一次获取哈希中多个字段的值。
  • HGETALL key:获取哈希中所有字段和值。
  • HDEL key field [field ...]:删除哈希中一个或多个字段。
  • HEXISTS key field:判断哈希中是否存在指定字段。
  • HINCRBY key field increment:将哈希中指定字段的值增加指定的整数。
  • HINCRBYFLOAT key field increment:将哈希中指定字段的值增加指定的浮点数。
  • HKEYS key:获取哈希中所有字段。
  • HVALS key:获取哈希中所有值。
  • HLEN key:获取哈希中字段的数量。

使用场景:

  • 存储对象: 将对象(如用户信息、商品信息)的多个属性存储在同一个哈希中,可以方便地读取和更新对象的属性。
  • 购物车: 将用户的购物车信息存储在哈希中,每个商品 ID 作为字段,商品数量作为值。
  • 配置管理: 将配置信息存储在哈希中,每个配置项作为字段,配置值作为值。

示例:

```

设置用户信息

HSET user:1 name "Alice" age 30 email "[email protected]"

获取用户信息

HGETALL user:1

输出:

1) "name"

2) "Alice"

3) "age"

4) "30"

5) "email"

6) "[email protected]"

获取用户年龄

HGET user:1 age # 输出: "30"

将用户年龄增加 1

HINCRBY user:1 age 1
```

6. 位图 (Bitmap)

位图不是一个真正的数据类型,它实际上是字符串类型的一种特殊用法。位图可以看作是一个由比特位组成的数组,每个比特位可以设置为 0 或 1。Redis 的位图操作可以高效地进行位级别的操作,例如统计用户活跃状态、签到等。

常用命令:

  • SETBIT key offset value:设置位图中指定偏移量上的比特位的值。
  • GETBIT key offset:获取位图中指定偏移量上的比特位的值。
  • BITCOUNT key [start end]:统计位图中值为 1 的比特位的数量。
  • BITOP operation destkey key [key ...]:对多个位图进行位运算(AND、OR、XOR、NOT),并将结果保存到目标键中。
  • BITPOS key bit [start] [end]:查找位图中第一个值为指定值的比特位的偏移量。

使用场景:

  • 用户活跃状态: 使用位图记录用户的每日活跃状态,每一位代表一天,1 表示活跃,0 表示不活跃,可以快速统计活跃用户数、连续活跃天数等。
  • 用户签到: 使用位图记录用户的每日签到状态,每一位代表一天,1 表示已签到,0 表示未签到。
  • 布隆过滤器: 位图可以用于实现布隆过滤器,用于判断一个元素是否存在于一个集合中。
  • 统计独立用户: 每天的独立用户可以使用一个Bitmap来记录,最后通过BITOP命令进行计算.

示例:

```

设置用户在第 1 天和第 3 天活跃

SETBIT user:activity 0 1
SETBIT user:activity 2 1

获取用户在第 2 天的活跃状态

GETBIT user:activity 1 # 输出: 0 (false)

统计用户活跃天数

BITCOUNT user:activity # 输出: 2

对两个位图进行 AND 运算

SETBIT user1:activity 0 1
SETBIT user1:activity 1 1
SETBIT user2:activity 1 1
BITOP AND result user1:activity user2:activity
BITCOUNT result # 输出 1
```

7. HyperLogLog

HyperLogLog 是一种概率数据结构,用于估计一个集合中不同元素的数量(基数)。HyperLogLog 的优点是只需要非常小的内存空间就可以估计非常大的基数,但它提供的计数是近似值,有一定的误差。

常用命令:

  • PFADD key element [element ...]:向 HyperLogLog 添加一个或多个元素。
  • PFCOUNT key [key ...]:返回 HyperLogLog 的近似基数。
  • PFMERGE destkey sourcekey [sourcekey ...]:合并多个 HyperLogLog。

使用场景:

  • 统计网站 UV: 使用 HyperLogLog 统计网站的独立访客数(UV),只需要很小的内存空间就可以统计数亿级别的 UV。
  • 统计搜索关键词: 使用 HyperLogLog 统计搜索关键词的数量,可以了解用户搜索的热点。

示例:

```

向 HyperLogLog 添加元素

PFADD myhll "apple"
PFADD myhll "banana"
PFADD myhll "apple" # 重复添加会被忽略

获取 HyperLogLog 的近似基数

PFCOUNT myhll # 输出: 2 (可能略有误差)
```

8. 地理空间索引 (Geospatial Index)

地理空间索引是一种用于存储和查询地理位置信息的数据结构。Redis 的地理空间索引可以将经纬度坐标与成员关联起来,并提供基于位置的查询功能,例如查找附近的成员、计算距离等。

常用命令:

  • GEOADD key longitude latitude member [longitude latitude member ...]:将经纬度坐标与成员添加到地理空间索引中。
  • GEOPOS key member [member ...]:获取成员的经纬度坐标。
  • GEODIST key member1 member2 [unit]:计算两个成员之间的距离。
    • unit:距离单位,可以是 m(米)、km(千米)、mi(英里)、ft(英尺)。
  • GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]:根据给定的经纬度坐标和半径,查找附近的成员。
    • WITHCOORD:返回成员的经纬度坐标。
    • WITHDIST:返回成员与中心点的距离。
    • WITHHASH:返回成员的 geohash 值。
    • COUNT count:限制返回的成员数量。
    • ASC|DESC:按距离排序(升序或降序)。
    • STORE key:将查询结果存储到指定的键中(存储成员)。
    • STOREDIST key:将查询结果存储到指定的键中(存储距离)。
  • GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]:根据给定的成员和半径,查找附近的成员。
  • GEOHASH key member [member ...]:获取成员的 geohash 值。

使用场景:

  • 附近的商家: 存储商家的位置信息,可以根据用户的位置查找附近的商家。
  • 打车服务: 存储司机的位置信息,可以根据乘客的位置查找附近的司机。
  • 社交应用: 存储用户的位置信息,可以查找附近的人。

示例:

```

添加商家的位置信息

GEOADD locations 116.397128 39.916527 "商家A"
GEOADD locations 116.410873 39.919553 "商家B"

获取商家 A 的经纬度坐标

GEOPOS locations "商家A"

输出:

1) "116.39712834358215332"

2) "39.91652705063035746"

查找距离 (116.4, 39.92) 1 公里范围内的商家

GEORADIUS locations 116.4 39.92 1 km WITHCOORD WITHDIST
```

总结

Redis 提供了丰富的数据类型,每种类型都有其独特的特性和适用场景。通过灵活运用这些数据类型,可以构建高性能、高可用的应用。希望本文能够帮助你深入理解 Redis 的各种数据类型及其相关命令,并在实际开发中充分发挥 Redis 的优势。

请注意,本文仅涵盖了 Redis 的主要数据类型和常用命令,Redis 还有许多其他功能和命令,例如事务、发布/订阅、Lua 脚本、持久化等,读者可以参考 Redis 官方文档进行更深入的学习。

THE END