苍穹外卖-DAY05

一、redis

  • 基于内存存储数据,读写性能高

image-20260203164720160

1.redis数据结构

  • key只能为String

value的数据类型多样

数据结构 核心特点 常用命令 最佳应用场景
String 简单的 Key-Value SET, GET, INCR 缓存、计数器、分布式锁
Hash 键值对集合 HSET, HGET, HMGET 用户资料、对象存储
List 双向链表 LPUSH, RPOP, LRANGE 简单队列、时间轴
Set 无序去重集合 SADD, SMEMBERS, SINTER 标签、共同好友、黑白名单
ZSet 有序去重集合 ZADD, ZRANGE, ZRANK 排行榜、带权重队列

2.字符串操作

基础读写操作 (CRUD)

  • SET key value
    • 含义: 设置指定 key 的值。如果 key 已经存在,会覆盖旧值。
    • 示例: SET name "Gemini" -> OK
  • GET key
    • 含义: 获取指定 key 的值。
    • 示例: GET name -> “Gemini”
  • SETEX key seconds value

    • 含义: SET + EXPIRE 的组合原子操作。设置值的同时,设置过期时间(单位:秒)。

    • 场景: 缓存。比如存储验证码,5分钟后自动过期失效。

    • 示例: SETEX code 300 "123456" (设置 code 为 123456,300秒后自动删除)

  • SETNX key value

    • 含义: SET if Not eXists(如果不存在,则设置)。

    • 如果 key 不存在,设置成功,返回 1。

    • 如果 key 已存在,什么都不做,返回 0。

    • 场景: 分布式锁的基石。多个客户端同时抢占一个资源,谁执行 SETNX 成功(返回1),谁就抢到了锁。

    • 示例: SETNX lock_product_101 "true"

3.哈希操作

  • HSET key field value
    • 含义: 给 key 中的 field 字段赋值。如果 key 不存在会自动创建。
    • 示例: HSET user:1 name "Tom" (Redis 4.0+ 后,HSET 也支持一次设置多个字段)
  • HGET key field
    • 含义: 获取 key 中指定 field 的值。
    • 示例: HGET user:1 name -> “Tom”
  • HDEL key field

    • 含义: 删除 key 中的一个或多个 field。

    • 示例: HDEL user:1 age

  • HKEYS key / HVALS key

    • 含义: 只获取所有的字段名 / 只获取所有的值。

4.列表操作

A. 进(添加元素)

  • LPUSH key value ...
    • 含义:左边(头部)推入元素。
    • 示例: LPUSH numbers 1 2 3 -> 列表变成 [3, 2, 1] (因为 1 先进,3 最后进,插在最头)。
  • RPUSH key value ...
    • 含义:右边(尾部)推入元素。
    • 示例: RPUSH names "A" "B" -> 列表变成 ["A", "B"]

B. 出(弹出元素)

  • LPOP key
    • 含义:左边弹出一个元素(移除并返回)。
  • RPOP key
    • 含义:右边弹出一个元素。
  • BLPOP key timeout / BRPOP key timeout (重要!)
    • 含义: 阻塞式弹出。
    • 场景: 如果 List 是空的,普通的 LPOP 会直接返回 null。但 BLPOP一直在这个连接上等待,直到 List 里有新数据进来,或者超时。这是做消息队列的神器。

C. 查(范围查看)

  • LRANGE key start stop (最常用)
    • 含义: 获取指定范围内的元素。
    • 技巧: 0 代表第一个元素,-1 代表最后一个元素。
    • 查看所有: LRANGE mylist 0 -1
  • LLEN key
    • 含义: 获取列表长度。

5.集合操作

  • SADD key member ...

    • 含义: 向集合添加一个或多个元素。如果元素已存在,则忽略。
    • 返回值: 成功添加的新元素个数(不包含已存在的)。
    • 示例: SADD tags:python "web" "crawler" "ai"
  • SREM key member ...

    • 含义: 移除集合中的元素。
    • 示例: SREM tags:python "ai"
  • SMEMBERS key

    • 含义: 返回集合中的所有元素。
    • 注意: 如果集合很大,这个命令会阻塞 Redis,生产环境建议用 SSCAN 迭代获取。
  • SCARD key

    • 含义: 获取集合的成员总数 (Set CARDinality)。
  • SINTER key1 key2 ...

    • 含义: 找出两个集合都有的元素。
    • 场景: “共同好友”“共同关注”
    • 示例: SINTER A B -> {"Apple", "OpenAI"}
  • SUNION key1 key2 ...

    • 含义: 把两个集合合并,自动去重。
    • 场景: “可能认识的人”(把我的好友的好友全部聚合起来)。
    • 示例: SUNION A B -> {"Google", "Apple", "OpenAI", "Microsoft"}
  • SDIFF key1 key2

    • 含义: 返回在 key1 中有,但在 key2 中没有的元素 (key1 - key2)。注意顺序!
    • 场景: “推荐关注”(B 关注了但 A 没关注的人)。
    • 示例: SDIFF B A -> {"Microsoft"} (因为 Microsoft 在 B 里,且不在 A 里)

6.有序集合

A. 增与改 (Add & Update)

  • ZADD key score member ...

    • 含义: 添加元素并设置分数。如果元素已存在,则更新其分数并重新排序。
    • 示例: ZADD leaderboard 100 "Alex" 90 "Bob" 95 "Cindy"
    • 注意:Redis 内部自动排好了序:Bob(90) < Cindy(95) < Alex(100)
  • ZINCRBY key increment member (神器)

    • 含义: 给指定成员的分数加上增量。
    • 场景: 用户点了一个赞,文章热度 +1。
    • 示例: ZINCRBY leaderboard 2 "Bob" -> Bob 的分变成了 92。
  • ZRANGE key start stop [WITHSCORES]

    • 含义: 按照分数从小到大返回指定索引区间的成员。
    • 示例: ZRANGE leaderboard 0 -1 -> 1) “Bob” 2) “Cindy” 3) “Alex” (这是倒数排名)
  • ZREM key member

    • 含义: 删除指定成员。

7.通用

类别 命令 描述 关键点 / 安全警示
查询 KEYS * 查所有 Key ⚠️ 生产环境禁用,会导致服务卡死
SCAN 游标遍历 安全的 KEYS 替代方案
TYPE 查看类型 操作前确认类型,防报错
过期 EXPIRE 设置倒计时 缓存系统的核心
TTL 看剩余时间 -1: 永久, -2: 不存在
删除 DEL 同步删除 删小数据
UNLINK 异步删除 删大数据 (Big Key) 推荐
系统 SELECT 切库 默认 0 号库
FLUSHALL 删光所有库 ⚠️ 极其危险

二、java中的redis

javaredis操作

image-20260203190506835

1.sping Data Redis操作

实现步骤

image-20260203190650943
1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
@Slf4j
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
log.info("Initializing RedisTemplate bean");
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}

2.具体操作

opsForValue() —— 操作 String (字符串)

这是最常用的,对应 RedisString 结构。虽然名字叫 Value,但它不仅能存字符串,也能存序列化后的对象。

  • 对应 Redis 命令: SET, GET, INCR, SETEX 等。
  • 代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Autowired
private RedisTemplate<String, Object> redisTemplate;

public void testString() {
// 1. 设置值 (SET city "Beijing")
redisTemplate.opsForValue().set("city", "Beijing");

// 2. 设置值并带过期时间 (SETEX code 60 "1234")
redisTemplate.opsForValue().set("code", "1234", 60, TimeUnit.SECONDS);

// 3. 获取值 (GET city)
String city = (String) redisTemplate.opsForValue().get("city");

// 4. 自增 (INCR count)
redisTemplate.opsForValue().increment("count");
}

opsForHash() —— 操作 Hash (哈希)

对应 RedisHash 结构。适合存储对象(如用户信息)。

  • 对应 Redis 命令: HSET, HGET, HMGET, HKEY, HVALS 等。
  • 代码示例:
1
2
3
4
5
6
7
8
9
10
11
public void testHash() {
// 1. 存入 Hash 的某个字段 (HSET user:1 name "Alex")
redisTemplate.opsForHash().put("user:1", "name", "Alex");
redisTemplate.opsForHash().put("user:1", "age", 18);

// 2. 获取 Hash 的某个字段 (HGET user:1 name)
String name = (String) redisTemplate.opsForHash().get("user:1", "name");

// 3. 获取 Hash 的所有字段和值 (HGETALL user:1)
Map<Object, Object> entries = redisTemplate.opsForHash().entries("user:1");
}

opsForList() —— 操作 List (列表)

对应 RedisList 结构(双向链表)。

  • 对应 Redis 命令: LPUSH, RPUSH, LPOP, LRANGE 等。
  • 代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
public void testList() {
// 1. 从左边推入 (LPUSH history "a" "b")
redisTemplate.opsForList().leftPushAll("history", "a", "b");

// 2. 从右边推入 (RPUSH history "c")
redisTemplate.opsForList().rightPush("history", "c");

// 3. 获取范围 (LRANGE history 0 -1)
List<Object> list = redisTemplate.opsForList().range("history", 0, -1);

// 4. 从左边弹出 (LPOP history)
Object pop = redisTemplate.opsForList().leftPop("history");
}

opsForSet() —— 操作 Set (集合)

对应 RedisSet 结构(无序去重)。

  • 对应 Redis 命令: SADD, SMEMBERS, SISMEMBER, SINTER 等。
  • 代码示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
public void testSet() {
// 1. 添加元素 (SADD tags "java" "redis")
redisTemplate.opsForSet().add("tags", "java", "redis");

// 2. 判断是否存在 (SISMEMBER tags "python")
Boolean isMember = redisTemplate.opsForSet().isMember("tags", "python");

// 3. 获取所有元素 (SMEMBERS tags)
Set<Object> members = redisTemplate.opsForSet().members("tags");

// 4. 求两个集合的交集 (SINTER set1 set2)
Set<Object> intersect = redisTemplate.opsForSet().intersect("set1", "set2");
}

opsForZSet() —— 操作 ZSet (有序集合)

对应 RedisZSet 结构(带分数的排序集合)。

  • 对应 Redis 命令: ZADD, ZRANGE, ZINCRBY 等。
  • 代码示例:
1
2
3
4
5
6
7
8
9
10
11
public void testZSet() {
// 1. 添加元素带分数 (ZADD rank 100 "Alex")
redisTemplate.opsForZSet().add("rank", "Alex", 100);

// 2. 加分 (ZINCRBY rank 10 "Alex")
redisTemplate.opsForZSet().incrementScore("rank", "Alex", 10.0);

// 3. 获取前 10 名 (ZRANGE rank 0 9) - 注意:这里默认是从小到大
// 如果要排行榜(从大到小),用 reverseRange
Set<Object> top10 = redisTemplate.opsForZSet().reverseRange("rank", 0, 9);
}