redis.conf之save配置项解读

本文深入解析Redis中RDB快照机制的工作原理,包括配置解读、生成时机及后台保存流程,阐述了如何通过调整配置策略来优化RDB文件的生成频率,减轻系统压力。

配置示例:

save 900 1

save 300 10

save 60 3600

 

配置解读:

1) “save 900 1”表示如果900内至少1个key发生变化(新增、修改和删除),则重写rdb文件;

2) “save 300 10”表示如果每300内至少10个key发生变化(新增、修改和删除),则重写rdb文件;

3) “save 60 3600”表示如果每60内至少10000个key发生变化(新增、修改和删除),则重写rdb文件。

 

作用:

控制什么时候生成rdb文件(快照,也可叫Checkpoint,即检查点)。

 

进程启动的时候,会将每一行save读进到类型为struct saveparam的数组中。这个没有排序,依在redis.conf中的先后顺序。在检查时,只要满足就不会再检查下一条规则。

 

配置策略:

如果同时开启了aof,则可考虑将save的参数调大一点,以减少写rdb带来的压力。实际上如果开启了aof,redis在启动时只会读取aof文件,而不会读取rdb文件:

// Function called at startup to load RDB or AOF file in memory.

void loadDataFromDisk(void) {    

    if (server.aof_state == AOF_ON) {      

        // 允许空的aof文件,

        // 如果读取aof文件出错,则调用exit(1)直接退出进程

        if (loadAppendOnlyFile(server.aof_filename) == C_OK)

            serverLog(LL_NOTICE,"DB loaded from append only file: %.3f seconds",(float)(ustime()-start)/1000000);

    } else {

         if (rdbLoad(server.rdb_filename,&rsi) == C_OK) {

    }

}

 

// #define AOF_OFF 0             /* AOF is off */

// #define AOF_ON 1              /* AOF is on */

void loadServerConfigFromString(char *config) {

    。。。。。。

    } else if (!strcasecmp(argv[0],"appendonly") && argc == 2) {

        int yes;

        if ((yes = yesnotoi(argv[1])) == -1) {

            err = "argument must be 'yes' or 'no'"; goto loaderr;

        }

         server.aof_state = yes ? AOF_ON : AOF_OFF;

    }

    。。。。。。

}

 

int yesnotoi(char *s) {

    if (!strcasecmp(s,"yes")) return 1;

    else if (!strcasecmp(s,"no")) return 0;

    else return -1;

}

 

调用顺序:

main()/server.c ->

aeMain()/ae.c -> while (!stop) { aeProcessEvents()/ae.c } ->

serverCron()/server.c -> rdbSaveBackground()/server.c

 

注:

aeProcessEvents可看作是个epoll_wait调用,在Linux上实际正是epoll_wait调用,而在Solaris上则是port_getn调用。

 

相关源代码:

int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {

    。。。。。。

    // Check if a background saving or AOF rewrite in progress terminated.

    // 如果已有rdb和aof进程,检查进程是否已退出。

    // 如果已退出,则会善后处理,否则什么也不做,等待下一次循环时再次检查

    if (server.rdb_child_pid != -1 ||

        server.aof_child_pid != -1 ||

         ldbPendingChildren()) {

        int statloc;

        pid_t pid;

        if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {

            int exitcode = WEXITSTATUS(statloc);

            。。。。。。

        }

    } else {

        // If there is not a background saving/rewrite

        // in progress check if we have to save/rewrite now.

        // 按在redis.conf中定义的顺序依次遍历每一行配置项

        // 最终是否进行写rdb操作(即生成快照文件),不仅由redis.conf

        // 中的配置项决定,还要看上一次操作的结果和状态。

        for (j = 0; j < server.saveparamslen; j++) {

            struct saveparam *sp = server.saveparams+j;

            // Save if we reached the given amount of changes,

            // the given amount of seconds, and if the latest bgsave was

            // successful or if, in case of an error, at least

            // CONFIG_BGSAVE_RETRY_DELAY seconds already elapsed.

            // CONFIG_BGSAVE_RETRY_DELAY(5): Wait a few secs before trying again.

            if (server.dirty >= sp->changes &&

                server.unixtime-server.lastsave > sp->seconds &&

                (server.unixtime-server.lastbgsave_try>CONFIG_BGSAVE_RETRY_DELAY ||

                 server.lastbgsave_status == C_OK)) {

                serverLog(LL_NOTICE,"%d changes in %d seconds. Saving...",

                    sp->changes, (int)sp->seconds);

                rdbSaveInfo rsi, *rsiptr;

                rsiptr = rdbPopulateSaveInfo(&rsi);

                rdbSaveBackground(server.rdb_filename,rsiptr);

                break; // 遇到一条满足的即结束处理,因为已没有必要判断是否满足下一条配置规则

            }

        }

    }

    。。。。。。     

}

 

// rdb.c

int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) {

    。。。。。。

    server.lastbgsave_try = time(NULL);

    。。。。。。

    // 创建写rdb的子进程

    if ((childpid = fork()) == 0) {

        redisSetProcTitle("redis-rdb-bgsave");

        retval = rdbSave(filename,rsi);

    }

    。。。。。。

}

 

/* Save the DB on disk. Return C_ERR on error, C_OK on success. */

// rdb.c

// rdbSave调用rdbSaveRio将数据写入到rdb文件中

int rdbSave(char *filename, rdbSaveInfo *rsi) {

    。。。。。。

    // 写rdb文件

    if (rdbSaveRio(&rdb,&error,RDB_SAVE_NONE,rsi) == C_ERR) {

        errno = error;

        goto werr;

    }

    。。。。。。

    serverLog(LL_NOTICE,"DB saved on disk");

    server.dirty = 0;

    server.lastsave = time(NULL);

    server.lastbgsave_status = C_OK;

    return C_OK;

}

 

/* Produces a dump of the database in RDB format sending it to the specified

 * Redis I/O channel. On success C_OK is returned, otherwise C_ERR

 * is returned and part of the output, or all the output, can be

 * missing because of I/O errors.

 *

 * When the function returns C_ERR and if 'error' is not NULL, the

 * integer pointed by 'error' is set to the value of errno just after the I/O

 * error. */

int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) {

    for (j = 0; j < server.dbnum; j++) {

        。。。。。。

        // Iterate this DB writing every entry

        while((de = dictNext(di)) != NULL) {

            。。。。。。

            // 将一对对KV写入到rdb文件

            if (rdbSaveKeyValuePair(rdb,&key,o,expire) == -1) goto werr;            

            。。。。。。

        }

    }

    。。。。。。

werr:

    if (error) *error = errno;

    if (di) dictReleaseIterator(di);

    return C_ERR;

}

 

// 以SADD命令为例,所有写操作,均会修改dirty 的值

void saddCommand(client *c) {

    。。。。。。

    for (j = 2; j < c->argc; j++) {

        if (setTypeAdd(set,c->argv[j]->ptr)) added++;

    }

    。。。。。。

    server.dirty += added;

    addReplyLongLong(c,added);

}

 

<think>我们正在回答用户关于redis.conf配置项含义的详细解释问题。根据用户的要求,我们需要参考之前提供的引用内容,并结合Redis官方文档的常见配置项进行详细说明。同时,我们需要注意以下几点: 1. 回答结构清晰,分点解释配置项。 2. 在适当的地方添加引用标识(如[^1], [^2])。 3. 生成相关问题。 由于用户之前的问题是关于Redis配置文件的,而引用内容中提供了部分配置项的解释,我们可以结合这些引用内容以及常见的Redis配置项进行详细说明。 下面开始组织回答: ### Redis 配置文件 redis.conf 详解 Redis的配置文件`redis.conf`包含了Redis服务器的各种配置选项。以下是一些重要配置项的详细解释: #### 1. 基本设置 - **`bind`**: 指定Redis实例绑定的IP地址,默认是`127.0.0.1`(仅本地访问)。若要允许远程连接,可设置为`0.0.0.0`(绑定所有接口)或指定IP地址[^1][^2]。 示例:`bind 0.0.0.0` - **`port`**: Redis监听端口,默认为`6379`[^2]。 示例:`port 6379` - **`daemonize`**: 是否以守护进程方式运行,设置为`yes`时Redis会在后台运行[^2]。 示例:`daemonize yes` - **`pidfile`**: 当Redis以守护进程方式运行时,将进程ID写入指定文件[^2]。 示例:`pidfile /var/run/redis.pid` - **`loglevel`**: 日志记录级别,可选值:`debug`(详细日志,开发测试用)、`verbose`(较多信息)、`notice`(生产环境推荐)、`warning`(仅重要信息)[^2]。 示例:`loglevel notice` - **`logfile`**: 日志文件路径。若为空字符串则输出到标准输出[^2]。 示例:`logfile ""`(控制台输出)或`logfile /var/log/redis.log` #### 2. 持久化配置 - **`save`**: 触发RDB持久化的条件,格式为`save <seconds> <changes>`,表示在指定秒数内有指定数量的键被修改则执行快照[^2]。 示例:`save 900 1`(900秒内有1个键被修改则保存) - **`rdbcompression`**: RDB快照是否启用压缩,默认为`yes`(使用LZF算法压缩)[^2]。 示例:`rdbcompression yes` - **`dbfilename`**: RDB快照文件名[^2]。 示例:`dbfilename dump.rdb` - **`appendonly`**: 是否开启AOF持久化模式,默认为`no`[^2]。 示例:`appendonly yes` - **`appendfilename`**: AOF文件名称[^2]。 示例:`appendfilename "appendonly.aof"` #### 3. 安全与权限 - **`requirepass`**: 设置客户端连接密码(明文存储,建议配合防火墙使用)[^2]。 示例:`requirepass mypassword` - **`rename-command`**: 重命名危险命令(如`FLUSHALL`),增强安全性[^2]。 示例:`rename-command FLUSHALL ""`(禁用命令)或`rename-command FLUSHALL NEWNAME`(重命名) #### 4. 内存管理 - **`maxmemory`**: 最大内存限制(单位:字节),超出时根据`maxmemory-policy`策略处理[^2]。 示例:`maxmemory 2gb` - **`maxmemory-policy`**: 内存淘汰策略,可选值包括: - `volatile-lru`:对设置了过期时间的键使用LRU淘汰 - `allkeys-lru`:对所有键使用LRU淘汰 - `volatile-random`:随机淘汰过期键 - `noeviction`:不淘汰,返回错误(默认策略)[^2] 示例:`maxmemory-policy allkeys-lru` #### 5. 主从复制 - **`slaveof`**: 配置当前实例为从节点,并指定主节点的IP和端口[^2]。 示例:`slaveof 192.168.1.100 6379` - **`masterauth`**: 若主节点设置了密码,从节点需通过此配置项提供密码[^2]。 示例:`masterauth mymasterpassword` #### 6. 高级配置 - **`notify-keyspace-events`**: 键空间事件通知配置,用于发布订阅键事件(如键过期、删除等)[^2]。 示例:`notify-keyspace-events Ex`(启用过期事件通知) - **`protected-mode`**: 保护模式,默认`yes`(仅当未设置密码且只绑定本地时禁止外部访问)[^2]。 示例:`protected-mode yes` #### 7. 哨兵相关配置(sentinel.conf) 哨兵模式有独立的配置文件`sentinel.conf`,部分关键配置如下: - **`sentinel monitor`**: 定义监控的主节点,格式为`sentinel monitor <master-name> <ip> <port> <quorum>`,其中`quorum`为判定主节点失效的哨兵数量阈值[^3]。 示例:`sentinel monitor mymaster 127.0.0.1 6379 2` - **`sentinel down-after-milliseconds`**: 主节点响应超时时间(毫秒),超过此时间哨兵标记节点为“主观下线”[^3]。 示例:`sentinel down-after-milliseconds mymaster 5000` - **`sentinel auth-pass`**: 若主节点有密码,需配置此项[^3]。 示例:`sentinel auth-pass mymaster mypassword` - **`sentinel notification-script`**: 事件通知脚本路径,用于自定义报警(如邮件、短信)[^3]。 示例:`sentinel notification-script mymaster /path/to/script.sh` > 提示:以上配置项仅为常见选项,完整配置请参考Redis官方文档。 §§相关问题§§ 1. Redis的持久化机制(RDB和AOF)有何优缺点? 2. 如何优化Redis的内存使用效率? 3. Redis哨兵模式的工作原理是什么? </think>### Redis 配置文件 redis.conf 详解 以下是 Redis 核心配置文件的详细说明(基于 Redis 7.0 版本): #### 一、基础配置 1. **`bind`** 指定 Redis 监听的 IP 地址,默认仅本地访问: ```conf bind 127.0.0.1 # 允许远程访问需改为 0.0.0.0[^1] ``` - 多 IP 示例:`bind 192.168.1.10 10.0.0.1` 2. **`port`** 服务监听端口,默认 6379: ```conf port 6379 ``` 3. **`daemonize`** 是否以守护进程运行: ```conf daemonize yes # 生产环境建议启用[^2] ``` #### 二、持久化配置 1. **RDB 快照** ```conf save 900 1 # 900秒内至少1次修改触发快照 save 300 10 # 300秒内至少10次修改 dbfilename dump.rdb # RDB文件名 rdbcompression yes # 启用压缩 ``` - 关闭 RDB:`save ""` 2. **AOF 日志** ```conf appendonly yes # 启用AOF appendfilename "appendonly.aof" appendfsync everysec # 同步策略:everysec/always/no auto-aof-rewrite-percentage 100 # AOF文件增长100%时重写[^2] ``` #### 三、内存管理 1. **内存限制** ```conf maxmemory 2gb # 最大内存限制 maxmemory-policy allkeys-lru # 淘汰策略(LRU/LFU等) ``` 2. **过期策略** ```conf maxmemory-samples 5 # LRU/LFU采样精度 ``` #### 四、安全配置 1. **密码认证** ```conf requirepass yourpassword # 客户端访问密码[^1] ``` 2. **高危命令禁用** ```conf rename-command FLUSHDB "" # 禁用命令 rename-command CONFIG "CONFIG_MANAGER" # 重命名命令 ``` #### 五、主从复制 1. **从节点配置** ```conf slaveof 192.168.1.100 6379 # 指向主节点 masterauth masterpassword # 主节点密码[^1] slave-read-only yes # 从节点只读 ``` 2. **复制优化** ```conf repl-backlog-size 1gb # 复制积压缓冲区大小 repl-disable-tcp-nodelay no # 启用低延迟复制 ``` #### 六、高级配置 1. **慢查询日志** ```conf slowlog-log-slower-than 10000 # 超过10ms的记录 slowlog-max-len 128 # 最多保存128条 ``` 2. **事件通知** ```conf notify-keyspace-events Ex # 键过期事件通知[^3] ``` 3. **Lua 脚本** ```conf lua-time-limit 5000 # 脚本执行超时时间(ms) ``` #### 七、哨兵配置 (sentinel.conf) 1. **监控主节点** ```conf sentinel monitor mymaster 192.168.1.100 6379 2 # 2个哨兵确认故障[^3] ``` - `mymaster` 为自定义主节点名称 2. **故障检测** ```conf sentinel down-after-milliseconds mymaster 5000 # 5秒无响应视为下线 sentinel failover-timeout mymaster 60000 # 故障转移超时60秒 ``` 3. **通知脚本** ```conf sentinel notification-script mymaster /alert.sh # 事件触发脚本[^3] ``` > 完整配置参考官方文档:https://redis.io/docs/management/config/
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值