redis.conf之save配置项解读
配置示例:
|
save9001 save30010 save603600 |
配置解讀:
1)“save9001”表示如果900秒內至少1個key發生變化(新增、修改和刪除),則重寫rdb文件;
2)“save30010”表示如果每300秒內至少10個key發生變化(新增、修改和刪除),則重寫rdb文件;
3)“save603600”表示如果每60秒內至少10000個key發生變化(新增、修改和刪除),則重寫rdb文件。
作用:
控制什么時候生成rdb文件(快照,也可叫Checkpoint,即檢查點)。
進程啟動的時候,會將每一行save讀進到類型為structsaveparam的數組中。這個沒有排序,依在redis.conf中的先后順序。在檢查時,只要滿足就不會再檢查下一條規則。
配置策略:
如果同時開啟了aof,則可考慮將save的參數調大一點,以減少寫rdb帶來的壓力。實際上如果開啟了aof,redis在啟動時只會讀取aof文件,而不會讀取rdb文件:
|
//FunctioncalledatstartuptoloadRDBorAOFfileinmemory. voidloadDataFromDisk(void){ if(server.aof_state==AOF_ON){ //允許空的aof文件, //如果讀取aof文件出錯,則調用exit(1)直接退出進程 if(loadAppendOnlyFile(server.aof_filename)==C_OK) serverLog(LL_NOTICE,"DBloadedfromappendonlyfile:%.3fseconds",(float)(ustime()-start)/1000000); }else{ if(rdbLoad(server.rdb_filename,&rsi)==C_OK){ } } //#defineAOF_OFF0/*AOFisoff*/ //#defineAOF_ON1/*AOFison*/ voidloadServerConfigFromString(char*config){ 。。。。。。 }elseif(!strcasecmp(argv[0],"appendonly")&&argc==2){ intyes; if((yes=yesnotoi(argv[1]))==-1){ err="argumentmustbe'yes'or'no'";gotoloaderr; } server.aof_state=yes?AOF_ON:AOF_OFF; } 。。。。。。 } intyesnotoi(char*s){ if(!strcasecmp(s,"yes"))return1; elseif(!strcasecmp(s,"no"))return0; elsereturn-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調用。
相關源代碼:
|
intserverCron(structaeEventLoop*eventLoop,longlongid,void*clientData){ 。。。。。。 //CheckifabackgroundsavingorAOFrewriteinprogressterminated. //如果已有rdb和aof進程,檢查進程是否已退出。 //如果已退出,則會善后處理,否則什么也不做,等待下一次循環時再次檢查 if(server.rdb_child_pid!=-1|| server.aof_child_pid!=-1|| ldbPendingChildren()){ intstatloc; pid_tpid; if((pid=wait3(&statloc,WNOHANG,NULL))!=0){ intexitcode=WEXITSTATUS(statloc); 。。。。。。 } }else{ //Ifthereisnotabackgroundsaving/rewrite //inprogresscheckifwehavetosave/rewritenow. //按在redis.conf中定義的順序依次遍歷每一行配置項 //最終是否進行寫rdb操作(即生成快照文件),不僅由redis.conf //中的配置項決定,還要看上一次操作的結果和狀態。 for(j=0;j<server.saveparamslen;j++){ structsaveparam*sp=server.saveparams+j; //Saveifwereachedthegivenamountofchanges, //thegivenamountofseconds,andifthelatestbgsavewas //successfulorif,incaseofanerror,atleast //CONFIG_BGSAVE_RETRY_DELAYsecondsalreadyelapsed. //CONFIG_BGSAVE_RETRY_DELAY(5):Waitafewsecsbeforetryingagain. 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,"%dchangesin%dseconds.Saving...", sp->changes,(int)sp->seconds); rdbSaveInforsi,*rsiptr; rsiptr=rdbPopulateSaveInfo(&rsi); rdbSaveBackground(server.rdb_filename,rsiptr); break;//遇到一條滿足的即結束處理,因為已沒有必要判斷是否滿足下一條配置規則 } } } 。。。。。。 } //rdb.c intrdbSaveBackground(char*filename,rdbSaveInfo*rsi){ 。。。。。。 server.lastbgsave_try=time(NULL); 。。。。。。 //創建寫rdb的子進程 if((childpid=fork())==0){ redisSetProcTitle("redis-rdb-bgsave"); retval=rdbSave(filename,rsi); } 。。。。。。 } /*SavetheDBondisk.ReturnC_ERRonerror,C_OKonsuccess.*/ //rdb.c //rdbSave調用rdbSaveRio將數據寫入到rdb文件中 intrdbSave(char*filename,rdbSaveInfo*rsi){ 。。。。。。 //寫rdb文件 if(rdbSaveRio(&rdb,&error,RDB_SAVE_NONE,rsi)==C_ERR){ errno=error; gotowerr; } 。。。。。。 serverLog(LL_NOTICE,"DBsavedondisk"); server.dirty=0; server.lastsave=time(NULL); server.lastbgsave_status=C_OK; returnC_OK; } /*ProducesadumpofthedatabaseinRDBformatsendingittothespecified *RedisI/Ochannel.OnsuccessC_OKisreturned,otherwiseC_ERR *isreturnedandpartoftheoutput,oralltheoutput,canbe *missingbecauseofI/Oerrors. * *WhenthefunctionreturnsC_ERRandif'error'isnotNULL,the *integerpointedby'error'issettothevalueoferrnojustaftertheI/O *error.*/ intrdbSaveRio(rio*rdb,int*error,intflags,rdbSaveInfo*rsi){ for(j=0;j<server.dbnum;j++){ 。。。。。。 //IteratethisDBwritingeveryentry while((de=dictNext(di))!=NULL){ 。。。。。。 //將一對對KV寫入到rdb文件 if(rdbSaveKeyValuePair(rdb,&key,o,expire)==-1)gotowerr; 。。。。。。 } } 。。。。。。 werr: if(error)*error=errno; if(di)dictReleaseIterator(di); returnC_ERR; } //以SADD命令為例,所有寫操作,均會修改dirty的值 voidsaddCommand(client*c){ 。。。。。。 for(j=2;j<c->argc;j++){ if(setTypeAdd(set,c->argv[j]->ptr))added++; } 。。。。。。 server.dirty+=added; addReplyLongLong(c,added); } |
總結
以上是生活随笔為你收集整理的redis.conf之save配置项解读的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 土耳其称发现7亿吨稀土 是真的吗?权威专
- 下一篇: php开启fileinfo扩展