目录
Redis
1. 概述
Redis 简介
Redis 是一种开源的内存数据库,支持键值对(Key-Value)存储,并提供多种数据结构,如字符串、哈希、列表、集合和有序集合。它以极高的性能和丰富的功能被广泛应用于缓存、会话管理、实时数据分析等场景。
Redis 与关系型数据库对比
- 数据模型:关系型数据库(如 MySQL)使用表、行和列来存储数据,而 Redis 采用键值对(Key-Value)模型。
- 查询语言:关系型数据库使用 SQL 查询语言,而 Redis 提供了一套简单的命令集。
- 存储机制:关系型数据库的数据通常存储在磁盘上,而 Redis 的数据存储在内存中,具有极快的读写性能。
- 存储容量:关系型数据库可以存储大量数据,但 Redis 受限于服务器的内存容量。
2. 常见应用场景
- 缓存:由于 Redis 的高速读写特性,它常用于缓存数据库查询结果、网页内容等。
- 会话存储:在分布式系统中,Redis 可用于存储用户会话信息。
- 消息队列:利用 Redis 的列表和发布/订阅功能实现消息队列。
- 排行榜:使用 Redis 的有序集合(Sorted Set)实现实时更新的排行榜。
3. 持久化机制
尽管 Redis 将数据存储在内存中,但为了防止数据丢失,它提供了两种持久化机制:
- RDB(Redis Database):通过快照(snapshot)将数据定期保存到磁盘。
- AOF(Append Only File):通过将每个写操作记录到日志文件中,实现数据的持久化。
4. 哨兵(Sentinel)
Redis Sentinel 是一个用于监控和管理 Redis 高可用性的系统,它能够自动检测主节点的故障并进行切换,以确保系统的持续可用性。
哨兵的作用
- 监控(Monitoring):监控 Redis 主节点和从节点是否正常工作。
- 提醒(Notification):当 Redis 实例出现问题时,向管理员发送通知。
- 自动故障转移(Automatic Failover):在主节点故障时,自动将某个从节点提升为新的主节点。
使用 Sentinel 的好处
- 提供高可用性保障
- 自动故障恢复
- 减少人工干预
常见应用场景
-
缓存: Redis常用于缓存数据,将经常访问的数据存储在内存中,从而减轻后端数据库的压力,加速数据检索。
-
会话存储: 在Web应用中,可以使用Redis存储用户会话数据,以提供持久性和快速的用户体验。
-
排行榜和计数器: Redis的有序集合和计数器可以轻松地实现排行榜和计数功能,适用于社交媒体应用等场景。
-
发布订阅系统: Redis的发布订阅功能使得开发人员可以实现实时消息传递,适用于聊天应用、实时通知等。
5. 基本操作
常用命令
# 连接到 Redis 服务器
redis-cli
# 字符串类型
SET name "Alice" # 设置键 'name' 的值为 'Alice'
GET name # 获取键 'name' 的值
# 哈希类型
HSET user:123 username "alice123" # 设置哈希表 'user:123' 的字段 'username' 值为 'alice123'
HGET user:123 username # 获取哈希表 'user:123' 的字段 'username' 的值
# 列表类型
LPUSH tasks "task1" # 将值 'task1' 插入到列表 'tasks' 的头部
LPOP tasks # 移除并获取列表 'tasks' 的第一个元素
# 集合类型
SADD followers:123 "user1" # 将成员 'user1' 添加到集合 'followers:123'
SMEMBERS followers:123 # 获取集合 'followers:123' 中的所有成员
# 有序集合类型
ZADD highscores 100 "Alice" # 将成员 "Alice" 添加到有序集合 "highscores",分数为 100
ZRANGE highscores 0 -1 WITHSCORES # 获取有序集合 "highscores" 中的所有成员及其分数
# 设置过期时间
SET session:123 "data" EX 3600 # 设置键 "session:123" 的值为 "data",并设置过期时间为 3600 秒
TTL session:123 # 获取键 "session:123" 的剩余过期时间
# 发布订阅模式
SUBSCRIBE notifications # 订阅频道 "notifications",等待接收消息
PUBLISH notifications "New message" # 向频道 "notifications" 发布消息
# 事务
MULTI # 开始事务
SET key1 "value1" # 执行多个命令
INCR key2
EXEC # 提交事务
# 乐观锁
WATCH counter # 监视键 "counter"
GET counter # 获取键 "counter" 的值
MULTI # 开始事务
INCR counter # 将键 "counter" 的值增加 1
EXEC # 提交事务,如果期间键 "counter" 被修改,则事务失败
# 分布式锁
SETNX lock:resource "token" EX 30 NX # 尝试获取分布式锁
6. Redis API 示例
@Override
public boolean hset(final String key, final String field, final String val) {
return redisTemplate.execute(connection -> {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
byte[] keyBytes = serializer.serialize(key);
byte[] fieldBytes = serializer.serialize(field);
byte[] valBytes = serializer.serialize(val);
connection.hSet(keyBytes, fieldBytes, valBytes);
return true;
});
}
@Override
public String hget(final String key, final String field) {
return redisTemplate.execute(connection -> {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
byte[] keyBytes = serializer.serialize(key);
byte[] fieldBytes = serializer.serialize(field);
byte[] res = connection.hGet(keyBytes, fieldBytes);
return serializer.deserialize(res);
});
}
@Override
public void batchHset(final String key, final Map<String, String> fieldValMap) {
redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
byte[] keyBytes = serializer.serialize(key);
fieldValMap.forEach((field, val) -> {
byte[] fieldBytes = serializer.serialize(field);
byte[] valBytes = serializer.serialize(val);
connection.hSet(keyBytes, fieldBytes, valBytes);
});
return null;
});
}
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Data Redis Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Jedis Redis Client -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- Add other dependencies as needed -->
</dependencies>