Redis 提供了多种持久化机制,用于确保数据在服务器重启或崩溃后不会丢失。主要的持久化机制有两种:RDB(Redis DataBase)和 AOF(Append Only File)。这两种机制可以单独使用,也可以结合使用,以满足不同的需求。
1. RDB 持久化
RDB 持久化通过生成数据的快照(snapshot)来保存数据库的状态。快照是 Redis 数据的二进制压缩文件。
配置 RDB
RDB 的配置可以在 redis.conf 文件中设置:
conf
# Save the DB if both the given number of seconds and the given number of
# write operations against the DB occurred.
save 900 1 # 在 900 秒(15 分钟)内至少有 1 次写操作时进行持久化
save 300 10 # 在 300 秒(5 分钟)内至少有 10 次写操作时进行持久化
save 60 10000 # 在 60 秒(1 分钟)内至少有 10000 次写操作时进行持久化
# 指定快照文件的名称
dbfilename dump.rdb
# 指定快照文件的存放路径
dir ./
手动生成 RDB
你可以通过以下 Redis 命令手动生成 RDB 快照:
SAVE:阻塞 Redis 服务器,生成快照。BGSAVE:在后台生成快照,不阻塞 Redis 服务器。
bash
redis-cli SAVE
redis-cli BGSAVE
Java 示例代码
java
import redis.clients.jedis.Jedis;
public class RedisRDBExample {
public static void main(String[] args) {
try (Jedis jedis = new Jedis("localhost")) {
// 添加一些数据
jedis.set("key1", "value1");
jedis.set("key2", "value2");
// 手动触发快照
jedis.save(); // 阻塞操作
// 或者
jedis.bgsave(); // 非阻塞操作
}
}
}
2. AOF 持久化
AOF 持久化通过将每个写操作记录到日志文件中来保存数据。AOF 文件记录了所有的写操作命令,可以通过重放这些命令恢复数据。
配置 AOF
AOF 的配置可以在 redis.conf 文件中设置:
conf
# 启用 AOF 持久化
appendonly yes
# 指定 AOF 文件的名称
appendfilename "appendonly.aof"
# AOF 的同步策略
# appendfsync always # 每次有写操作发生时都同步到 AOF 文件中(最安全,但性能最差)
# appendfsync everysec # 每秒同步一次(折中选择)
appendfsync no # 从不同步(性能最高,但可能会丢失数据)
# AOF 重写的默认设置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
重写 AOF 文件
AOF 文件会随着时间的推移而变大,为了优化性能,Redis 提供了 AOF 重写机制。
BGREWRITEAOF:在后台重写 AOF 文件。
bash
redis-cli BGREWRITEAOF
Java 示例代码
java
import redis.clients.jedis.Jedis;
public class RedisAOFExample {
public static void main(String[] args) {
try (Jedis jedis = new Jedis("localhost")) {
// 添加一些数据
jedis.set("key1", "value1");
jedis.set("key2", "value2");
// 手动触发 AOF 重写
jedis.bgrewriteaof();
}
}
}
3. RDB 与 AOF 结合使用
为了实现最佳的数据持久性和性能,Redis 允许同时启用 RDB 和 AOF。这样,您可以利用 RDB 的快速恢复特性和 AOF 的高持久性。
配置文件示例
conf
# 启用 RDB 和 AOF
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir ./
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
# 启用在加载 RDB 文件和 AOF 文件时出现冲突时优先使用 AOF
aof-use-rdb-preamble yes
4. 数据恢复
当 Redis 服务器启动时,会按照以下顺序加载数据:
- 如果 AOF 持久化启用了,会先加载 AOF 文件。
- 如果没有启用 AOF 或 AOF 文件不存在,会加载 RDB 文件。
5. 高级示例:模拟数据丢失和恢复
以下示例演示如何在 Redis 中模拟数据丢失和恢复。
发布者代码
java
import redis.clients.jedis.Jedis;
public class RedisPublisher {
public static void main(String[] args) throws InterruptedException {
try (Jedis jedis = new Jedis("localhost")) {
for (int i = 0; i < 10; i++) {
String message = "Message " + i;
System.out.println("Publishing message: " + message);
jedis.publish("news_channel", message);
Thread.sleep(1000); // 等待1秒
}
}
}
}
订阅者代码
java
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class RedisSubscriber {
public static void main(String[] args) {
try (Jedis jedis = new Jedis("localhost")) {
JedisPubSub jedisPubSub = new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
System.out.println("Received message: " + message + " from channel: " + channel);
}
};
jedis.subscribe(jedisPubSub, "news_channel");
}
}
}
持久化测试代码
java
import redis.clients.jedis.Jedis;
public class RedisPersistenceTest {
public static void main(String[] args) {
try (Jedis jedis = new Jedis("localhost")) {
// 添加数据并触发持久化
jedis.set("key1", "value1");
jedis.save(); // 手动触发 RDB 持久化
// 模拟重启 Redis 服务器后恢复数据
System.out.println("After restart, key1: " + jedis.get("key1")); // 输出 "value1"
}
}
}
6. RDB 与 AOF 的优缺点
RDB 优点
- 适合备份:RDB 文件非常适合用于备份,因为它们是压缩的二进制文件。
- 启动速度快:加载 RDB 文件比 AOF 文件快,因为 RDB 是 Redis 数据的快照。
RDB 缺点
- 数据丢失风险:在生成快照之间的数据变更不会被保存,会有数据丢失的风险。
- 性能影响:生成 RDB 快照会阻塞 Redis 服务器,可能会影响性能。
AOF 优点
- 更高的持久性:AOF 可以配置为每秒同步一次,数据丢失的风险较小。
- 可读性强:AOF 文件是 Redis 命令的日志文件,可以读取和分析。
AOF 缺点
- 文件体积大:AOF 文件比 RDB 文件大,重写机制需要额外的 CPU 资源。
- 启动速度慢:由于需要重放所有命令,加载 AOF 文件的启动速度比加载 RDB 文件慢。
通过以上示例和解释,展示了如何使用和配置 Redis 的持久化机制,包括 RDB 和 AOF,以及它们的优缺点。根据具体需求,可以选择使用 RDB、AOF 或两者结合来实现最佳的数据持久性和性能。