{"id":432,"date":"2020-06-14T21:20:00","date_gmt":"2020-06-14T13:20:00","guid":{"rendered":"https:\/\/www.ccagml.com\/?p=432"},"modified":"2021-06-21T21:33:46","modified_gmt":"2021-06-21T13:33:46","slug":"redis%e6%ba%90%e7%a0%81%e4%bb%8emain%e5%bc%80%e5%a7%8b17","status":"publish","type":"post","link":"https:\/\/www.ccagml.com\/?p=432","title":{"rendered":"redis\u6e90\u7801\u4ecemain\u5f00\u59cb17"},"content":{"rendered":"\n<p>\u672c\u7ae0\u6765\u770b\u6301\u4e45\u5316RDB\u3001AOF<\/p>\n\n\n\n<p>RDB\uff1a\u751f\u6210\u6307\u5b9a\u65f6\u95f4\u95f4\u9694\u5185\u7684&nbsp;Redis&nbsp;\u5185\u5b58\u4e2d\u6570\u636e\u5feb\u7167\uff0c\u662f\u4e00\u4e2a\u4e8c\u8fdb\u5236\u6587\u4ef6&nbsp;dumpr.rdb<\/p>\n\n\n\n<p>AOF\uff1a\u8bb0\u5f55&nbsp;Redis&nbsp;\u9664\u4e86\u67e5\u8be2\u4ee5\u5916\u7684\u6240\u6709\u5199\u547d\u4ee4\uff0c\u5e76\u5728Redis&nbsp;\u670d\u52a1\u542f\u52a8\u65f6\uff0c\u901a\u8fc7\u91cd\u65b0\u6267\u884c\u8fd9\u4e9b\u547d\u4ee4\u6765\u8fd8\u539f\u6570\u636e\u3002<\/p>\n\n\n\n<p>\u4e24\u8005\u5728\u5b98\u7f51\u6709\u8be6\u7ec6\u7684\u5bf9\u6bd4<a href=\"https:\/\/redis.io\/topics\/persistence\" target=\"_blank\" rel=\"noopener\">https:\/\/redis.io\/topics\/persistence<\/a><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\n\/\/ \u5148\u6765\u770bRDB\n\/\/1.save\u547d\u4ee4\n\/\/ save 60 1000\n\nvoid saveCommand(redisClient *c)\n{\n\n    \/\/ \u5df2\u7ecf\u5728bgsave\n    if (server.rdb_child_pid != -1)\n    {\n        addReplyError(c, \"Background save already in progress\");\n        return;\n    }\n\n    \/\/ \u6267\u884c\n    if (rdbSave(server.rdb_filename) == REDIS_OK)\n    {\n        addReply(c, shared.ok);\n    }\n    else\n    {\n        addReply(c, shared.err);\n    }\n}\n\n\n\/\/\u4fdd\u5b58\u6570\u636e\u5e93\u5230\u78c1\u76d8\u7684\u5177\u4f53\u5b9e\u73b0\nint rdbSave(char *filename)\n{\n    dictIterator *di = NULL;\n    dictEntry *de;\n    char tmpfile&#91;256];\n    char magic&#91;10];\n    int j;\n    long long now = mstime();\n    FILE *fp;\n    rio rdb;\n    uint64_t cksum;\n\n    \/\/ \u4e34\u65f6\u6587\u4ef6\n    snprintf(tmpfile, 256, \"temp-%d.rdb\", (int)getpid());\n    fp = fopen(tmpfile, \"w\");\n    if (!fp)\n    {\n        redisLog(REDIS_WARNING, \"Failed opening .rdb for saving: %s\",\n                 strerror(errno));\n        return REDIS_ERR;\n    }\n    rioInitWithFile(&amp;rdb, fp);\n\n    \/\/ \u662f\u5426\u9700\u8981\u6821\u9a8c\n    if (server.rdb_checksum)\n        rdb.update_cksum = rioGenericUpdateChecksum;\n    snprintf(magic, sizeof(magic), \"REDIS%04d\", REDIS_RDB_VERSION);\n    if (rdbWriteRaw(&amp;rdb, magic, 9) == -1)\n        goto werr;\n\n    \/\/ \u904d\u5386\u6574\u4e2a\u5e93\n    for (j = 0; j &lt; server.dbnum; j++)\n    {\n        \/\/\u54ea\u4e2a\u5e93\n        redisDb *db = server.db + j;\n        \/\/\u5e93\u4e2d\u5177\u4f53\u5b58\u6570\u636e\u7684\u5b57\u5178\n        dict *d = db-&gt;dict;\n\n        \/\/ \u5b57\u5178\u662f\u5426\u4e3a\u7a7a\n        if (dictSize(d) == 0)\n            continue;\n\n        \/\/ \u521b\u5efa\u5b89\u5168\u8fed\u4ee3\u5668\n        di = dictGetSafeIterator(d);\n        if (!di)\n        {\n            fclose(fp);\n            return REDIS_ERR;\n        }\n\n        \/\/ \u5199\u5165\u9009\u62e9\u6570\u636e\u5e93\u6807\u8bc6\u7b26,REDIS_RDB_OPCODE_SELECTDB\u662f\u7279\u6b8a\u64cd\u4f5c\u6807\u8bc6\u7b26\n        if (rdbSaveType(&amp;rdb, REDIS_RDB_OPCODE_SELECTDB) == -1)\n            goto werr;\n        if (rdbSaveLen(&amp;rdb, j) == -1)\n            goto werr;\n\n        \/\/ \u904d\u5386\u6570\u636e\u5e93\n        while ((de = dictNext(di)) != NULL)\n        {\n            sds keystr = dictGetKey(de);\n            robj key, *o = dictGetVal(de);\n            long long expire;\n\n            \/\/ \u6839\u636e keystr \uff0c\u5728\u6808\u4e2d\u521b\u5efa\u4e00\u4e2a key \u5bf9\u8c61\n            initStaticStringObject(key, keystr);\n            expire = getExpire(db, &amp;key);\n\n            \/\/ \u4fdd\u5b58\u952e\u503c\u5bf9\u6570\u636e\n            if (rdbSaveKeyValuePair(&amp;rdb, &amp;key, o, expire, now) == -1)\n                goto werr;\n        }\n        dictReleaseIterator(di);\n    }\n    di = NULL;\n\n    \/\/ \u5199\u5165\u67d0\u4e2a\u6570\u636e\u5e93\u7ed3\u675f\u7684\u7279\u6b8a\u64cd\u4f5c\u6807\u8bc6\u7b26\n    if (rdbSaveType(&amp;rdb, REDIS_RDB_OPCODE_EOF) == -1)\n        goto werr;\n    \/\/ \u6821\u9a8c\u548c\n    cksum = rdb.cksum;\n    memrev64ifbe(&amp;cksum);\n    rioWrite(&amp;rdb, &amp;cksum, 8);\n    if (fflush(fp) == EOF)\n        goto werr;\n    if (fsync(fileno(fp)) == -1)\n        goto werr;\n    if (fclose(fp) == EOF)\n        goto werr;\n\n    \/\/ \u91cd\u547d\u540d\u8986\u76d6\u539f\u6765\u7684\u6587\u4ef6\n    if (rename(tmpfile, filename) == -1)\n    {\n        redisLog(REDIS_WARNING, \"Error moving temp DB file on the final destination: %s\", strerror(errno));\n        unlink(tmpfile);\n        return REDIS_ERR;\n    }\n\n    redisLog(REDIS_NOTICE, \"DB saved on disk\");\n\n    \/\/ \u6e05\u96f6\u6570\u636e\u5e93\u810f\u72b6\u6001\n    server.dirty = 0;\n    \/\/ \u8bb0\u5f55\u6700\u540e\u4e00\u6b21\u5b8c\u6210 SAVE \u7684\u65f6\u95f4\n    server.lastsave = time(NULL);\n    \/\/ \u8bb0\u5f55\u6700\u540e\u4e00\u6b21\u6267\u884c SAVE \u7684\u72b6\u6001\n    server.lastbgsave_status = REDIS_OK;\n    return REDIS_OK;\n\nwerr:\n    \/\/ \u5173\u95ed\u6587\u4ef6\n    fclose(fp);\n    \/\/ \u5220\u9664\u6587\u4ef6\n    unlink(tmpfile);\n\n    redisLog(REDIS_WARNING, \"Write error saving DB on disk: %s\", strerror(errno));\n\n    if (di)\n        dictReleaseIterator(di);\n\n    return REDIS_ERR;\n}\n\n\/\/ \u4fdd\u5b58\u952e\u503c\nint rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val,\n                        long long expiretime, long long now)\n{\n    \/\/ \u8fc7\u671f\u65f6\u95f4\n    if (expiretime != -1)\n    {\n        \/\/ \u5df2\u8fc7\u671f\n        if (expiretime &lt; now)\n            return 0;\n        \/\/ \u4ee5\u6beb\u79d2\u8ba1\u7b97\u8fc7\u671f\u65f6\u95f4\n        if (rdbSaveType(rdb, REDIS_RDB_OPCODE_EXPIRETIME_MS) == -1)\n            return -1;\n        if (rdbSaveMillisecondTime(rdb, expiretime) == -1)\n            return -1;\n    }\n\n    \/\/ \u4fdd\u5b58\u952e\u503c\n    \/\/ \u4fdd\u5b58\u503c\u7684\u7c7b\u578b\n    if (rdbSaveObjectType(rdb, val) == -1)\n        return -1;\n    \/\/ \u4fdd\u5b58\u952e\n    if (rdbSaveStringObject(rdb, key) == -1)\n        return -1;\n    \/\/\u4fdd\u5b58\u503c\n    if (rdbSaveObject(rdb, val) == -1)\n        return -1;\n\n    return 1;\n}\n\n\/\/ \u4fdd\u5b58\u503c,\u6839\u636e\u4e0d\u540c\u503c\u7c7b\u578b\u4fdd\u5b58\nint rdbSaveObject(rio *rdb, robj *o)\n{\n    int n, nwritten = 0;\n\n    if (o-&gt;type == REDIS_STRING)\n    {\n        if ((n = rdbSaveStringObject(rdb, o)) == -1)\n            return -1;\n        nwritten += n;\n    }\n    else if (o-&gt;type == REDIS_LIST)\n    {\n        if (o-&gt;encoding == REDIS_ENCODING_ZIPLIST)\n        {\n            size_t l = ziplistBlobLen((unsigned char *)o-&gt;ptr);\n\n            if ((n = rdbSaveRawString(rdb, o-&gt;ptr, l)) == -1)\n                return -1;\n            nwritten += n;\n        }\n        else if (o-&gt;encoding == REDIS_ENCODING_LINKEDLIST)\n        {\n            list *list = o-&gt;ptr;\n            listIter li;\n            listNode *ln;\n\n            if ((n = rdbSaveLen(rdb, listLength(list))) == -1)\n                return -1;\n            nwritten += n;\n            listRewind(list, &amp;li);\n            while ((ln = listNext(&amp;li)))\n            {\n                robj *eleobj = listNodeValue(ln);\n                if ((n = rdbSaveStringObject(rdb, eleobj)) == -1)\n                    return -1;\n                nwritten += n;\n            }\n        }\n        else\n        {\n            redisPanic(\"Unknown list encoding\");\n        }\n    }\n    else if (o-&gt;type == REDIS_SET)\n    {\n        if (o-&gt;encoding == REDIS_ENCODING_HT)\n        {\n            dict *set = o-&gt;ptr;\n            dictIterator *di = dictGetIterator(set);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb, dictSize(set))) == -1)\n                return -1;\n            nwritten += n;\n\n            while ((de = dictNext(di)) != NULL)\n            {\n                robj *eleobj = dictGetKey(de);\n                if ((n = rdbSaveStringObject(rdb, eleobj)) == -1)\n                    return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n        }\n        else if (o-&gt;encoding == REDIS_ENCODING_INTSET)\n        {\n            size_t l = intsetBlobLen((intset *)o-&gt;ptr);\n            if ((n = rdbSaveRawString(rdb, o-&gt;ptr, l)) == -1)\n                return -1;\n            nwritten += n;\n        }\n        else\n        {\n            redisPanic(\"Unknown set encoding\");\n        }\n    }\n    else if (o-&gt;type == REDIS_ZSET)\n    {\n        if (o-&gt;encoding == REDIS_ENCODING_ZIPLIST)\n        {\n            size_t l = ziplistBlobLen((unsigned char *)o-&gt;ptr);\n            if ((n = rdbSaveRawString(rdb, o-&gt;ptr, l)) == -1)\n                return -1;\n            nwritten += n;\n        }\n        else if (o-&gt;encoding == REDIS_ENCODING_SKIPLIST)\n        {\n            zset *zs = o-&gt;ptr;\n            dictIterator *di = dictGetIterator(zs-&gt;dict);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb, dictSize(zs-&gt;dict))) == -1)\n                return -1;\n            nwritten += n;\n            while ((de = dictNext(di)) != NULL)\n            {\n                robj *eleobj = dictGetKey(de);\n                double *score = dictGetVal(de);\n                if ((n = rdbSaveStringObject(rdb, eleobj)) == -1)\n                    return -1;\n                nwritten += n;\n\n                if ((n = rdbSaveDoubleValue(rdb, *score)) == -1)\n                    return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n        }\n        else\n        {\n            redisPanic(\"Unknown sorted set encoding\");\n        }\n    }\n    else if (o-&gt;type == REDIS_HASH)\n    {\n        if (o-&gt;encoding == REDIS_ENCODING_ZIPLIST)\n        {\n            size_t l = ziplistBlobLen((unsigned char *)o-&gt;ptr);\n            if ((n = rdbSaveRawString(rdb, o-&gt;ptr, l)) == -1)\n                return -1;\n            nwritten += n;\n        }\n        else if (o-&gt;encoding == REDIS_ENCODING_HT)\n        {\n            dictIterator *di = dictGetIterator(o-&gt;ptr);\n            dictEntry *de;\n\n            if ((n = rdbSaveLen(rdb, dictSize((dict *)o-&gt;ptr))) == -1)\n                return -1;\n            nwritten += n;\n            while ((de = dictNext(di)) != NULL)\n            {\n                robj *key = dictGetKey(de);\n                robj *val = dictGetVal(de);\n                if ((n = rdbSaveStringObject(rdb, key)) == -1)\n                    return -1;\n                nwritten += n;\n                if ((n = rdbSaveStringObject(rdb, val)) == -1)\n                    return -1;\n                nwritten += n;\n            }\n            dictReleaseIterator(di);\n        }\n        else\n        {\n            redisPanic(\"Unknown hash encoding\");\n        }\n    }\n    else\n    {\n        redisPanic(\"Unknown object type\");\n    }\n    return nwritten;\n}\n\n\/\/2.bgsave\u547d\u4ee4,bgsave\u4f1a\u521b\u5efa\u5b50\u8fdb\u7a0b\u8fdb\u884c\u4fdd\u5b58\n\nvoid bgsaveCommand(redisClient *c)\n{\n    if (server.rdb_child_pid != -1)\n    {\n        addReplyError(c, \"Background save already in progress\");\n    }\n    else if (server.aof_child_pid != -1)\n    {\n        addReplyError(c, \"Can't BGSAVE while AOF log rewriting is in progress\");\n    }\n    else if (rdbSaveBackground(server.rdb_filename) == REDIS_OK)\n    {\n        addReplyStatus(c, \"Background saving started\");\n    }\n    else\n    {\n        addReply(c, shared.err);\n    }\n}\n\nint rdbSaveBackground(char *filename)\n{\n    pid_t childpid;\n    long long start;\n    if (server.rdb_child_pid != -1)\n        return REDIS_ERR;\n    server.dirty_before_bgsave = server.dirty;\n    server.lastbgsave_try = time(NULL);\n    start = ustime();\n\n    if ((childpid = fork()) == 0)\n    {\n        int retval;\n\n        \/* Child *\/\n        closeListeningSockets(0);\n        redisSetProcTitle(\"redis-rdb-bgsave\");\n\n        \/\/ \u6267\u884c\u4fdd\u5b58\u64cd\u4f5c\n        retval = rdbSave(filename);\n        if (retval == REDIS_OK)\n        {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty)\n            {\n                redisLog(REDIS_NOTICE,\n                         \"RDB: %zu MB of memory used by copy-on-write\",\n                         private_dirty \/ (1024 * 1024));\n            }\n        }\n\n        \/\/ \u5411\u7236\u8fdb\u7a0b\u53d1\u9001\u4fe1\u53f7\n        exitFromChild((retval == REDIS_OK) ? 0 : 1);\n    }\n    else\n    {\n\n        \/* Parent *\/\n\n        \/\/ \u8ba1\u7b97 fork() \u6267\u884c\u7684\u65f6\u95f4\n        server.stat_fork_time = ustime() - start;\n\n        \/\/ \u5982\u679c fork() \u51fa\u9519\uff0c\u90a3\u4e48\u62a5\u544a\u9519\u8bef\n        if (childpid == -1)\n        {\n            server.lastbgsave_status = REDIS_ERR;\n            redisLog(REDIS_WARNING, \"Can't save in background: fork: %s\",\n                     strerror(errno));\n            return REDIS_ERR;\n        }\n\n        \/\/ \u6253\u5370 BGSAVE \u5f00\u59cb\u7684\u65e5\u5fd7\n        redisLog(REDIS_NOTICE, \"Background saving started by pid %d\", childpid);\n\n        \/\/ \u8bb0\u5f55\u6570\u636e\u5e93\u5f00\u59cb BGSAVE \u7684\u65f6\u95f4\n        server.rdb_save_time_start = time(NULL);\n\n        \/\/ \u8bb0\u5f55\u8d1f\u8d23\u6267\u884c BGSAVE \u7684\u5b50\u8fdb\u7a0b ID\n        server.rdb_child_pid = childpid;\n\n        \/\/ \u5173\u95ed\u81ea\u52a8 rehash\n        updateDictResizePolicy();\n\n        return REDIS_OK;\n    }\n\n    return REDIS_OK; \/* unreached *\/\n}\n\n\/\/3.dump.rdb\u6062\u590d\u6570\u636e\n\/\/ \u5728\u542f\u52a8\u7684main\u65b9\u6cd5\u4e2d\u6267\u884cloadDataFromDisk,\u4f1a\u5224\u65ad\u662f\u5426\u52a0\u8f7d\u6570\u636e\nint rdbLoad(char *filename)\n{\n    uint32_t dbid;\n    int type, rdbver;\n    redisDb *db = server.db + 0;\n    char buf&#91;1024];\n    long long expiretime, now = mstime();\n    FILE *fp;\n    rio rdb;\n\n    \/\/ \u6253\u5f00 rdb \u6587\u4ef6\n    if ((fp = fopen(filename, \"r\")) == NULL)\n        return REDIS_ERR;\n\n    \/\/ \u521d\u59cb\u5316\u5199\u5165\u6d41\n    rioInitWithFile(&amp;rdb, fp);\n    rdb.update_cksum = rdbLoadProgressCallback;\n    rdb.max_processing_chunk = server.loading_process_events_interval_bytes;\n    if (rioRead(&amp;rdb, buf, 9) == 0)\n        goto eoferr;\n    buf&#91;9] = '\\0';\n\n    \/\/ \u68c0\u67e5\u7248\u672c\u53f7\n    if (memcmp(buf, \"REDIS\", 5) != 0)\n    {\n        fclose(fp);\n        redisLog(REDIS_WARNING, \"Wrong signature trying to load DB from file\");\n        errno = EINVAL;\n        return REDIS_ERR;\n    }\n    rdbver = atoi(buf + 5);\n    if (rdbver &lt; 1 || rdbver &gt; REDIS_RDB_VERSION)\n    {\n        fclose(fp);\n        redisLog(REDIS_WARNING, \"Can't handle RDB format version %d\", rdbver);\n        errno = EINVAL;\n        return REDIS_ERR;\n    }\n\n    \/\/ \u5c06\u670d\u52a1\u5668\u72b6\u6001\u8c03\u6574\u5230\u5f00\u59cb\u8f7d\u5165\u72b6\u6001\n    startLoading(fp);\n    while (1)\n    {\n        robj *key, *val;\n        expiretime = -1;\n\n        \/* Read type. \n         *\n         * \u8bfb\u5165\u7c7b\u578b\u6307\u793a\uff0c\u51b3\u5b9a\u8be5\u5982\u4f55\u8bfb\u5165\u4e4b\u540e\u8ddf\u7740\u7684\u6570\u636e\u3002\n         *\n         * \u8fd9\u4e2a\u6307\u793a\u53ef\u4ee5\u662f rdb.h \u4e2d\u5b9a\u4e49\u7684\u6240\u6709\u4ee5\n         * REDIS_RDB_TYPE_* \u4e3a\u524d\u7f00\u7684\u5e38\u91cf\u7684\u5176\u4e2d\u4e00\u4e2a\n         * \u6216\u8005\u6240\u6709\u4ee5 REDIS_RDB_OPCODE_* \u4e3a\u524d\u7f00\u7684\u5e38\u91cf\u7684\u5176\u4e2d\u4e00\u4e2a\n         *\/\n        if ((type = rdbLoadType(&amp;rdb)) == -1)\n            goto eoferr;\n\n        \/\/ \u8bfb\u5165\u8fc7\u671f\u65f6\u95f4\u503c\n        if (type == REDIS_RDB_OPCODE_EXPIRETIME)\n        {\n\n            \/\/ \u4ee5\u79d2\u8ba1\u7b97\u7684\u8fc7\u671f\u65f6\u95f4\n\n            if ((expiretime = rdbLoadTime(&amp;rdb)) == -1)\n                goto eoferr;\n\n            \/* We read the time so we need to read the object type again. \n             *\n             * \u5728\u8fc7\u671f\u65f6\u95f4\u4e4b\u540e\u4f1a\u8ddf\u7740\u4e00\u4e2a\u952e\u503c\u5bf9\uff0c\u6211\u4eec\u8981\u8bfb\u5165\u8fd9\u4e2a\u952e\u503c\u5bf9\u7684\u7c7b\u578b\n             *\/\n            if ((type = rdbLoadType(&amp;rdb)) == -1)\n                goto eoferr;\n\n            \/* the EXPIRETIME opcode specifies time in seconds, so convert\n             * into milliseconds. \n             *\n             * \u5c06\u683c\u5f0f\u8f6c\u6362\u4e3a\u6beb\u79d2*\/\n            expiretime *= 1000;\n        }\n        else if (type == REDIS_RDB_OPCODE_EXPIRETIME_MS)\n        {\n\n            \/\/ \u4ee5\u6beb\u79d2\u8ba1\u7b97\u7684\u8fc7\u671f\u65f6\u95f4\n\n            \/* Milliseconds precision expire times introduced with RDB\n             * version 3. *\/\n            if ((expiretime = rdbLoadMillisecondTime(&amp;rdb)) == -1)\n                goto eoferr;\n\n            \/* We read the time so we need to read the object type again.\n             *\n             * \u5728\u8fc7\u671f\u65f6\u95f4\u4e4b\u540e\u4f1a\u8ddf\u7740\u4e00\u4e2a\u952e\u503c\u5bf9\uff0c\u6211\u4eec\u8981\u8bfb\u5165\u8fd9\u4e2a\u952e\u503c\u5bf9\u7684\u7c7b\u578b\n             *\/\n            if ((type = rdbLoadType(&amp;rdb)) == -1)\n                goto eoferr;\n        }\n\n        \/\/ \u8bfb\u5165\u6570\u636e EOF \uff08\u4e0d\u662f rdb \u6587\u4ef6\u7684 EOF\uff09\n        if (type == REDIS_RDB_OPCODE_EOF)\n            break;\n\n        \/* Handle SELECT DB opcode as a special case \n         *\n         * \u8bfb\u5165\u5207\u6362\u6570\u636e\u5e93\u6307\u793a\n         *\/\n        if (type == REDIS_RDB_OPCODE_SELECTDB)\n        {\n\n            \/\/ \u8bfb\u5165\u6570\u636e\u5e93\u53f7\u7801\n            if ((dbid = rdbLoadLen(&amp;rdb, NULL)) == REDIS_RDB_LENERR)\n                goto eoferr;\n\n            \/\/ \u68c0\u67e5\u6570\u636e\u5e93\u53f7\u7801\u7684\u6b63\u786e\u6027\n            if (dbid &gt;= (unsigned)server.dbnum)\n            {\n                redisLog(REDIS_WARNING, \"FATAL: Data file was created with a Redis server configured to handle more than %d databases. Exiting\\n\", server.dbnum);\n                exit(1);\n            }\n\n            \/\/ \u5728\u7a0b\u5e8f\u5185\u5bb9\u5207\u6362\u6570\u636e\u5e93\n            db = server.db + dbid;\n\n            \/\/ \u8df3\u8fc7\n            continue;\n        }\n\n        \/* Read key \n         *\n         * \u8bfb\u5165\u952e\n         *\/\n        if ((key = rdbLoadStringObject(&amp;rdb)) == NULL)\n            goto eoferr;\n\n        \/* Read value \n         *\n         * \u8bfb\u5165\u503c\n         *\/\n        if ((val = rdbLoadObject(type, &amp;rdb)) == NULL)\n            goto eoferr;\n\n        \/* Check if the key already expired. This function is used when loading\n         * an RDB file from disk, either at startup, or when an RDB was\n         * received from the master. In the latter case, the master is\n         * responsible for key expiry. If we would expire keys here, the\n         * snapshot taken by the master may not be reflected on the slave. \n         *\n         * \u5982\u679c\u670d\u52a1\u5668\u4e3a\u4e3b\u8282\u70b9\u7684\u8bdd\uff0c\n         * \u90a3\u4e48\u5728\u952e\u5df2\u7ecf\u8fc7\u671f\u7684\u65f6\u5019\uff0c\u4e0d\u518d\u5c06\u5b83\u4eec\u5173\u8054\u5230\u6570\u636e\u5e93\u4e2d\u53bb\n         *\/\n        if (server.masterhost == NULL &amp;&amp; expiretime != -1 &amp;&amp; expiretime &lt; now)\n        {\n            decrRefCount(key);\n            decrRefCount(val);\n            \/\/ \u8df3\u8fc7\n            continue;\n        }\n\n        \/* Add the new object in the hash table \n         *\n         * \u5c06\u952e\u503c\u5bf9\u5173\u8054\u5230\u6570\u636e\u5e93\u4e2d\n         *\/\n        dbAdd(db, key, val);\n\n        \/* Set the expire time if needed \n         *\n         * \u8bbe\u7f6e\u8fc7\u671f\u65f6\u95f4\n         *\/\n        if (expiretime != -1)\n            setExpire(db, key, expiretime);\n\n        decrRefCount(key);\n    }\n\n    \/* Verify the checksum if RDB version is &gt;= 5 \n     *\n     * \u5982\u679c RDB \u7248\u672c &gt;= 5 \uff0c\u90a3\u4e48\u6bd4\u5bf9\u6821\u9a8c\u548c\n     *\/\n    if (rdbver &gt;= 5 &amp;&amp; server.rdb_checksum)\n    {\n        uint64_t cksum, expected = rdb.cksum;\n\n        \/\/ \u8bfb\u5165\u6587\u4ef6\u7684\u6821\u9a8c\u548c\n        if (rioRead(&amp;rdb, &amp;cksum, 8) == 0)\n            goto eoferr;\n        memrev64ifbe(&amp;cksum);\n\n        \/\/ \u6bd4\u5bf9\u6821\u9a8c\u548c\n        if (cksum == 0)\n        {\n            redisLog(REDIS_WARNING, \"RDB file was saved with checksum disabled: no check performed.\");\n        }\n        else if (cksum != expected)\n        {\n            redisLog(REDIS_WARNING, \"Wrong RDB checksum. Aborting now.\");\n            exit(1);\n        }\n    }\n\n    \/\/ \u5173\u95ed RDB\n    fclose(fp);\n\n    \/\/ \u670d\u52a1\u5668\u4ece\u8f7d\u5165\u72b6\u6001\u4e2d\u9000\u51fa\n    stopLoading();\n\n    return REDIS_OK;\n\neoferr: \/* unexpected end of file is handled here with a fatal exit *\/\n    redisLog(REDIS_WARNING, \"Short read or OOM loading DB. Unrecoverable error, aborting now.\");\n    exit(1);\n    return REDIS_ERR; \/* Just to avoid warning *\/\n}\n<\/code><\/pre>\n\n\n\n<p><a href=\"https:\/\/download.redis.io\/releases\/redis-3.0.0.tar.gz\" target=\"_blank\" rel=\"noopener\">\u57fa\u4e8e\u7248\u672c3.0.0\u7248\u672c,<\/a>\u70b9\u51fb\u4e0b\u8f7dhttps:\/\/download.redis.io\/releases\/redis-3.0.0.tar.gz<\/p>\n\n\n\n<p><a href=\"https:\/\/www.ccagml.com\/?p=432\">\u672c\u6587\u5730\u5740<\/a>\uff0chttps:\/\/www.ccagml.com\/?p=432<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u7ae0\u6765\u770b\u6301\u4e45\u5316RDB\u3001AOF RDB\uff1a\u751f\u6210\u6307\u5b9a\u65f6\u95f4\u95f4\u9694\u5185\u7684&nbsp;Redis&nbsp;\u5185\u5b58\u4e2d\u6570\u636e\u5feb\u7167\uff0c\u662f<a href=\"https:\/\/www.ccagml.com\/?p=432\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">redis\u6e90\u7801\u4ecemain\u5f00\u59cb17<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[31,22],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts\/432"}],"collection":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=432"}],"version-history":[{"count":3,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts\/432\/revisions"}],"predecessor-version":[{"id":440,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts\/432\/revisions\/440"}],"wp:attachment":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=432"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=432"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=432"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}