<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當(dāng)前位置: 首頁 - 科技 - 知識(shí)百科 - 正文

        硬盤寫滿后redis的處理機(jī)制

        來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-09 14:20:50
        文檔

        硬盤寫滿后redis的處理機(jī)制

        硬盤寫滿后redis的處理機(jī)制:前些天一臺(tái)redis機(jī)器硬盤寫滿了,主要是由于程序bug導(dǎo)致備份量激增,而恰好監(jiān)控程序的通知機(jī)制也罷工了,于是第一次體驗(yàn)到了redis的罷工(只讀不寫)。 現(xiàn)在我們來看下在磁盤寫滿后redis的處理機(jī)制: save流程:serverCron-rdbSaveBackgroun
        推薦度:
        導(dǎo)讀硬盤寫滿后redis的處理機(jī)制:前些天一臺(tái)redis機(jī)器硬盤寫滿了,主要是由于程序bug導(dǎo)致備份量激增,而恰好監(jiān)控程序的通知機(jī)制也罷工了,于是第一次體驗(yàn)到了redis的罷工(只讀不寫)。 現(xiàn)在我們來看下在磁盤寫滿后redis的處理機(jī)制: save流程:serverCron-rdbSaveBackgroun

        前些天一臺(tái)redis機(jī)器硬盤寫滿了,主要是由于程序bug導(dǎo)致備份量激增,而恰好監(jiān)控程序的通知機(jī)制也罷工了,于是第一次體驗(yàn)到了redis的罷工(只讀不寫)。 現(xiàn)在我們來看下在磁盤寫滿后redis的處理機(jī)制: save流程:serverCron-rdbSaveBackground-rdbSave save后

        前些天一臺(tái)redis機(jī)器硬盤寫滿了,主要是由于程序bug導(dǎo)致備份量激增,而恰好監(jiān)控程序的通知機(jī)制也罷工了,于是第一次體驗(yàn)到了redis的罷工(只讀不寫)。

        現(xiàn)在我們來看下在磁盤寫滿后redis的處理機(jī)制:

        save流程:serverCron->rdbSaveBackground->rdbSave
        save后流程:serverCron->backgroundSaveDoneHandler
        上述流程產(chǎn)生的結(jié)果就是server.lastbgsave_status = REDIS_ERR,

        受其影響,processCommand和luaRedisGenericCommand中判斷如果是寫操作,則直接返回REDIS_OK,而沒有實(shí)際寫入

        1.rdbSave所有的寫出錯(cuò)都會(huì)返回REDIS_ERR

        int rdbSave(char *filename) {
         dictIterator *di = NULL;
         dictEntry *de;
         char tmpfile[256];
         char magic[10];
         int j;
         long long now = mstime();
         FILE *fp;
         rio rdb;
         uint64_t cksum;
        
         snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
         fp = fopen(tmpfile,"w");
         if (!fp) {
         redisLog(REDIS_WARNING, "Failed opening .rdb for saving: %s",
         strerror(errno));
         return REDIS_ERR;
         }
        
         rioInitWithFile(&rdb,fp);
         if (server.rdb_checksum)
         rdb.update_cksum = rioGenericUpdateChecksum;
         snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION);
         if (rdbWriteRaw(&rdb,magic,9) == -1) goto werr;
        
         for (j = 0; j < server.dbnum; j++) {
         redisDb *db = server.db+j;
         dict *d = db->dict;
         if (dictSize(d) == 0) continue;
         di = dictGetSafeIterator(d);
         if (!di) {
         fclose(fp);
         return REDIS_ERR;
         }
        
         /* Write the SELECT DB opcode */
         if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_SELECTDB) == -1) goto werr;
         if (rdbSaveLen(&rdb,j) == -1) goto werr;
        
         /* Iterate this DB writing every entry */
         while((de = dictNext(di)) != NULL) {
         sds keystr = dictGetKey(de);
         robj key, *o = dictGetVal(de);
         long long expire;
        
         initStaticStringObject(key,keystr);
         expire = getExpire(db,&key);
         if (rdbSaveKeyValuePair(&rdb,&key,o,expire,now) == -1) goto werr;
         }
         dictReleaseIterator(di);
         }
         di = NULL; /* So that we don't release it again on error. */
        
         /* EOF opcode */
         if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr;
        
         /* CRC64 checksum. It will be zero if checksum computation is disabled, the
         * loading code skips the check in this case. */
         cksum = rdb.cksum;
         memrev64ifbe(&cksum);
         if (rioWrite(&rdb,&cksum,8) == 0) goto werr;
        
         /* Make sure data will not remain on the OS's output buffers */
         if (fflush(fp) == EOF) goto werr;
         if (fsync(fileno(fp)) == -1) goto werr;
         if (fclose(fp) == EOF) goto werr;
        
         /* Use RENAME to make sure the DB file is changed atomically only
         * if the generate DB file is ok. */
         if (rename(tmpfile,filename) == -1) {
         redisLog(REDIS_WARNING,"Error moving temp DB file on the final destination: %s", strerror(errno));
         unlink(tmpfile);
         return REDIS_ERR;
         }
         redisLog(REDIS_NOTICE,"DB saved on disk");
         server.dirty = 0;
         server.lastsave = time(NULL);
         server.lastbgsave_status = REDIS_OK;
         return REDIS_OK;
        
        werr:
         fclose(fp);
         unlink(tmpfile);
         redisLog(REDIS_WARNING,"Write error saving DB on disk: %s", strerror(errno));
         if (di) dictReleaseIterator(di);
         return REDIS_ERR;
        }

        2.rdbSaveBackground中,如果子進(jìn)程調(diào)用rdbsave返回REDIS_ERR,那么子進(jìn)程exit(1)

        int rdbSaveBackground(char *filename) {
         pid_t childpid;
         long long start;
        
         if (server.rdb_child_pid != -1) return REDIS_ERR;
        
         server.dirty_before_bgsave = server.dirty;
         server.lastbgsave_try = time(NULL);
        
         start = ustime();
         if ((childpid = fork()) == 0) {
         int retval;
        
         /* Child */
         closeListeningSockets(0);
         redisSetProcTitle("redis-rdb-bgsave");
         retval = rdbSave(filename);
         if (retval == REDIS_OK) {
         size_t private_dirty = zmalloc_get_private_dirty();
        
         if (private_dirty) {
         redisLog(REDIS_NOTICE,
         "RDB: %zu MB of memory used by copy-on-write",
         private_dirty/(1024*1024));
         }
         }
         exitFromChild((retval == REDIS_OK) ? 0 : 1); //進(jìn)程退出時(shí)返回0/1
         } else {
         /* Parent */
         server.stat_fork_time = ustime()-start;
         if (childpid == -1) {
         server.lastbgsave_status = REDIS_ERR;
         redisLog(REDIS_WARNING,"Can't save in background: fork: %s",
         strerror(errno));
         return REDIS_ERR;
         }
         redisLog(REDIS_NOTICE,"Background saving started by pid %d",childpid);
         server.rdb_save_time_start = time(NULL);
         server.rdb_child_pid = childpid;
         updateDictResizePolicy();
         return REDIS_OK;
         }
         return REDIS_OK; /* unreached */
        }
        3.bgsave完成后,serverCron中得到bgsave子進(jìn)程的返回碼進(jìn)行后續(xù)處理
         /* Check if a background saving or AOF rewrite in progress terminated. */
         if (server.rdb_child_pid != -1 || server.aof_child_pid != -1) {
         int statloc;
         pid_t pid;
        
         if ((pid = wait3(&statloc,WNOHANG,NULL)) != 0) {
         int exitcode = WEXITSTATUS(statloc);
         int bysignal = 0;
        
         if (WIFSIGNALED(statloc)) bysignal = WTERMSIG(statloc);
        
         if (pid == server.rdb_child_pid) {
         backgroundSaveDoneHandler(exitcode,bysignal); //根據(jù)bgsave子進(jìn)程的exitcode以及是否由信號(hào)結(jié)束的標(biāo)簽進(jìn)行后續(xù)處理
         } else if (pid == server.aof_child_pid) {
         backgroundRewriteDoneHandler(exitcode,bysignal);
         } else {
         redisLog(REDIS_WARNING,
         "Warning, detected child with unmatched pid: %ld",
         (long)pid);
         }
         updateDictResizePolicy();
         }
         }
        4.如果子進(jìn)程非信號(hào)結(jié)束,并且exitcode非0,那么設(shè)置bgsave狀態(tài)為REDIS_ERR
        void backgroundSaveDoneHandler(int exitcode, int bysignal) {
         if (!bysignal && exitcode == 0) {
         redisLog(REDIS_NOTICE,
         "Background saving terminated with success");
         server.dirty = server.dirty - server.dirty_before_bgsave;
         server.lastsave = time(NULL);
         server.lastbgsave_status = REDIS_OK;
         } else if (!bysignal && exitcode != 0) {
         redisLog(REDIS_WARNING, "Background saving error");
         server.lastbgsave_status = REDIS_ERR; //狀態(tài)轉(zhuǎn)換
         } else {
         mstime_t latency;
        
         redisLog(REDIS_WARNING,
         "Background saving terminated by signal %d", bysignal);
         latencyStartMonitor(latency);
         rdbRemoveTempFile(server.rdb_child_pid);
         latencyEndMonitor(latency);
         latencyAddSampleIfNeeded("rdb-unlink-temp-file",latency);
         /* SIGUSR1 is whitelisted, so we have a way to kill a child without
         * tirggering an error conditon. */
         if (bysignal != SIGUSR1)
         server.lastbgsave_status = REDIS_ERR;
         }
         server.rdb_child_pid = -1;
         server.rdb_save_time_last = time(NULL)-server.rdb_save_time_start;
         server.rdb_save_time_start = -1;
         /* Possibly there are slaves waiting for a BGSAVE in order to be served
         * (the first stage of SYNC is a bulk transfer of dump.rdb) */
         updateSlavesWaitingBgsave((!bysignal && exitcode == 0) ? REDIS_OK : REDIS_ERR);
        }
        5.processCommand中判定cmd是寫操作的話,直接返回REDIS_OK
         /* Don't accept write commands if there are problems persisting on disk
         * and if this is a master instance. */
         if (((server.stop_writes_on_bgsave_err &&
         server.saveparamslen > 0 &&
         server.lastbgsave_status == REDIS_ERR) ||
         server.aof_last_write_status == REDIS_ERR) &&
         server.masterhost == NULL &&
         (c->cmd->flags & REDIS_CMD_WRITE ||
         c->cmd->proc == pingCommand))
         {
         flagTransaction(c);
         if (server.aof_last_write_status == REDIS_OK)
         addReply(c, shared.bgsaveerr);
         else
         addReplySds(c,
         sdscatprintf(sdsempty(),
         "-MISCONF Errors writing to the AOF file: %s\r\n",
         strerror(server.aof_last_write_errno)));
         return REDIS_OK;
         }
        6.luaRedisGenericCommand中判定cmd是寫操作的話,屏蔽
         /* Write commands are forbidden against read-only slaves, or if a
         * command marked as non-deterministic was already called in the context
         * of this script. */
         if (cmd->flags & REDIS_CMD_WRITE) {
         if (server.lua_random_dirty) {
         luaPushError(lua,
         "Write commands not allowed after non deterministic commands");
         goto cleanup;
         } else if (server.masterhost && server.repl_slave_ro &&
         !server.loading &&
         !(server.lua_caller->flags & REDIS_MASTER))
         {
         luaPushError(lua, shared.roslaveerr->ptr);
         goto cleanup;
         } else if (server.stop_writes_on_bgsave_err &&
         server.saveparamslen > 0 &&
         server.lastbgsave_status == REDIS_ERR)
         {
         luaPushError(lua, shared.bgsaveerr->ptr);
         goto cleanup;
         }
         }
        
        cleanup:
         /* Clean up. Command code may have changed argv/argc so we use the
         * argv/argc of the client instead of the local variables. */
         for (j = 0; j < c->argc; j++) {
         robj *o = c->argv[j];
        
         /* Try to cache the object in the cached_objects array.
         * The object must be small, SDS-encoded, and with refcount = 1
         * (we must be the only owner) for us to cache it. */
         if (j < LUA_CMD_OBJCACHE_SIZE &&
         o->refcount == 1 &&
         o->encoding == REDIS_ENCODING_RAW &&
         sdslen(o->ptr) <= LUA_CMD_OBJCACHE_MAX_LEN)
         {
         struct sdshdr *sh = (void*)(((char*)(o->ptr))-(sizeof(struct sdshdr)));
        
         if (cached_objects[j]) decrRefCount(cached_objects[j]);
         cached_objects[j] = o;
         cached_objects_len[j] = sh->free + sh->len;
         } else {
         decrRefCount(o);
         }
         }
        
         if (c->argv != argv) {
         zfree(c->argv);
         argv = NULL;
         }
        
         if (raise_error) {
         /* If we are here we should have an error in the stack, in the
         * form of a table with an "err" field. Extract the string to
         * return the plain error. */
         lua_pushstring(lua,"err");
         lua_gettable(lua,-2);
         return lua_error(lua);
         }
         return 1; 

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        硬盤寫滿后redis的處理機(jī)制

        硬盤寫滿后redis的處理機(jī)制:前些天一臺(tái)redis機(jī)器硬盤寫滿了,主要是由于程序bug導(dǎo)致備份量激增,而恰好監(jiān)控程序的通知機(jī)制也罷工了,于是第一次體驗(yàn)到了redis的罷工(只讀不寫)。 現(xiàn)在我們來看下在磁盤寫滿后redis的處理機(jī)制: save流程:serverCron-rdbSaveBackgroun
        推薦度:
        標(biāo)簽: 硬盤 處理 解決
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: avtt天堂网手机版亚洲| 亚洲精品人成电影网| 日韩成人毛片高清视频免费看| AV片在线观看免费| 久久精品国产亚洲av麻豆蜜芽 | 99999久久久久久亚洲| 成人免费黄色网址| 亚洲女人影院想要爱| 色婷婷7777免费视频在线观看| 亚洲成a人片在线网站| 亚洲精品无码av人在线观看| jizz18免费视频| 噜噜噜亚洲色成人网站| a毛片成人免费全部播放| 中文字幕亚洲一区二区三区| 91福利免费网站在线观看| 亚洲高清国产AV拍精品青青草原| 日本免费高清视频| 亚洲大香伊人蕉在人依线| 日韩免费视频网站| 乱爱性全过程免费视频| 亚洲av无码不卡| 久久久久久久免费视频| 爱情岛论坛亚洲品质自拍视频网站| 亚洲国产综合久久天堂| 免费无码黄网站在线看| 亚洲av永久无码嘿嘿嘿| 四虎免费影院4hu永久免费| 国产啪精品视频网站免费尤物| 亚洲视频免费在线看| 日韩免费一区二区三区| 一级有奶水毛片免费看| 精品亚洲国产成人| 亚洲国产成人久久综合野外| 免费国产99久久久香蕉| 在线观看亚洲AV日韩AV| 国产亚洲精品免费视频播放| 免费H网站在线观看的| 国产精品高清免费网站 | 岛国片在线免费观看| 国产又黄又爽又大的免费视频|