外观
Redis基础 学习笔记
Redis 是基于内存的键值型 NoSQL 数据库,本笔记复习常用数据类型、常用命令与 Java 操作三块内容。
1. Redis常用数据类型
- 核心概念:Redis 命令执行是单线程模型(多线程仅用于网络 IO 与持久化),所有命令原子执行;key 是字符串,value 有五种基本类型。
- 五种类型速查:
- String:可存字符串、数字、JSON 序列化结果,最通用
- Hash:字段集合,适合存对象(只改某个字段)
- List:双向链表,适合消息队列、最新列表
- Set:无序去重,适合交集/并集/差集运算
- ZSet:带 score 的有序去重集合,适合排行榜
- 易错点:ZSet 去重看 member 而非 score,score 相同按字典序排;key 命名习惯用"业务:对象:id"(如
user:1001),避免无意义短 key。
bash
# String
SET user:1001 "zhangsan"
GET user:1001
# Hash(对象)
HSET user:1001 name zhangsan age 18
HGET user:1001 name
# List(队列)
LPUSH msg:queue "hello"
LRANGE msg:queue 0 -1
# Set(集合运算)
SADD tags:java "redis" "spring"
SINTER tags:java tags:python
# ZSet(排行榜)
ZADD rank:game 100 "playerA"
ZRANGE rank:game 0 -1 WITHSCORES2. Redis常用命令
- 通用命令:
EXISTS、DEL、TYPE、EXPIRE/TTL;遍历 key 用SCAN,生产环境禁用KEYS(会阻塞)。 - 过期与持久化:
EXPIRE key seconds设置过期;持久化有 RDB(快照)与 AOF(追加日志),AOF 更安全、RDB 恢复更快。 - 事务:
MULTI/EXEC/DISCARD只是把命令依次排队执行,某条出错不回滚,与关系型数据库事务不同。 - 易错点:
TTL返回 -1 表示永不过期,-2 才表示 key 不存在,两者别混淆;计数用INCR(原子),不要"读-改-写"。
bash
# 过期时间
SET code "123456" EX 120 # 120 秒后自动删除
TTL code # -1 永不过期 / -2 不存在
EXPIRE code 60 # 给已有 key 设过期
# 原子计数
INCR visit:count
INCRBY visit:count 5
# 事务(无回滚)
MULTI
SET a 1
INCR a
EXEC
# 增量遍历,避免 KEYS 阻塞
SCAN 0 MATCH user:* COUNT 1003. JAVA中操作Redis
- 客户端选型:Jedis(简单)、Lettuce(Spring Boot 默认)、Redisson(分布式锁等高级特性)。
- Spring Boot 集成:引入
spring-boot-starter-data-redis,注入StringRedisTemplate(纯字符串)或RedisTemplate。 - 序列化:
RedisTemplate默认 JDK 序列化会存乱码,key 用StringRedisSerializer,value 常用 JSON 序列化。 - API 对应关系:
opsForValue()(String)、opsForHash()、opsForList()、opsForSet()、opsForZSet()对应五种类型。 - 易错点:
StringRedisTemplate与RedisTemplate序列化方式不同,混用会读不到数据;set带过期时间的参数顺序是(key, value, timeout, unit)。
java
// 配置序列化,避免 key/value 乱码
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}java
@Autowired
private StringRedisTemplate redisTemplate;
// 带过期时间的读写
redisTemplate.opsForValue().set("name", "zhangsan", 60, TimeUnit.SECONDS);
String name = redisTemplate.opsForValue().get("name");
// Hash 操作
redisTemplate.opsForHash().put("user:1001", "age", "18");
Object age = redisTemplate.opsForHash().get("user:1001", "age");
// Redisson 分布式锁
RLock lock = redissonClient.getLock("order:lock");
lock.lock(10, TimeUnit.SECONDS);
try {
// 业务逻辑
} finally {
lock.unlock();
}