邵阳营销型网站建设网页游戏排行力荐新壹玩

web/2025/10/4 13:46:02/文章来源:
邵阳营销型网站建设,网页游戏排行力荐新壹玩,wordpress 说说 插件,php制作投票网站前言 Redis 的 RDB 持久化机制简单直接#xff0c;把某一时刻的所有键值对以二进制的方式写入到磁盘#xff0c;特点是恢复速度快#xff0c;尤其适合数据备份、主从复制场景。但如果你的目的是要保证数据可靠性#xff0c;RDB 就不太适合了#xff0c;因为 RDB 持久化不…前言 Redis 的 RDB 持久化机制简单直接把某一时刻的所有键值对以二进制的方式写入到磁盘特点是恢复速度快尤其适合数据备份、主从复制场景。但如果你的目的是要保证数据可靠性RDB 就不太适合了因为 RDB 持久化不宜频繁触发如果 Redis 触发 RDB 后又有新的数据写入且还没来得及触发下一次 RDB 就宕机了中间的数据就会丢失。 在这种场景下我们就急需一种增量备份的方式只记录上一次 RDB 到现在为止所有的变更记录就好了相较于全量备份增量备份的数据量就小得多了。所以Redis 还提供了 AOF 持久化机制。 特性RDBAOF文件格式二进制文本内存效率高较低恢复速度快慢文件大小小大运行效率高低 Redis 会把服务端执行的所有写命令以 RESP 协议的方式追加到 AOF 日志文件中数据恢复时只要读取 AOF 文件重放所有的日志即可。 开启AOF 开启 AOF 你需要关心下面几个参数 appendonly yes #开启AOF appendfilename appendonly.aof #AOF文件名#AOF文件刷盘策略 appendfsync always # appendfsync everysec # appendfsync no#AOF触发机制 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb#是否开启RDB前导 混合持久化 aof-use-rdb-preamble yesappendfsync 配置 AOF 文件刷盘策略 always每个写命令执行完都立即同步到磁盘可靠性高、效率低everysecAOF 日志先写入内存缓冲区再由定时任务每秒刷一次盘noAOF 日志只写入操作系统文件缓存由操作系统决定刷盘时机 建议设置为 everysec兼顾性能和可靠性最多丢失一秒的数据always 虽然足够可靠但是会严重拉低性能no 会让 AOF 文件刷盘的时机脱离 Redis 的控制并不推荐。 开启 AOF 不代表就可以高枕无忧了因为 AOF 是日志追加的形式意味着随着不断运行AOF 日志会越来越大。AOF 日志文件膨胀会带来两个问题 AOF 文件大小超过文件系统的限制会发生错误AOF 文件太大会影响数据恢复效率 所以Redis 会对 AOF 文件重写你可以通过bgrewriteaof命令手动触发重写也可以配置当条件满足时自动触发重写。 auto-aof-rewrite-percentageAOF 文件的增长比例默认增长为原来的一倍大小就开始重写auto-aof-rewrite-min-size允许 AOF 重写的文件最小值 为什么重写可以缩小 AOF 文件呢因为可以把多条命令合并成一条命令AOF 只需要记录 Key 最新的 Value 即可而不用记录修改的历史记录。 最后是aof-use-rdb-preamble参数它是 Redis4 才开始支持的混合持久化机制开启后 AOF 重写时将会在 AOF 文件的前半部分先写入全量的 RDB 数据再把增量 AOF 日志追加在后半部分同时兼顾了性能和可靠性建议开启。 AOF机制 先测试下开启 AOF 后我们写入数据 127.0.0.1:6379 set name Jackson OK 127.0.0.1:6379 lpush names Lisa (integer) 1 127.0.0.1:6379 lpush names Tom (integer) 2因为 AOF 文件是文本形式的所以我们可以直接查看。AOF 日志是按照 RESP 协议写入的所以你需要先了解一下 RESP 协议这个协议很简单。如下 *代表数组后面跟着数组长度$代表字符串后面跟着长度 我们来解读一下这段日志首先是SELECT 0代表后续操作的是 0 号数据库紧接着就是各个命令和对应的参数了。 *2 $6 SELECT $1 0 *3 $3 set $4 name $7 Jackson *3 $5 lpush $5 names $4 Lisa *3 $5 lpush $5 names $3 Tom注意读命令不会对数据有影响是不会记录到 AOF 文件的。 此时我们执行bgrewriteaof命令重写 AOF 文件再次查看发现 AOF 文件确实变小了两次lpush合并为一次RPUSH了。 *2 $6 SELECT $1 0 *3 $3 SET $4 name $7 Jackson *4 $5 RPUSH $5 names $3 Tom $4 Lisa如果开启了混合持久化我们再执行bgrewriteaof命令重写 AOF 文件会发现 AOF 文件不可读了因为此时里面的内容是二进制的 RDB 数据。 REDIS0009 redis-ver6.2.13 redis-bitsctime·eused-memaof-preamblenameJacksonnamesTomLisaO{v*2再执行写命令 127.0.0.1:6379 del name (integer) 1再查看 AOF 文件会发现前半段是不可读的 RDB 数据后半段是可读的 AOF 日志这就是混合持久化。 REDIS0009 redis-ver6.2.13 redis-bitsctime·eused-memaof-preamblenameJacksonnamesTomLisaO{v*2 $6 SELECT $1 0 *2 $3 del $4 nameAOF流程 Redis 服务端在执行完写命令后还会有一套命令传播机制用于追加 AOF 日志和主从数据复制。命令被传播到 AOF 后会Redis 会根据命令生成对应的 RESP 协议的文本字符串然后追加到缓冲区最后根据刷盘策略来把缓冲区的日志刷新到磁盘。 源码中Redis 在处理命令时如果开启了 AOF 或有主从数据复制命令就需要传播此时会调用propagate() if (propagate_flags ! PROPAGATE_NONE !(c-cmd-flags CMD_MODULE))propagate(c-cmd,c-db-id,c-argv,c-argc,propagate_flags);传播命令时会进一步调用feedAppendOnlyFile()来追加 AOF 日志 void propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,int flags) {// AOF开启 要追加AOF日志if (server.aof_state ! AOF_OFF flags PROPAGATE_AOF)feedAppendOnlyFile(cmd,dbid,argv,argc);if (flags PROPAGATE_REPL)replicationFeedSlaves(server.slaves,dbid,argv,argc); }有了写命令怎么生成 AOF 日志呢是把命令直接记录下来吗 当然不是Redis 会把写命令按照 RESP 协议的方式序列化成文本再记录。其次记录 AOF 日志是一个非常频繁的操作如果每次都直接写文件会严重影响 Redis 性能。所以Redis 会先写到 sds 缓冲区里变量是aof_buf。 void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc) {// 命令用sds承载sds buf sdsempty();// 命令操作的数据库和上次数据库不同此时要先写入一个SELECT命令if (dictid ! server.aof_selected_db) {char seldb[64];snprintf(seldb,sizeof(seldb),%d,dictid);buf sdscatprintf(buf,*2\r\n$6\r\nSELECT\r\n$%lu\r\n%s\r\n,(unsigned long)strlen(seldb),seldb);server.aof_selected_db dictid;}// 再根据命令生成AOF日志if (cmd-proc expireCommand || cmd-proc pexpireCommand ||cmd-proc expireatCommand) {/* Translate EXPIRE/PEXPIRE/EXPIREAT into PEXPIREAT */buf catAppendOnlyExpireAtCommand(buf,cmd,argv[1],argv[2]);}......// 追加到AOF缓冲区if (server.aof_state AOF_ON)server.aof_buf sdscatlen(server.aof_buf,buf,sdslen(buf));// 如果有AOF子进程在重写还要把增量部分追加到AOF重写缓冲区if (server.child_type CHILD_TYPE_AOF)aofRewriteBufferAppend((unsigned char*)buf,sdslen(buf));// 释放sdsfree(buf); }光写到内存缓冲区是不安全的如果宕机数据就丢了。所以接下来还会调用flushAppendOnlyFile()来根据同步策略把缓冲区的日志同步到磁盘。 void flushAppendOnlyFile(int force) {ssize_t nwritten;int sync_in_progress 0;mstime_t latency;if (sdslen(server.aof_buf) 0) {// 即使缓冲区是空的也要判断是否要刷盘因为之前可能只是写入文件系统缓存if (server.aof_fsync AOF_FSYNC_EVERYSEC server.aof_fsync_offset ! server.aof_current_size server.unixtime server.aof_last_fsync !(sync_in_progress aofFsyncInProgress())) {goto try_fsync;} else {return;}}// 每秒刷盘 判断是否在处理中if (server.aof_fsync AOF_FSYNC_EVERYSEC)sync_in_progress aofFsyncInProgress();// 每秒刷盘 且不强制刷盘if (server.aof_fsync AOF_FSYNC_EVERYSEC !force) {if (sync_in_progress) {if (server.aof_flush_postponed_start 0) {// 记录延迟刷盘的开始时间server.aof_flush_postponed_start server.unixtime;return;} else if (server.unixtime - server.aof_flush_postponed_start 2) {// 延迟刷盘时间没超过2秒 也会跳过return;}server.aof_delayed_fsync;serverLog(LL_NOTICE,Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.);}}// AOF缓冲区写入到文件latencyStartMonitor(latency);nwritten aofWrite(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));latencyEndMonitor(latency);// 写入字节数不等于缓冲区大小 写入异常的处理if (nwritten ! (ssize_t)sdslen(server.aof_buf)) {......} else {// 写入成功if (server.aof_last_write_status C_ERR) {serverLog(LL_WARNING,AOF write error looks solved, Redis can write again.);server.aof_last_write_status C_OK;}}server.aof_current_size nwritten;// 缓冲区小于4K就重用否则释放申请新的if ((sdslen(server.aof_buf)sdsavail(server.aof_buf)) 4000) {sdsclear(server.aof_buf);} else {sdsfree(server.aof_buf);server.aof_buf sdsempty();}try_fsync: // 尝试刷盘if (server.aof_no_fsync_on_rewrite hasActiveChildProcess())return;if (server.aof_fsync AOF_FSYNC_ALWAYS) {// 每次都刷盘// 刷盘if (redis_fsync(server.aof_fd) -1) {serverLog(LL_WARNING,Cant persist AOF for fsync error when the AOF fsync policy is always: %s. Exiting..., strerror(errno));exit(1);}latencyEndMonitor(latency);latencyAddSampleIfNeeded(aof-fsync-always,latency);server.aof_fsync_offset server.aof_current_size;server.aof_last_fsync server.unixtime;} else if ((server.aof_fsync AOF_FSYNC_EVERYSEC server.unixtime server.aof_last_fsync)) {// 每秒刷盘 且时间已到if (!sync_in_progress) {aof_background_fsync(server.aof_fd);server.aof_fsync_offset server.aof_current_size;}server.aof_last_fsync server.unixtime;} }AOF重写 随着运行AOF 文件会不断膨胀AOF 文件过大会影响数据恢复效率所以 Redis 会不时的重写 AOF 文件。 AOF 重写触发的时机主要有两种 手动执行bgrewriteaof命令AOF 文件增长超过阈值由定时任务自动触发 AOF 重写不关心键值对的历史修改记录只需要记录最新的值即可所以重写后它几乎总是会更小。但是 AOF 重写会面临两个问题 AOF 重写要遍历数据库且需要写磁盘文件会导致阻塞如果无法容忍阻塞异步写的话期间发生的数据变更怎么办? Redis 给出的解决方案是一次拷贝、两处日志。 一次拷贝fork 子进程时需要拷贝父进程的页表日志一AOF 日志缓冲区正常写哪怕 AOF 重写失败也不影响现有日志文件日志二再多写一份 AOF 重写缓冲区日志用来发送给子进程追加到重写后的 AOF 文件 Redis 在 AOF 重写时首先会创建三个管道用于和子进程发送增量日志和ACK然后 fork 子进程子进程开始遍历数据库生成新的 AOF 文件同时主进程在执行写命令时会把 AOF 日志同时追加到 AOF 缓冲区和 AOF 重写缓冲区再通过管道把增量日志发送给子进程子进程重写好 AOF 日志后再把接收到的父进程发送过来的增量日志也一并追加到新的 AOF 文件子进程退出父进程把最后剩余的增量日志追加到新的 AOF 文件然后替换旧文件AOF 重写完成。 为什么还要用到 Linux 管道 如果不用管道子进程在 AOF 重写期间父进程会积压很多增量日志子进程重写完成后父进程要把这些增量日志追加到新的 AOF 文件后才算重写完成这势必会发生阻塞。 有了管道父进程可以实时的把增量日志发送给子进程由子进程把增量日志追加到重写后的 AOF 文件里这样就不会阻塞父进程。最终父进程只需要把最后一点点剩余的增量日志追加到新的 AOF 文件即可这个阻塞时间就可以忽略不计了归根结底是为了避免阻塞父进程。 一起看下 AOF 重写的源码吧bgrewriteaofCommand()方法用来处理bgrewriteaof命令 如果 AOF 已经在重写这里直接跳过如果在执行 RDB 持久化AOF 也要等待稍后被调度执行 void bgrewriteaofCommand(client *c) {if (server.child_type CHILD_TYPE_AOF) {// AOF重写子进程处理中addReplyError(c,Background append only file rewriting already in progress);} else if (hasActiveChildProcess()) {// AOF和RDB子进程不能同时进行此时把AOF重写任务设为等待调度执行由定时任务触发server.aof_rewrite_scheduled 1;addReplyStatus(c,Background append only file rewriting scheduled);} else if (rewriteAppendOnlyFileBackground() C_OK) {// AOF子进程开始启动addReplyStatus(c,Background append only file rewriting started);} }rewriteAppendOnlyFileBackground()会在后台 fork 一个子进程来处理 AOF 重写 创建管道fork AOF 子进程根据进程 ID 生成临时文件AOF重写到临时文件 int rewriteAppendOnlyFileBackground(void) {pid_t childpid;// RDB子进程在工作返回错误if (hasActiveChildProcess()) return C_ERR;// 创建三个管道 用于父子进程通信if (aofCreatePipes() ! C_OK) return C_ERR;// fork子进程if ((childpid redisFork(CHILD_TYPE_AOF)) 0) {// 子进程char tmpfile[256];redisSetProcTitle(redis-aof-rewrite);redisSetCpuAffinity(server.aof_rewrite_cpulist);// 进程ID生成临时文件snprintf(tmpfile,256,temp-rewriteaof-bg-%d.aof, (int) getpid());// AOF重写到临时文件if (rewriteAppendOnlyFile(tmpfile) C_OK) {sendChildCowInfo(CHILD_INFO_TYPE_AOF_COW_SIZE, AOF rewrite);exitFromChild(0);} else {exitFromChild(1);}} else {// 父进程if (childpid -1) {serverLog(LL_WARNING,Cant rewrite append only file in background: fork: %s,strerror(errno));aofClosePipes();return C_ERR;}serverLog(LL_NOTICE,Background append only file rewriting started by pid %ld,(long) childpid);server.aof_rewrite_scheduled 0;server.aof_rewrite_time_start time(NULL);server.aof_selected_db -1;replicationScriptCacheFlush();return C_OK;}return C_OK; /* unreached */ }父进程首先会调用aofCreatePipes()创建三个管道用于后续和子进程传输数据 pipe1父给子传输增量日志的管道pipe2子给父发送 ACK 的管道让父进程停止发送增量日志自己已经重写完要退出了pipe3父给子发送 ACK 的管道 int aofCreatePipes(void) {int fds[6] {-1, -1, -1, -1, -1, -1};int j;// 创建三个管道if (pipe(fds) -1) goto error; // 父子进程数据传输管道 传输重写期间的增量AOF日志if (pipe(fds2) -1) goto error; // 子父进程ACK管道if (pipe(fds4) -1) goto error; // 父子进程ACK管道// 父子进程的数据传输管道设为非阻塞if (anetNonBlock(NULL,fds[0]) ! ANET_OK) goto error;if (anetNonBlock(NULL,fds[1]) ! ANET_OK) goto error;// 注册可读事件监听子进程重写完成会发送ACK父进程停止发送增量AOF日志if (aeCreateFileEvent(server.el, fds[2], AE_READABLE, aofChildPipeReadable, NULL) AE_ERR) goto error;server.aof_pipe_write_data_to_child fds[1];server.aof_pipe_read_data_from_parent fds[0];server.aof_pipe_write_ack_to_parent fds[3];server.aof_pipe_read_ack_from_child fds[2];server.aof_pipe_write_ack_to_child fds[5];server.aof_pipe_read_ack_from_parent fds[4];server.aof_stop_sending_diff 0;return C_OK; error:serverLog(LL_WARNING,Error opening /setting AOF rewrite IPC pipes: %s,strerror(errno));for (j 0; j 6; j) if(fds[j] ! -1) close(fds[j]);return C_ERR; }管道创建完开始重写rewriteAppendOnlyFile()会先打开临时文件然后判断是否开启混合持久化模式来选择是写 RDB 数据还是 AOF 日志 if (server.aof_use_rdb_preamble) {int error;// RDB二进制全量写入if (rdbSaveRio(aof,error,RDBFLAGS_AOF_PREAMBLE,NULL) C_ERR) {errno error;goto werr;} } else {// 仅使用AOF日志if (rewriteAppendOnlyFileRio(aof) C_ERR) goto werr; }rewriteAppendOnlyFileRio()是仅写 AOF 日志和 RDB 类似也是遍历数据库再遍历键值对生成对应的 AOF 日志写入文件。 int rewriteAppendOnlyFileRio(rio *aof) {dictIterator *di NULL;dictEntry *de;size_t processed 0;int j;long key_count 0;long long updated_time 0;// 遍历数据库for (j 0; j server.dbnum; j) {// 选择数据库的命令char selectcmd[] *2\r\n$6\r\nSELECT\r\n;redisDb *db server.dbj;dict *d db-dict;if (dictSize(d) 0) continue; // 数据库空的,则跳过// 获取哈希表迭代器di dictGetSafeIterator(d);// 写入选择数据库的命令 例如:*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\nif (rioWrite(aof,selectcmd,sizeof(selectcmd)-1) 0) goto werr;if (rioWriteBulkLongLong(aof,j) 0) goto werr;// 遍历全局哈希表while((de dictNext(di)) ! NULL) {sds keystr;robj key, *o;long long expiretime;// 获取Key、Valuekeystr dictGetKey(de);o dictGetVal(de);initStaticStringObject(key,keystr);// 获取过期时间expiretime getExpire(db,key);// 根据不同的数据类型生成对应的AOF日志.....// 保存过期时间if (expiretime ! -1) {char cmd[]*3\r\n$9\r\nPEXPIREAT\r\n;if (rioWrite(aof,cmd,sizeof(cmd)-1) 0) goto werr;if (rioWriteBulkObject(aof,key) 0) goto werr;if (rioWriteBulkLongLong(aof,expiretime) 0) goto werr;}// AOF重写文件每写入10KB就从尝试管道中读取父进程发送过来的增量AOF日志if (aof-processed_bytes processedAOF_READ_DIFF_INTERVAL_BYTES) {processed aof-processed_bytes;aofReadDiffFromParent();}}dictReleaseIterator(di);di NULL;}return C_OK; werr:if (di) dictReleaseIterator(di);return C_ERR; }子进程在 AOF 重写期间会不时地读取父进程通过管道发送过来的增量日志在 AOF 重写完以后也会再读取一下增量日志尽可能地让自己重写的 AOF 文件更全面一些方法是aofReadDiffFromParent()读取到的增量日志会先缓存到server.aof_child_diff ssize_t aofReadDiffFromParent(void) {char buf[65536]; /* Default pipe buffer size on most Linux systems. */ssize_t nread, total 0;while ((nread read(server.aof_pipe_read_data_from_parent,buf,sizeof(buf))) 0) {server.aof_child_diff sdscatlen(server.aof_child_diff,buf,nread);total nread;}return total; }子进程重写完以后把 AOF 文件刷新到磁盘就可以退出了。父进程的定时任务监听到子进程退出后会触发backgroundRewriteDoneHandler()方法对 AOF 重写做一个收尾的工作 打开重写后的临时文件把最后还剩余的增量日志写入到临时文件替换旧的 AOF 文件清理管道等资源 void backgroundRewriteDoneHandler(int exitcode, int bysignal) {// 打开子进程重写后的临时文件snprintf(tmpfile,256,temp-rewriteaof-bg-%d.aof,(int)server.child_pid);// 把aof_rewrite_buf_blocks的剩余数据写入AOF文件if (aofRewriteBufferWrite(newfd) -1) {serverLog(LL_WARNING,Error trying to flush the parent diff to the rewritten AOF: %s, strerror(errno));close(newfd);goto cleanup;}......// 替换AOF文件rename(tmpfile,server.aof_filename);...... }至此AOF 重写就算彻底结束了。 现在还有一个问题父进程把 AOF 重写期间的增量日志写在哪里呢 父进程写完 AOF 日志缓冲区后会继续判断当前是否有子进程在重写 AOF如果有就把增量日志再写一份到 AOF 重写缓冲区 void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc) {......// 追加到AOF缓冲区if (server.aof_state AOF_ON)server.aof_buf sdscatlen(server.aof_buf,buf,sdslen(buf));// 如果有AOF子进程在重写还要把增量部分追加到AOF重写缓冲区if (server.child_type CHILD_TYPE_AOF)aofRewriteBufferAppend((unsigned char*)buf,sdslen(buf)); }aofRewriteBufferAppend()方法会把增量日志写入到 AOF 重写缓冲区重写缓冲区是由若干个aofrwblock串联成的一条链表单个 block 容量是 10MB。 typedef struct aofrwblock {unsigned long used, free; // 已使用空间、空闲空间char buf[AOF_RW_BUF_BLOCK_SIZE]; // 缓冲区 默认10MB } aofrwblock;Redis 会先判断当前 block 是否能容纳增量日志如果空间不够会申请新的 block 再写入。如果重写期间有大量写入重写缓冲区会变得很大占用大量内存。 void aofRewriteBufferAppend(unsigned char *s, unsigned long len) {// AOF重写缓冲区由若干个aofrwblock组成单个block默认10MBlistNode *ln listLast(server.aof_rewrite_buf_blocks);aofrwblock *block ln ? ln-value : NULL;while(len) {if (block) {unsigned long thislen (block-free len) ? block-free : len;if (thislen) {// 当前已经分配了block且block可以容纳增量AOF日志直接写入即可memcpy(block-bufblock-used, s, thislen);block-used thislen;block-free - thislen;s thislen;len - thislen;}}if (len) { // 还没有分配block或block容量不够需要分配新的int numblocks;// 分配blockblock zmalloc(sizeof(*block));block-free AOF_RW_BUF_BLOCK_SIZE;block-used 0;// block加入链表listAddNodeTail(server.aof_rewrite_buf_blocks,block);// block数量超过10或100的倍数时记录日志numblocks listLength(server.aof_rewrite_buf_blocks);if (((numblocks1) % 10) 0) {int level ((numblocks1) % 100) 0 ? LL_WARNING :LL_NOTICE;serverLog(level,Background AOF buffer size: %lu MB,aofRewriteBufferSize()/(1024*1024));}}}if (!server.aof_stop_sending_diff aeGetFileEvents(server.el,server.aof_pipe_write_data_to_child) 0){aeCreateFileEvent(server.el, server.aof_pipe_write_data_to_child,AE_WRITABLE, aofChildWriteDiffData, NULL);} }注意最后几行代码Redis 给管道 fd 注册了可写事件。因为父进程光写入重写缓冲区还不够还要把重写缓冲区里的增量日志发给子进程让子进程尽可能多的写入日志自己最后就能少写一点了监听方法是aofChildWriteDiffData()父进程发送后子进程就可以读到了。 void aofChildWriteDiffData(aeEventLoop *el, int fd, void *privdata, int mask) {listNode *ln;aofrwblock *block;ssize_t nwritten;UNUSED(el);UNUSED(fd);UNUSED(privdata);UNUSED(mask);while(1) {// 从头开始发ln listFirst(server.aof_rewrite_buf_blocks);block ln ? ln-value : NULL;if (server.aof_stop_sending_diff || !block) {aeDeleteFileEvent(server.el,server.aof_pipe_write_data_to_child,AE_WRITABLE);return;}if (block-used 0) {// 写入管道nwritten write(server.aof_pipe_write_data_to_child,block-buf,block-used);if (nwritten 0) return;memmove(block-buf,block-bufnwritten,block-used-nwritten);block-used - nwritten;block-free nwritten;}if (block-used 0) listDelNode(server.aof_rewrite_buf_blocks,ln);} }尾巴 AOF 主要解决 Redis 数据持久化的实时性问题现在已经成为了主流的持久化方式。它会把写命令生成 RESP 协议文本的方式追加到 AOF 文件中为了避免 AOF 文件过度膨胀Redis 会按照一定的策略对 AOF 文件做重写。重写时为了避免阻塞主线程Redis 会 fork 子进程处理同时主进程会记录下重写期间的增量日志通过管道发送给子进程让子进程尽可能多的记录日志子进程重写完毕后会通过管道发送 ACK 要求父进程停止发送增量日志子进程退出父进程做最后的收尾工作把最后剩余的一点增量日志追加到新的 AOF 文件后并完成替换整个 AOF 重写就结束了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/86803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

西安高端品牌网站wang域名的网站

列表 列表的元素 有序列表:ol、li无序列表:ul、li自定义列表:dl dt dd 自定义列表 dl 定义列表,直接元素只能是dt、dd dt 列表中每一项的项目名 dd 列表的每一项的具体描述 表格 table 表格border-collapse:collapse; (塌陷的…

上海红酒网站建设沈阳工程建设监理咨询

文章目录 Batch Normalizationinternal covariate shift激活层的作用BN执行的位置数据白化网络中的BN层训练过程 BN的实验效果MNIST与GoogleLeNet V1比较 GoogleLeNet出来之后,Google在这个基础上又演进了几个版本,一般来说是说有4个版本,之前…

与安网站建设广州短视频网站开发

国外主流还是使用apache;国内现在主流是nginx(并发能力强,相对稳定) nginx:高性能、轻量级的web服务软件 特点: 1.稳定性高(没apache稳); 2.系统资源消耗比较低&#xf…

一些设计网站投票链接制作

运行示例项目报错缺少dll,发现运用了这个大老李,通过添加PATH路径也无法解决,看到debug文件夹下面没有其他的依赖项。 通过depneds工具可以看到 OCCTProxy_D3D.dll 缺少依赖项,图中的缺项都是OCCT生成的模块dll所以讲这些dll从..…

商城网站建设价位asp.net门户网站项目怎么做

本文转载自公众号: 美团技术团队.作为人工智能时代最重要的知识表示方式之一,知识图谱能够打破不同场景下的数据隔离,为搜索、推荐、问答、解释与决策等应用提供基础支撑。美团大脑围绕吃喝玩乐等多种场景,构建了生活娱乐领域超大规模的知识图…

站内推广方案公司部门名字大全

2016年五一杯数学建模 C题 二孩政策问题 原题再现 多年来实施的严、紧计划生育政策对控制人口增长起到关键作用。在优生优育政策的指引下,我国人口质量显著提高,但也带来了不利影响,生育率偏低、男女比例失衡、人口老龄化情况严重等问题。2…

郑州网站app建设微信应用平台开发

如果调试是消除软件错误的过程,那么编程一定是添加错误的过程。Edsger Dijkstra。来自 https://www.azquotes.com/quote/561997 一、说明 在这篇文章中,我想谈谈 TensorFlow 中的调试。 在之前的一些帖子(此处、此处和此处)中&…

仿网站教程关键词搜索排行榜

Java 条件语句 - if…else Java 中的条件语句允许程序根据条件的不同执行不同的代码块。 一个 if 语句包含一个布尔表达式和一条或多条语句。 语法 if 语句的语法如下: if(布尔表达式) {//如果布尔表达式为true将执行的语句 }如果布尔表达式的值为 true&#x…

网站集约化建设工作总结郑州男科医院怎么样啊

随着计算机技术的不断发展,企业的办公系统得到了很大提升,但是随之而来的网络安全威胁也不断增加,勒索病毒的攻击事件时有发生。近期,我们收到某地连锁超市的求助,企业的计算机服务器遭到了360后缀勒索病毒攻击&#x…

怎么做投票网站什么网站可以免费做视频的软件

在 C 中&#xff0c;可以使用 std::map 统计值出现次数为 2 的键。具体步骤如下&#xff1a; 遍历 std::map&#xff0c;找出所有值为 2 的键。使用条件语句检查每个值&#xff0c;符合条件时记录对应键。 #include <iostream> #include <map> #include <vect…

网站开发公对公转账合同模板自己在网站开发的客户怎么联系

2019独角兽企业重金招聘Python工程师标准>>> lrzsz linux与windows互传 # 前提是使用 xshell 或者 securecrt 这两个远程软件&#xff0c;putty不支持 yum install -y lrzsz //安装文件包 linux向windows 传文件使用 &#xff1a; sz 文件名 回…

在手机制作网站90设计官方网站

目录 前言 项目规划&#xff08;第二周&#xff09; 具体实现 用户大类 AccountOperations接口 UserOperations接口 Operations类&#xff08;实现类&#xff09; Account类 User类 Area类 &#xff08;父类&#xff09; 货币大类 Money类&#xff08;抽象类&…

泰州网站建设方案优化安徽建设厅网站考勤

数据库是什么 数据库是一种用来存储数据的仓库&#xff0c;是一种高效存储和处理数据的介质&#xff08;载体&#xff09;。我们通常口中所说的数据库指的是数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;是一种用于方便管理数据库的软件。 数据库的分类 根据存储…

网站设计知名企业剑三做月饼活动网站

是cocoaChina网站上下载的知识点整理&#xff0c;共669个知识点&#xff0c;我花了点时间给文件全部做了重命名&#xff0c;这样用来查阅或者选择性的学习会有些帮助。 文件放在115网盘&#xff0c;下载地址&#xff1a;http://115.com/file/bhkqjlx2#cocoaChina整理知识点.rar…

网站点击量在哪里看网站推广方法有哪些

目录 stack类介绍 stack类定义 stack类常见构造函数 stack数据操作 empty()函数 size()函数 top()函数 push()函数 pop()函数 swap()函数 stack类介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端…

做特价网站百度云网站建设视频教程

10.1 文件I/O操作概述在Linux系统中&#xff0c;文件I/O操作可以分为两类&#xff0c;一类是基于文件描述符的I/O操作&#xff0c;另一类是基于数据流的I/O操作。10.1.1 文件描述符简介在文件操作一章中&#xff0c;也经常提到文件描述符这个概念。所谓文件描述符&#xff0c;就…

济南网站建设制作设计北京引流推广公司

为什么80%的码农都做不了架构师&#xff1f;>>> 1、图形简介 与html5不同&#xff0c;Raphael提供了以下基本图形&#xff1a;矩形、圆形、椭圆形&#xff08;html5只有矩形&#xff09;。 Paper.rect(x,y,width,height,r)&#xff1a;绘制矩形&#xff1b; 参…

海宁市建设局官方网站6APP编辑WordPress

前言 在说到对图片资源进行优化时&#xff0c;那就不得不提到图片预加载和图片懒加载&#xff0c;可能很多朋友都了解这两者&#xff0c;但是一直没有很清晰的概念&#xff0c;以及什么时候用&#xff0c;用在什么场景下&#xff0c;今天就来详细的了解一下吧&#xff01; 图…

网站建网站建设做水利网站需要多少钱

一、前言 K8S经过多年的发展&#xff0c;构建了云原生的基石&#xff0c;成为了云原生时代的统治者。我将用三个博客系列全面&#xff0c;循序渐进的介绍K8S相关知识。 初级入门系列&#xff0c;主要针对K8S初学者&#xff0c;以及希望对K8S有所了解的研发人员&#xff0c;重点…

怎么做汽车网站php和什么语言做网站

最近富文本编辑器jodit终于更新发布到了4.0版本&#xff0c;加入了css变量、有更好的typescript支持&#xff0c;截止发文时的版本是&#xff1a;4.0.5&#xff0c;看到有了新版本于是便想着将本地项目中的jodit版本也进行升级&#xff0c;琢磨着再丰富和添加一些功能&#xff…