跳至主要內容

五种基础数据类型(对比 JS 数据结构)

Mr.Dingredis基础数据结构前端转后端大约 4 分钟约 1088 字

五种基础数据类型(对比 JS 数据结构)

Redis 数据结构总览

┌────────────────────────────────────────────────────────┐
│                    Redis 数据类型                         │
├──────────┬──────────────────┬──────────────────────────┤
│ 类型     │ 底层结构          │ 前端类比                  │
├──────────┼──────────────────┼──────────────────────────┤
│ String   │ 动态字符串        │ string + number           │
│ List     │ 双向链表/压缩列表  │ Array(push/pop)        │
│ Hash     │ 哈希表            │ Map<string, string>      │
│ Set      │ 哈希表            │ Set                      │
│ Zset     │ 跳表 + 哈希表     │ 有序 Set(自动排序)      │
└──────────┴──────────────────┴──────────────────────────┘

1. String — 字符串(最基础)

# 存/取(≈ map.set / map.get)
SET name "小明"              # 存入
GET name                     # → "小明"

# 数值操作(原子性!没有并发问题)
SET count 0
INCR count                   # → 1(原子 +1)
INCRBY count 5              # → 6(原子 +5)
DECR count                   # → 5(原子 -1)

# 设置过期时间(≈ setTimeout + 自动删除)
SET code "1234" EX 60        # 60秒后自动删除
SETEX code 60 "1234"        # 同上,另一种写法
TTL code                     # 查看剩余秒数
// JS 类比
const redis = new Map();
redis.set('name', '小明');
redis.get('name');          // '小明'

// 但 JS 没有原生的过期机制和原子递增
// Redis 是单线程处理命令,天然原子

适用场景:缓存 HTML、存 Session、计数器、验证码、分布式锁


2. List — 列表(≈ JS Array 的双向链表版)

# 右入/左出(队列 FIFO)
RPUSH queue "任务1"          # 右边入队
RPUSH queue "任务2"
LPOP queue                   # 左边出队 → "任务1"

# 左入/右出(栈 LIFO)
LPUSH stack "A"              # 左边入栈
LPUSH stack "B"
RPOP stack                   # 右边出栈 → "B"

# 范围查询(≈ arr.slice)
LRANGE list 0 -1            # 全部元素
LRANGE list 0 2             # 前3个

# 长度
LLEN list                    # ≈ arr.length
// JS 类比
const queue = [];
queue.push('任务1');          // RPUSH
queue.push('任务2');
queue.shift();                // LPOP → '任务1'

const stack = [];
stack.unshift('A');           // LPUSH
stack.unshift('B');
stack.pop();                  // RPOP → 'B'

适用场景:消息队列、最新消息列表(取前 N 条)、时间线


3. Hash — 哈希(≈ JS Map)

# 存储对象(比 String 存 JSON 更灵活)
HSET user:1 name "小明" age "25" city "北京"
HGET user:1 name             # → "小明"
HGETALL user:1                # → {name: "小明", age: "25", city: "北京"}

# 批量操作
HMSET user:2 name "小红" age "23"
HMGET user:2 name age        # → ["小红", "23"]

# 递增某个字段
HINCRBY user:1 age 1        # 年龄 +1

# 获取所有字段或值
HKEYS user:1                  # → ["name", "age", "city"]
HVALS user:1                 # → ["小明", "25", "北京"]
// JS 类比
const user1 = new Map();
user1.set('name', '小明');
user1.set('age', '25');
user1.get('name');           // '小明'

适用场景:存储用户信息/商品信息/配置等对象数据(比 String 存取部分字段更高效)


4. Set — 集合(≈ JS Set)

# 添加/移除
SADD tags "前端" "后端" "数据库"
SREM tags "后端"

# 判断是否存在(≈ set.has)
SISMEMBER tags "前端"        # → 1(存在)
SISMEMBER tags "后端"        # → 0(已移除)

# 集合操作
SMEMBERS tags                 # → ["前端", "数据库"]
SCARD tags                   # → 2(元素个数)

# 集合运算(Redis 特产)
SADD setA "a" "b" "c"
SADD setB "b" "c" "d"

SINTER setA setB             # 交集 → ["b", "c"]
SUNION setA setB             # 并集 → ["a", "b", "c", "d"]
SDIFF setA setB              # 差集 → ["a"]
// JS 类比
const tags = new Set(['前端', '后端', '数据库']);
tags.delete('后端');
tags.has('前端');             // true

适用场景:标签系统、共同好友(交集)、每日签到(去重)


5. Zset — 有序集合(JS 没有直接对应,Redis 独有)

# 加分的成员(score 自动排序)
ZADD leaderboard 100 "小明"    # 100 分
ZADD leaderboard 80 "小红"     # 80 分
ZADD leaderboard 95 "小刚"     # 95 分

# 查看排名(升序:从低到高)
ZRANGE leaderboard 0 -1 WITHSCORES
# → ["小红", 80, "小刚", 95, "小明", 100]

# 查看排名(降序:谁分数最高排第一)
ZREVRANGE leaderboard 0 -1 WITHSCORES
# → ["小明", 100, "小刚", 95, "小红", 80]

# 获取分数
ZSCORE leaderboard "小明"     # → 100

# 增加分数
ZINCRBY leaderboard 10 "小明" # 小明 +10 分 → 110

# 排名(从 0 开始)
ZRANK leaderboard "小明"      # 排名第几(升序排位)
ZREVRANK leaderboard "小明"   # 排名第几(降序排位 ≈ 排行榜)
// JS 没有内置有序集合,实现类似功能需要:
const leaderboard = [
    { name: '小明', score: 100 },
    { name: '小红', score: 80 },
    { name: '小刚', score: 95 },
];
leaderboard.sort((a, b) => b.score - a.score);
// 每次都要全排序,Redis Zset 是 O(log N)

适用场景:排行榜、延时队列(用时间戳做 score)、点赞排序、商品评分


速查表

操作RedisJS 类比复杂度
存单个值SET key valmap.set(key, val)O(1)
取单个值GET keymap.get(key)O(1)
队列入队RPUSH list elarr.push(el)O(1)
队列出队LPOP listarr.shift()O(1)
存对象HSET obj key valmap.set(key, val)O(1)
集合添加SADD set elset.add(el)O(1)
集合判断SISMEMBER set elset.has(el)O(1)
有序集合加ZADD zset score mem无原生O(log N)
排行榜ZREVRANGE zset 0 9sort + sliceO(log N+M)
设置过期EXPIRE key 60无原生O(1)
上次编辑于:
贡献者: dingyongya