一、Redis简介

Redis(Remote Dictionary Server)是一个开源的、基于内存的数据结构存储系统,可用作数据库、缓存和消息代理。它支持丰富的数据类型、高可用方案和集群模式,被广泛应用于互联网业务中。

1.1 核心特性

  • 内存存储:所有数据常驻内存,读写延迟极低(微秒级)。
  • 数据结构丰富:支持多种数据结构,包括string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)、位图、超日志等。
  • 持久化:支持 RDB(快照)和 AOF(追加文件)两种持久化方式,可以将数据持久化到磁盘。
  • 高可用:主从复制、Sentinel 哨兵、Redis Cluster 集群。
  • 原子操作:单线程命令执行模型(6.0+ 引入多线程 I/O,但命令执行仍串行),天然支持原子操作。
  • Lua 脚本支持:可以使用 Lua 脚本在服务器端执行复杂的操作,减少网络延迟。

1.2 Redis 缺点

  1. 内存容量有限,成本高

    • 数据全部在内存,不能无限制存海量数据
    • 内存比磁盘贵很多,大数据量成本高
  2. 单线程命令执行,阻塞风险大

    • 执行命令是单线程
    • 慢命令(KEYS *、HGETALL大 Hash、LRANGE大量数据)会阻塞整个 Redis
    • BigKey 读写会严重卡顿
  3. 持久化有性能 / 数据安全取舍

    • RDB:宕机会丢数据
    • AOF:每秒刷盘最均衡,但依然可能丢 1s 数据
    • 持久化重写时会占用 CPU/IO
  4. 不支持复杂查询,没有 SQL

    • 只能按 key 查询,不支持条件查询、联表查询
    • 复杂业务查询必须依赖数据库
  5. 不支持事务回滚,弱事务

    • Redis 事务只能批量执行,不支持回滚
    • 中间一条失败,前面命令不会撤销
    • 真正原子性要靠 Lua
  6. 集群模式使用有约束

    • Redis Cluster 不支持跨节点事务、跨槽多键操作
    • 事务、Lua、MSET 等需要 key 在同槽
    • 扩容缩槽有数据迁移成本
  7. 内存淘汰可能导致业务抖动

    • 内存满后触发 LFU/LRU 淘汰
    • 淘汰瞬间可能卡顿,缓存命中率下降

1.3 适用场景

  1. 缓存:热点数据缓存、页面缓存、Session 共享。
  2. 计数器:阅读量、点赞数、限流(滑动窗口)。
  3. 排行榜:有序集合实现实时排行。
  4. 分布式锁:SET NX EX 实现互斥锁。
  5. 消息队列:Stream 或 List 实现简单队列。
  6. 社交网络:共同关注、好友关系(Set 交并差)。
  7. 地理位置:附近的人(Geospatial)。
  8. 位图统计:用户签到、活跃度统计。

1.4 基本配置(redis.conf 要点)

  • bind 0.0.0.0 – 允许所有 IP 访问(生产环境应限制)。
  • protected-mode yes – 保护模式,需设置密码或绑定 IP。
  • requirepass yourpassword – 设置密码。
  • port 6379 – 服务端口。
  • daemonize yes – 后台运行。
  • maxmemory 2gb – 最大内存限制。
  • maxmemory-policy allkeys-lru – 内存淘汰策略。

二、Redis数据类型

2.1 String(字符串)

String 类型是 Redis 中最基本的数据类型之一。它可以存储任何类型的数据,包括文本、数字、二进制数据等,最大能存储 512MB。

  • 内部编码:int(整数)、embstr(短字符串)、raw(长字符串)。
  • 应用场景:缓存对象(JSON 序列化)、计数器、分布式锁。
  • 常用命令:
    1. 设置和获取字符串
      • SET key value
        • 设置指定 key 的值为 value。
        • 示例:SET mykey “Hello World”
      • GET key
        • 获取指定 key 的值。
        • 示例:GET mykey // 返回 “Hello World”
    2. 修改字符串
      • APPEND key value
        • 将 value 追加到指定 key 的值后面。
        • 示例:APPEND mykey “!” // mykey 的值变为 “Hello World!”
      • INCR key
        • 将 key 的值加 1(值必须是整数)。
        • 示例:INCR mycounter // 如果 mycounter 不存在,则初始化为 0,然后加 1
      • DECR key
        • 将 key 的值减 1(值必须是整数)。
        • 示例:DECR mycounter // 将 mycounter 的值减 1
      • INCRBY key increment
        • 将 key 的值增加指定的增量。
        • 示例:INCRBY mycounter 5 // 将 mycounter 的值增加 5
      • DECRBY key decrement
        • 将 key 的值减少指定的减量。
        • 示例:DECRBY mycounter 3 // 将 mycounter 的值减少 3
    3. 字符串长度
      • STRLEN key
        • 获取指定 key 的字符串长度。
        • 示例:STRLEN mykey // 返回 mykey 的长度
    4. 字符串切片
      • GETRANGE key start end
        • 获取指定 key 的子字符串。
        • 示例:GETRANGE mykey 0 4 // 返回 “Hello”
      • SETRANGE key offset value
        • 用 value 替换 key 中从 offset 开始的部分。
        • 示例:SETRANGE mykey 6 “Redis” // mykey 的值变为 “Hello Redis”
    5. 其他命令
      • MSET key1 value1 key2 value2 …
        • 同时设置多个 key 的值。
        • 示例:MSET key1 “value1” key2 “value2”
      • MGET key1 key2 …
        • 获取多个 key 的值。
        • 示例:MGET key1 key2 // 返回 [“value1”, “value2”]
      • SETNX key value
        • 仅在 key 不存在时设置 key 的值。
        • 示例:SETNX mykey “Hello” // 如果 mykey 已存在,则不执行
      • SETEX key seconds value
        • 设置 key 的值,并设置过期时间(秒)。
        • 示例:SETEX mykey 10 “Hello” // mykey 在 10 秒后过期
    6. 过期和持久化
      • EXPIRE key seconds
        • 设置 key 的过期时间(秒)。
        • 示例:EXPIRE mykey 60 // mykey 在 60 秒后过期
      • TTL key
        • 获取 key 的剩余生存时间(秒)。
        • 示例:TTL mykey // 返回 mykey 的剩余时间
    7. 其他有用的命令
      • PSETEX key milliseconds value
        • 设置 key 的值,并设置过期时间(毫秒)。
        • 示例:PSETEX mykey 5000 “Hello” // mykey 在 5000 毫秒后过期
      • GETSET key value
        • 获取指定 key 的当前值,并将其设置为 value。
        • 示例:GETSET mykey “New Value” // 返回原值并将 mykey 设置为 “New Value”

以下是一些使用 Redis String 类型的示例:

# 设置键值
SET name "Alice"
SET age 30

# 获取键值
GET name  # 返回 "Alice"
GET age   # 返回 "30"

# 增加年龄
INCR age  # age 变为 31

# 追加字符串
APPEND name " Smith"  # name 变为 "Alice Smith"

# 设置带过期时间的键
SETEX session_id 3600 "abc123"  # session_id 在 3600 秒后过期

2.2 Hash(哈希)

Hash 类型是一种非常有用的数据结构,适合存储对象的属性。Hash 是一个键值对集合,键是字符串,值也是字符串。每个 Hash 可以存储 2^32 - 1 键值对(40多亿)。

  • 结构:key -> { field1: value1, field2: value2 },适合存储对象。
  • 内部编码:ziplist(小数据)、hashtable(大数据)。
  • 应用场景:用户信息、购物车(用户 ID 为 key,商品 ID 为 field,数量为 value)。
  • 常用命令:
    1. 基本命令
      • HSET
        • 描述:设置哈希表中指定字段的值。
        • 语法:HSET key field value
        • 示例:HSET user:1000 name “Alice”
      • HGET
        • 描述:获取哈希表中指定字段的值。
        • 语法:HGET key field
        • 示例:HGET user:1000 name
      • HDEL
        • 描述:删除哈希表中一个或多个指定字段。
        • 语法:HDEL key field1 [field2]
        • 示例:HDEL user:1000 age
      • HEXISTS
        • 描述:查看哈希表中指定字段是否存在。
        • 语法:HEXISTS key field
        • 示例:HEXISTS user:1000 name
      • HGETALL
        • 描述:获取哈希表中所有字段和值。
        • 语法:HGETALL key
        • 示例:HGETALL user:1000
    2. 计数和长度命令
      • HINCRBY
        • 描述:将哈希表中指定字段的整数值加上给定的增量。
        • 语法:HINCRBY key field increment
        • 示例:HINCRBY user:1000 age 1
      • HLEN
        • 描述:获取哈希表中字段的数量。
        • 语法:HLEN key
        • 示例:HLEN user:1000
    3. 获取字段命令
      • HKEYS
        • 描述:获取哈希表中所有字段的名称。
        • 语法:HKEYS key
        • 示例:HKEYS user:1000
      • HVALS
        • 描述:获取哈希表中所有字段的值。
        • 语法:HVALS key
        • 示例:HVALS user:1000
    4. 其他命令
      • HSCAN
        • 描述:迭代哈希表中的字段和元素。
        • 语法:HSCAN key cursor [MATCH pattern] [COUNT count]
        • 示例:HSCAN user:1000 0
      • HMGET
        • 描述:获取哈希表中多个字段的值。
        • 语法:HMGET key field1 [field2 …]
        • 示例:HMGET user:1000 name age

以下是一些使用 Redis Hash类型的示例:

# 设置用户信息
HSET user:1000 name "Alice"
HSET user:1000 age 30
HSET user:1000 email "alice@example.com"

# 获取用户信息
HGETALL user:1000
# 输出: 1) "name" 2) "Alice" 3) "age" 4) "30" 5) "email" 6) "alice@example.com"

# 增加年龄
HINCRBY user:1000 age 1

# 检查字段是否存在
HEXISTS user:1000 email
# 输出: 1 (存在)

# 获取所有字段名
HKEYS user:1000
# 输出: 1) "name" 2) "age" 3) "email"

# 获取所有字段值
HVALS user:1000
# 输出: 1) "Alice" 2) "31" 3) "alice@example.com"

2.3 List(列表)

List 类型是一种简单的字符串列表,按照插入顺序排序。它支持从两端插入和删除元素,适合实现队列和栈等数据结构。一个列表最多可以包含 2^32 - 1 个元素,超过40亿个元素。

  • 特点:有序、可重复,基于双向链表实现(两端操作 O(1),中间 O(N))。
  • 内部编码:ziplist(小数据)、linkedlist(旧)、quicklist(3.2+,混合结构)。
  • 应用场景:消息队列、最新消息列表(如评论时间线)。
  • 常用命令:
    1. 插入命令
      • LPUSH key value [value …]
        • 在列表的左侧插入一个或多个值。
        • 示例:LPUSH mylist “value1” “value2”
      • RPUSH key value [value …]
        • 在列表的右侧插入一个或多个值。
        • 示例:RPUSH mylist “value3” “value4”
    2. 删除命令
      • LPOP key
        • 移除并返回列表的左侧第一个元素。
        • 示例:LPOP mylist
      • RPOP key
        • 移除并返回列表的右侧第一个元素。
        • 示例:RPOP mylist
      • LREM key count value
        • 移除列表中与指定值相等的元素。
        • count 参数可以是正数(从左到右移除)、负数(从右到左移除)或零(移除所有匹配的元素)。
        • 示例:LREM mylist 0 “value1”
    3. 访问命令
      • LRANGE key start stop
        • 返回列表中指定范围内的元素(包含 start 和 stop)。
        • 示例:LRANGE mylist 0 -1 # 返回整个列表
      • LINDEX key index
        • 返回列表中指定索引的元素。
        • 示例:LINDEX mylist 0 # 返回第一个元素
    4. 其他命令
      • LLEN key
        • 返回列表的长度。
        • 示例:LLEN mylist
      • LTRIM key start stop
        • 修剪列表,只保留指定范围内的元素。
        • 示例:LTRIM mylist 0 1 # 只保留前两个元素
      • RPOPLPUSH source destination
        • 移除 source 列表的最后一个元素,并将该元素插入到 destination 列表的最前面。
        • 示例:RPOPLPUSH mylist2 mylist1
    5. 事务和批量操作
      • MULTI / EXEC
        • 可以在事务中执行多个命令。
        • 示例:
          MULTI
          LPUSH mylist "value1"
          RPUSH mylist "value2"
          EXEC
          

以下是一些使用 Redis List类型的示例:

# 插入元素
LPUSH mylist "A"
RPUSH mylist "B"
RPUSH mylist "C"

# 查看列表长度
LLEN mylist  # 返回 3

# 获取列表元素
LRANGE mylist 0 -1  # 返回 ["A", "B", "C"]

# 移除元素
LPOP mylist  # 返回 "A"
RPOP mylist  # 返回 "C"

# 最终列表
LRANGE mylist 0 -1  # 返回 ["B"]

2.4 Set(集合)

Set 类型是一种无序且不重复的集合,且集合中的值唯一,支持多种操作。

  • 特点:元素唯一、无序,支持交并差运算。
  • 内部编码:intset(整数小集合)、hashtable。
  • 应用场景:标签系统(用户标签集合)、共同好友、抽奖(SRANDMEMBER)。
  • 常用命令:
    1. 添加元素
      • SADD key member [member …]
        • 向集合中添加一个或多个成员。如果成员已经存在于集合中,则忽略。
        • 示例:SADD myset “apple” “banana” “orange”
    2. 获取集合中的所有成员
      • SMEMBERS key
        • 返回集合中所有的成员。
        • 示例:SMEMBERS myset
    3. 检查成员是否在集合中
      • SISMEMBER key member
        • 判断某个成员是否是集合的成员。
        • 示例:SISMEMBER myset “apple”
    4. 移除成员
      • SREM key member [member …]
        • 移除集合中的一个或多个成员。
        • 示例:SREM myset “banana”
    5. 获取集合的成员数量
      • SCARD key
        • 返回集合中成员的数量。
        • 示例:SCARD myset
    6. 随机获取集合中的一个成员
      • SPOP key
        • 移除并返回集合中的一个随机成员。
        • 示例:SPOP myset
    7. 随机获取多个成员
      • SRANDMEMBER key [count]
        • 返回集合中的一个或多个随机成员,不移除它们。
        • 示例:SRANDMEMBER myset 2
    8. 交集
      • SINTER key1 [key2 …]
        • 返回一个集合中所有给定集合的交集。
        • 示例:SINTER set1 set2
    9. 并集
      • SUNION key1 [key2 …]
        • 返回一个集合中所有给定集合的并集。
        • 示例:SUNION set1 set2
    10. 差集
      • SDIFF key1 [key2 …]
        • 返回一个集合中所有给定集合的差集。
        • 示例:SDIFF set1 set2
    11. 将一个集合的成员移动到另一个集合
      • SMOVE source destination member
        • 将成员从一个集合移动到另一个集合。
        • 示例:SMOVE myset2 myset1 “apple”
    12. 清空集合
      • DEL key
        • 删除一个集合。
        • 示例:DEL myset

以下是一些使用 Redis Set类型的示例:

# 添加元素
SADD myset "apple"
SADD myset "banana"
SADD myset "orange"

# 获取集合中的所有元素
SMEMBERS myset

# 检查元素是否在集合中
SISMEMBER myset "banana"  # 返回 1 (true)
SISMEMBER myset "grape"   # 返回 0 (false)

# 删除元素
SREM myset "banana"

# 获取集合的元素数量
SCARD myset

# 取两个集合的交集
SADD set1 "apple" "banana" "orange"
SADD set2 "banana" "kiwi" "orange"
SINTER set1 set2  # 返回 {"banana", "orange"}

# 取两个集合的并集
SUNION set1 set2  # 返回 {"apple", "banana", "orange", "kiwi"}

# 取两个集合的差集
SDIFF set1 set2  # 返回 {"apple"}

# 随机获取集合中的元素
SRANDMEMBER myset 1  # 随机返回一个元素
SRANDMEMBER myset 3  # 随机返回三个元素

# 移动元素到另一个集合
SMOVE myset anotherSet "apple"

# 清空集合
SMOVE myset anotherSet "apple"
DEL myset

2.5 Sorted Set(有序集合)

Sorted Set是一种非常强大的数据结构,它结合了Set集合的特性和有序列表的特性。每个元素都有一个分数(score),Redis 会根据分数对元素进行排序。

  • 特点:每个元素关联一个 double 类型分数(score),按分数升序排列。元素唯一,分数可重复。
  • 内部编码:ziplist(小数据)、skiplist + dict(大数据)。
  • 应用场景:排行榜(如积分榜)、延迟队列(按时间戳排序)、带权重的任务队列。
  • 常用命令:
    1. 添加元素

      • ZADD:向有序集合添加一个或多个成员,或者更新已存在成员的分数。
      ZADD key score member [score member ...]
      
    2. 获取元素

      • ZRANGE:返回有序集合中指定区间内的成员,按分数从小到大排序。
      ZRANGE key start stop [WITHSCORES]
      
      • ZRANGEBYSCORE: 返回有序集合中指定分数范围内的成员。
      ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
      
    3. 删除元素

      • ZREM: 移除有序集合中的一个或多个成员。
      ZREM key member [member ...]
      
    4. 计数

      • ZCARD: 返回有序集合的成员数量。
      ZCARD key
      
      • ZCOUNT: 计算有序集合中指定分数范围内的成员数量。
      ZCOUNT key min max
      
    5. 获取分数

      • ZSCORE: 返回有序集合中指定成员的分数。
      ZSCORE key member
      
    6. 排名

      • ZRANK: 返回有序集合中指定成员的排名(从小到大)。
      ZRANK key member
      
      • ZREVRANK: 返回有序集合中指定成员的排名(从大到小)。
      ZREVRANK key member
      
    7. 其他命令

      • ZPOPMIN: 移除并返回有序集合中分数最小的一个或多个成员。
      ZPOPMIN key [count]
      
      • ZPOPMAX: 移除并返回有序集合中分数最大的一个或多个成员。
      ZPOPMAX key [count]
      
      • ZINTERSTORE: 计算给定的一个或多个有序集合的交集,并将结果存储在新的有序集合中。
      ZINTERSTORE destination numkeys key1 key2 ... [WEIGHTS weight1 weight2 ...] [AGGREGATE SUM|MIN|MAX]
      
      • ZUNIONSTORE: 计算给定的一个或多个有序集合的并集,并将结果存储在新的有序集合中。
      ZUNIONSTORE destination numkeys key1 key2 ... [WEIGHTS weight1 weight2 ...] [AGGREGATE SUM|MIN|MAX]
      

以下是一些使用 Sorted Set类型的示例:

# 添加元素
ZADD myzset 1 "one" 2 "two" 3 "three"

# 获取排名
ZRANK myzset "two"  # 返回 1

# 获取分数
ZSCORE myzset "three"  # 返回 3

# 获取范围内的元素
ZRANGE myzset 0 -1 WITHSCORES  # 返回所有元素及其分数

2.6 其他特殊类型

  • Bitmaps(位图):基于 String 的位操作。SETBIT、GETBIT、BITCOUNT、BITOP。适用:签到、在线状态、布隆过滤器。

    SETBIT sign:20250101 100 1    # 设置第100位为1(用户签到)
    GETBIT sign:20250101 100      # 获取位值
    BITCOUNT sign:20250101        # 统计1的个数
    BITOP AND result key1 key2    # 位运算
    
  • HyperLogLog:基数统计(近似去重计数)。PFADD、PFCOUNT、PFMERGE。内存占用固定 12KB,误差约 0.81%。适用:UV 统计。

    PFADD visitors "user1" "user2" "user3"   # 添加元素
    PFCOUNT visitors                         # 获取基数估算值
    PFMERGE dest src1 src2                   # 合并
    
  • Geospatial:地理位置存储和计算。GEOADD、GEOPOS、GEODIST、GEORADIUS(已弃用,建议用 GEOSEARCH)。适用:附近的人、地点距离计算。

    GEOADD cities 116.40 39.90 "北京" 121.48 31.22 "上海"
    GEODIST cities "北京" "上海" km          # 计算距离
    GEORADIUS cities 116.40 39.90 100 km   # 半径查询
    
  • Stream:消息队列(类似 Kafka)。XADD、XREAD、XGROUP、XACK。支持消费组、消息持久化。适用:可靠消息队列。

    XADD mystream * name "Alice"    # 添加消息
    XREAD COUNT 2 STREAMS mystream 0 # 读取
    XGROUP CREATE mystream mygroup 0 # 创建消费者组
    XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream >
    
Logo

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

更多推荐