|
如果保存了AOF文件,则使用AOF文件来恢复数据,AOF的具体内容见AOF
如果没有AOF,则使用rdb文件恢复数据,调用rdbLoad函数
接着看看rdbLoad函数
Rdb.c:929- int rdbLoad(char *filename) {
- ...
- fp = fopen(filename,"r");
- if (!fp) {
- errno = ENOENT;
- return REDIS_ERR;
- }
- if (fread(buf,9,1,fp) == 0) goto eoferr;
- buf[9] = '\0';
- if (memcmp(buf,"REDIS",5) != 0) {
- fclose(fp);
- redisLog(REDIS_WARNING,"Wrong signature trying to load DB from file");
- errno = EINVAL;
- return REDIS_ERR;
- }
- rdbver = atoi(buf+5);
- if (rdbver < 1 || rdbver > 2) {
- fclose(fp);
- redisLog(REDIS_WARNING,"Can't handle RDB format version %d",rdbver);
- errno = EINVAL;
- return REDIS_ERR;
- }
- startLoading(fp);
- while(1) {
- robj *key, *val;
- int force_swapout;
- expiretime = -1;
- /* Serve the clients from time to time */
- if (!(loops++ % 1000)) {
- loadingProgress(ftello(fp));
- aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT);
- }
- /* Read type. */
- if ((type = rdbLoadType(fp)) == -1) goto eoferr;
- if (type == REDIS_EXPIRETIME) {
- if ((expiretime = rdbLoadTime(fp)) == -1) goto eoferr;
- /* We read the time so we need to read the object type again */
- if ((type = rdbLoadType(fp)) == -1) goto eoferr;
- }
- if (type == REDIS_EOF) break;
- /* Handle SELECT DB opcode as a special case */
- if (type == REDIS_SELECTDB) {
- if ((dbid = rdbLoadLen(fp,NULL)) == REDIS_RDB_LENERR)
- goto eoferr;
- if (dbid >= (unsigned)server.dbnum) {
- redisLog(REDIS_WARNING,"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\n", server.dbnum);
- exit(1);
- }
- db = server.db+dbid;
- continue;
- }
- /* Read key */
- if ((key = rdbLoadStringObject(fp)) == NULL) goto eoferr;
- /* Read value */
- if ((val = rdbLoadObject(type,fp)) == NULL) goto eoferr;
- /* Check if the key already expired. This function is used when loading
- * an RDB file from disk, either at startup, or when an RDB was
- * received from the master. In the latter case, the master is
- * responsible for key expiry. If we would expire keys here, the
- * snapshot taken by the master may not be reflected on the slave. */
- if (server.masterhost == NULL && expiretime != -1 && expiretime < now) {
- decrRefCount(key);
- decrRefCount(val);
- continue;
- }
- /* Add the new object in the hash table */
- dbAdd(db,key,val);
- /* Set the expire time if needed */
- if (expiretime != -1) setExpire(db,key,expiretime);
- /* Handle swapping while loading big datasets when VM is on */
- /* If we detecter we are hopeless about fitting something in memory
- * we just swap every new key on disk. Directly…
- * Note that's important to check for this condition before resorting
- * to random sampling, otherwise we may try to swap already
- * swapped keys. */
- if (swap_all_values) {
- dictEntry *de = dictFind(db->dict,key->ptr);
- /* de may be NULL since the key already expired */
- if (de) {
- vmpointer *vp;
- val = dictGetEntryVal(de);
- if (val->refcount == 1 &&
- (vp = vmSwapObjectBlocking(val)) != NULL)
- dictGetEntryVal(de) = vp;
- }
- decrRefCount(key);
- continue;
- }
- decrRefCount(key);
- /* Flush data on disk once 32 MB of additional RAM are used… */
- force_swapout = 0;
- if ((zmalloc_used_memory() - server.vm_max_memory) > 1024*1024*32)
- force_swapout = 1;
- /* If we have still some hope of having some value fitting memory
- * then we try random sampling. */
- if (!swap_all_values && server.vm_enabled && force_swapout) {
- while (zmalloc_used_memory() > server.vm_max_memory) {
- if (vmSwapOneObjectBlocking() == REDIS_ERR) break;
- }
- if (zmalloc_used_memory() > server.vm_max_memory)
- swap_all_values = 1; /* We are already using too much mem */
- }
- }
- fclose(fp);
- stopLoading();
- return REDIS_OK;
- eoferr: /* unexpected end of file is handled here with a fatal exit */
- redisLog(REDIS_WARNING,"Short read or OOM loading DB. Unrecoverable error, aborting now.");
- exit(1);
- return REDIS_ERR; /* Just to avoid warning */
- }
复制代码 |
|