{"id":437,"date":"2020-06-20T21:26:00","date_gmt":"2020-06-20T13:26:00","guid":{"rendered":"https:\/\/www.ccagml.com\/?p=437"},"modified":"2021-06-21T21:32:48","modified_gmt":"2021-06-21T13:32:48","slug":"redis%e6%ba%90%e7%a0%81%e4%bb%8emain%e5%bc%80%e5%a7%8b18","status":"publish","type":"post","link":"https:\/\/www.ccagml.com\/?p=437","title":{"rendered":"redis\u6e90\u7801\u4ecemain\u5f00\u59cb18"},"content":{"rendered":"\n<p>aof\u4fdd\u5b58<br>aof\u662fredis\u7684\u4e00\u79cd\u6301\u4e45\u5316\u65b9\u5f0f,\u53ef\u4ee5\u6839\u636e\u914d\u7f6e\u81ea\u52a8\u89e6\u53d1\u4fdd\u5b58,\u4e5f\u53ef\u4ee5\u624b\u52a8\u6267\u884c\u4fdd\u5b58<br>\/\/\u5728\u914d\u7f6e\u4e2d<br>appendonly yes \/\/\u6253\u5f00aof\u4fdd\u5b58<br>appendfilename &#8220;aof111.aof&#8221; \/\/ \u8bbe\u7f6eaof\u62a5\u9519\u8def\u5f84<br>appendfsync always \/\/ \u6bcf\u6b21\u64cd\u4f5c\u90fdaof\u4fdd\u5b58<br>appendfsync everysec \/\/ \u6bcf\u79d2aof\u4fdd\u5b58<br>appendfsync no \/\/ \u4e0d\u4fdd\u5b58<br>1.\u624b\u52a8\u4fdd\u5b58,\u5f53\u5ba2\u6237\u7aef\u6267\u884cbgrewriteaof\u547d\u4ee4,redis\u670d\u52a1\u7aef\u4f1a\u6267\u884cbgrewriteaofCommand\u65b9\u6cd5\u5f00\u59cb\u76f8\u5173\u7684\u4fdd\u5b58\u903b\u8f91<br>2.\u81ea\u52a8\u4fdd\u5b58,\u5f53\u5ba2\u6237\u7aef\u4f20\u6765\u547d\u4ee4\u540e,redis\u5728call\u65b9\u6cd5\u6267\u884cc-&gt;cmd-&gt;proc\u547d\u4ee4\u540e,\u4f1a\u5bf9\u547d\u4ee4\u8fdb\u884c\u8bb0\u5f55,\u5c06\u547d\u4ee4\u5b58\u653e\u5230server.aof_buf\u4e2d,\u5f53\u4e0b\u4e00\u4e2a\u4e8b\u4ef6\u5230\u6765\u65f6(beforeSleep)\u6216\u8005\u670d\u52a1\u5668\u6bcf\u6beb\u79d2\u7684\u5faa\u73af(serverCron)\u4f1a\u6839\u636e\u914d\u7f6e\u770b\u662f\u5426\u89e6\u53d1\u5199\u6587\u4ef6<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n\/\/1.beforeSleep\u624b\u52a8\u4fdd\u5b58\nvoid bgrewriteaofCommand(redisClient *c)\n{\n    if (server.aof_child_pid != -1)\n    {\n        addReplyError(c, \"Background append only file rewriting already in progress\");\n    }\n    else if (server.rdb_child_pid != -1)\n    {\n        server.aof_rewrite_scheduled = 1;\n        addReplyStatus(c, \"Background append only file rewriting scheduled\");\n    }\n    else if (rewriteAppendOnlyFileBackground() == REDIS_OK)\n    {\n        addReplyStatus(c, \"Background append only file rewriting started\");\n    }\n    else\n    {\n        addReply(c, shared.err);\n    }\n}\n\/\/ \u540e\u53f0\u4fdd\u5b58\nint rewriteAppendOnlyFileBackground(void)\n{\n    pid_t childpid;\n    long long start;\n\n    \/\/ \u5df2\u7ecf\u6709\u8fdb\u7a0b\u5728\u8fdb\u884c AOF \u91cd\u5199\u4e86\n    if (server.aof_child_pid != -1)\n        return REDIS_ERR;\n\n    \/\/ \u8bb0\u5f55 fork \u5f00\u59cb\u524d\u7684\u65f6\u95f4\uff0c\u8ba1\u7b97 fork \u8017\u65f6\u7528\n    start = ustime();\n\n    if ((childpid = fork()) == 0)\n    {\n        char tmpfile&#91;256];\n\n        \/* Child *\/\n\n        \/\/ \u5173\u95ed\u7f51\u7edc\u8fde\u63a5 fd\n        closeListeningSockets(0);\n\n        \/\/ \u4e3a\u8fdb\u7a0b\u8bbe\u7f6e\u540d\u5b57\uff0c\u65b9\u4fbf\u8bb0\u8ba4\n        redisSetProcTitle(\"redis-aof-rewrite\");\n\n        \/\/ \u521b\u5efa\u4e34\u65f6\u6587\u4ef6\uff0c\u5e76\u8fdb\u884c AOF \u91cd\u5199\n        snprintf(tmpfile, 256, \"temp-rewriteaof-bg-%d.aof\", (int)getpid());\n        if (rewriteAppendOnlyFile(tmpfile) == REDIS_OK)\n        {\n            size_t private_dirty = zmalloc_get_private_dirty();\n\n            if (private_dirty)\n            {\n                redisLog(REDIS_NOTICE,\n                         \"AOF rewrite: %zu MB of memory used by copy-on-write\",\n                         private_dirty \/ (1024 * 1024));\n            }\n            \/\/ \u53d1\u9001\u91cd\u5199\u6210\u529f\u4fe1\u53f7\n            exitFromChild(0);\n        }\n        else\n        {\n            \/\/ \u53d1\u9001\u91cd\u5199\u5931\u8d25\u4fe1\u53f7\n            exitFromChild(1);\n        }\n    }\n    else\n    {\n        \/* Parent *\/\n        \/\/ \u8bb0\u5f55\u6267\u884c fork \u6240\u6d88\u8017\u7684\u65f6\u95f4\n        server.stat_fork_time = ustime() - start;\n\n        if (childpid == -1)\n        {\n            redisLog(REDIS_WARNING,\n                     \"Can't rewrite append only file in background: fork: %s\",\n                     strerror(errno));\n            return REDIS_ERR;\n        }\n\n        redisLog(REDIS_NOTICE,\n                 \"Background append only file rewriting started by pid %d\", childpid);\n\n        \/\/ \u8bb0\u5f55 AOF \u91cd\u5199\u7684\u4fe1\u606f\n        server.aof_rewrite_scheduled = 0;\n        server.aof_rewrite_time_start = time(NULL);\n        server.aof_child_pid = childpid;\n\n        \/\/ \u5173\u95ed\u5b57\u5178\u81ea\u52a8 rehash\n        updateDictResizePolicy();\n\n        \/* We set appendseldb to -1 in order to force the next call to the\n         * feedAppendOnlyFile() to issue a SELECT command, so the differences\n         * accumulated by the parent into server.aof_rewrite_buf will start\n         * with a SELECT statement and it will be safe to merge. \n         *\n         * \u5c06 aof_selected_db \u8bbe\u4e3a -1 \uff0c\n         * \u5f3a\u5236\u8ba9 feedAppendOnlyFile() \u4e0b\u6b21\u6267\u884c\u65f6\u5f15\u53d1\u4e00\u4e2a SELECT \u547d\u4ee4\uff0c\n         * \u4ece\u800c\u786e\u4fdd\u4e4b\u540e\u65b0\u6dfb\u52a0\u7684\u547d\u4ee4\u4f1a\u8bbe\u7f6e\u5230\u6b63\u786e\u7684\u6570\u636e\u5e93\u4e2d\n         *\/\n        server.aof_selected_db = -1;\n        replicationScriptCacheFlush();\n        return REDIS_OK;\n    }\n    return REDIS_OK; \/* unreached *\/\n}\n\/\/\u5177\u4f53\u91cd\u5199\u903b\u8f91\nint rewriteAppendOnlyFile(char *filename)\n{\n    dictIterator *di = NULL;\n    dictEntry *de;\n    rio aof;\n    FILE *fp;\n    char tmpfile&#91;256];\n    int j;\n    long long now = mstime();\n\n    \/* Note that we have to use a different temp name here compared to the\n     * one used by rewriteAppendOnlyFileBackground() function. \n     *\n     * \u521b\u5efa\u4e34\u65f6\u6587\u4ef6\n     *\n     * \u6ce8\u610f\u8fd9\u91cc\u521b\u5efa\u7684\u6587\u4ef6\u540d\u548c rewriteAppendOnlyFileBackground() \u521b\u5efa\u7684\u6587\u4ef6\u540d\u7a0d\u6709\u4e0d\u540c\n     *\/\n    snprintf(tmpfile, 256, \"temp-rewriteaof-%d.aof\", (int)getpid());\n    fp = fopen(tmpfile, \"w\");\n    if (!fp)\n    {\n        redisLog(REDIS_WARNING, \"Opening the temp file for AOF rewrite in rewriteAppendOnlyFile(): %s\", strerror(errno));\n        return REDIS_ERR;\n    }\n\n    \/\/ \u521d\u59cb\u5316\u6587\u4ef6 io\n    rioInitWithFile(&amp;aof, fp);\n\n    \/\/ \u8bbe\u7f6e\u6bcf\u5199\u5165 REDIS_AOF_AUTOSYNC_BYTES \u5b57\u8282\n    \/\/ \u5c31\u6267\u884c\u4e00\u6b21 FSYNC\n    \/\/ \u9632\u6b62\u7f13\u5b58\u4e2d\u79ef\u7d2f\u592a\u591a\u547d\u4ee4\u5185\u5bb9\uff0c\u9020\u6210 I\/O \u963b\u585e\u65f6\u95f4\u8fc7\u957f\n    if (server.aof_rewrite_incremental_fsync)\n        rioSetAutoSync(&amp;aof, REDIS_AOF_AUTOSYNC_BYTES);\n\n    \/\/ \u904d\u5386\u6240\u6709\u6570\u636e\u5e93\n    for (j = 0; j &lt; server.dbnum; j++)\n    {\n\n        char selectcmd&#91;] = \"*2\\r\\n<span class=\"katex math inline\">6\\r\\nSELECT\\r\\n\";\n\n        redisDb *db = server.db + j;\n\n        \/\/ \u6307\u5411\u952e\u7a7a\u95f4\n        dict *d = db-&gt;dict;\n        if (dictSize(d) == 0)\n            continue;\n\n        \/\/ \u521b\u5efa\u952e\u7a7a\u95f4\u8fed\u4ee3\u5668\n        di = dictGetSafeIterator(d);\n        if (!di)\n        {\n            fclose(fp);\n            return REDIS_ERR;\n        }\n\n        \/* SELECT the new DB         *\n         * \u9996\u5148\u5199\u5165 SELECT \u547d\u4ee4\uff0c\u786e\u4fdd\u4e4b\u540e\u7684\u6570\u636e\u4f1a\u88ab\u63d2\u5165\u5230\u6b63\u786e\u7684\u6570\u636e\u5e93\u4e0a\n         *\/\n        if (rioWrite(&amp;aof, selectcmd, sizeof(selectcmd) - 1) == 0)\n            goto werr;\n        if (rioWriteBulkLongLong(&amp;aof, j) == 0)\n            goto werr;\n\n        \/* Iterate this DB writing every entry         *\n         * \u904d\u5386\u6570\u636e\u5e93\u6240\u6709\u952e\uff0c\u5e76\u901a\u8fc7\u547d\u4ee4\u5c06\u5b83\u4eec\u7684\u5f53\u524d\u72b6\u6001\uff08\u503c\uff09\u8bb0\u5f55\u5230\u65b0 AOF \u6587\u4ef6\u4e2d\n         *\/\n        while ((de = dictNext(di)) != NULL)\n        {\n            sds keystr;\n            robj key, *o;\n            long long expiretime;\n\n            \/\/ \u53d6\u51fa\u952e\n            keystr = dictGetKey(de);\n\n            \/\/ \u53d6\u51fa\u503c\n            o = dictGetVal(de);\n            initStaticStringObject(key, keystr);\n\n            \/\/ \u53d6\u51fa\u8fc7\u671f\u65f6\u95f4\n            expiretime = getExpire(db, &amp;key);\n\n            \/* If this key is already expired skip it             *\n             * \u5982\u679c\u952e\u5df2\u7ecf\u8fc7\u671f\uff0c\u90a3\u4e48\u8df3\u8fc7\u5b83\uff0c\u4e0d\u4fdd\u5b58\n             *\/\n            if (expiretime != -1 &amp;&amp; expiretime<now)\n                continue;\n\n            \/* Save the key and associated value             *\n             * \u6839\u636e\u503c\u7684\u7c7b\u578b\uff0c\u9009\u62e9\u9002\u5f53\u7684\u547d\u4ee4\u6765\u4fdd\u5b58\u503c\n             *\/\n            if (o-&gt;type == REDIS_STRING)\n            {\n                \/* Emit a SET command *\/\n                char cmd&#91;] = \"*3\\r\\n<\/span>3\\r\\nSET\\r\\n\";\n                if (rioWrite(&amp;aof, cmd, sizeof(cmd) - 1) == 0)\n                    goto werr;\n                \/* Key and value *\/\n                if (rioWriteBulkObject(&amp;aof, &amp;key) == 0)\n                    goto werr;\n                if (rioWriteBulkObject(&amp;aof, o) == 0)\n                    goto werr;\n            }\n            else if (o-&gt;type == REDIS_LIST)\n            {\n                if (rewriteListObject(&amp;aof, &amp;key, o) == 0)\n                    goto werr;\n            }\n            else if (o-&gt;type == REDIS_SET)\n            {\n                if (rewriteSetObject(&amp;aof, &amp;key, o) == 0)\n                    goto werr;\n            }\n            else if (o-&gt;type == REDIS_ZSET)\n            {\n                if (rewriteSortedSetObject(&amp;aof, &amp;key, o) == 0)\n                    goto werr;\n            }\n            else if (o-&gt;type == REDIS_HASH)\n            {\n                if (rewriteHashObject(&amp;aof, &amp;key, o) == 0)\n                    goto werr;\n            }\n            else\n            {\n                redisPanic(\"Unknown object type\");\n            }\n\n            \/* Save the expire time \n             *\n             * \u4fdd\u5b58\u952e\u7684\u8fc7\u671f\u65f6\u95f4\n             *\/\n            if (expiretime != -1)\n            {\n                char cmd&#91;] = \"*3\\r\\n<span class=\"katex math inline\">9\\r\\nPEXPIREAT\\r\\n\";\n\n                \/\/ \u5199\u5165 PEXPIREAT expiretime \u547d\u4ee4\n                if (rioWrite(&amp;aof, cmd, sizeof(cmd) - 1) == 0)\n                    goto werr;\n                if (rioWriteBulkObject(&amp;aof, &amp;key) == 0)\n                    goto werr;\n                if (rioWriteBulkLongLong(&amp;aof, expiretime) == 0)\n                    goto werr;\n            }\n        }\n\n        \/\/ \u91ca\u653e\u8fed\u4ee3\u5668\n        dictReleaseIterator(di);\n    }\n\n    \/* Make sure data will not remain on the OS's output buffers *\/\n    \/\/ \u51b2\u6d17\u5e76\u5173\u95ed\u65b0 AOF \u6587\u4ef6\n    if (fflush(fp) == EOF)\n        goto werr;\n    if (aof_fsync(fileno(fp)) == -1)\n        goto werr;\n    if (fclose(fp) == EOF)\n        goto werr;\n\n    \/* Use RENAME to make sure the DB file is changed atomically only\n     * if the generate DB file is ok.     *\n     * \u539f\u5b50\u5730\u6539\u540d\uff0c\u7528\u91cd\u5199\u540e\u7684\u65b0 AOF \u6587\u4ef6\u8986\u76d6\u65e7 AOF \u6587\u4ef6\n     *\/\n    if (rename(tmpfile, filename) == -1)\n    {\n        redisLog(REDIS_WARNING, \"Error moving temp append only file on the final destination: %s\", strerror(errno));\n        unlink(tmpfile);\n        return REDIS_ERR;\n    }\n\n    redisLog(REDIS_NOTICE, \"SYNC append only file rewrite performed\");\n\n    return REDIS_OK;\n\nwerr:\n    fclose(fp);\n    unlink(tmpfile);\n    redisLog(REDIS_WARNING, \"Write error writing append only file on disk: %s\", strerror(errno));\n    if (di)\n        dictReleaseIterator(di);\n    return REDIS_ERR;\n}\n\n\/\/ 2.\u81ea\u52a8\u5f00\u542f\u7684aof\n\/\/redis.c\nvoid call(redisClient *c, int flags)\n{\n    \/\/ \u6267\u884c\u5b9e\u73b0\u51fd\u6570\n    c-&gt;cmd-&gt;proc(c);\n    \/\/ \u5c06\u547d\u4ee4\u590d\u5236\u5230 AOF \u548c slave \u8282\u70b9\n    if (flags&REDIS_CALL_PROPAGATE)\n    {\n        int flags = REDIS_PROPAGATE_NONE;\n\n        \/\/ \u5f3a\u5236 REPL \u4f20\u64ad\n        if (c-&gt;flags&REDIS_FORCE_REPL)\n            flags |= REDIS_PROPAGATE_REPL;\n\n        \/\/ \u5f3a\u5236 AOF \u4f20\u64ad\n        if (c-&gt;flags&REDIS_FORCE_AOF)\n            flags |= REDIS_PROPAGATE_AOF;\n\n        \/\/ \u5982\u679c\u6570\u636e\u5e93\u6709\u88ab\u4fee\u6539\uff0c\u90a3\u4e48\u542f\u7528 REPL \u548c AOF \u4f20\u64ad\n        if (dirty)\n            flags |= (REDIS_PROPAGATE_REPL | REDIS_PROPAGATE_AOF);\n\n        if (flags != REDIS_PROPAGATE_NONE)\n            propagate(c-&gt;cmd, c-&gt;db-&gt;id, c-&gt;argv, c-&gt;argc, flags);\n    }\n}\nvoid propagate(struct redisCommand *cmd, int dbid, robj **argv, int argc,\n               int flags)\n{\n    \/\/ \u4f20\u64ad\u5230 AOF\n    if (server.aof_state != REDIS_AOF_OFF &amp;&amp; flags&REDIS_PROPAGATE_AOF)\n        feedAppendOnlyFile(cmd, dbid, argv, argc);\n\n    \/\/ \u4f20\u64ad\u5230 slave\n    if (flags&REDIS_PROPAGATE_REPL)\n        replicationFeedSlaves(server.slaves, dbid, argv, argc);\n}\n\n\/*\n * \u5c06\u547d\u4ee4\u8ffd\u52a0\u5230 AOF \u6587\u4ef6\u4e2d\uff0c\n * \u5982\u679c AOF \u91cd\u5199\u6b63\u5728\u8fdb\u884c\uff0c\u90a3\u4e48\u4e5f\u5c06\u547d\u4ee4\u8ffd\u52a0\u5230 AOF \u91cd\u5199\u7f13\u5b58\u4e2d\u3002\n *\/\nvoid feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv, int argc)\n{\n    sds buf = sdsempty();\n    robj *tmpargv&#91;3];\n\n    \/* The DB this command was targeting is not the same as the last command\n     * we appendend. To issue a SELECT command is needed.     *\n     * \u4f7f\u7528 SELECT \u547d\u4ee4\uff0c\u663e\u5f0f\u8bbe\u7f6e\u6570\u636e\u5e93\uff0c\u786e\u4fdd\u4e4b\u540e\u7684\u547d\u4ee4\u88ab\u8bbe\u7f6e\u5230\u6b63\u786e\u7684\u6570\u636e\u5e93\n     *\/\n    if (dictid != server.aof_selected_db)\n    {\n        char seldb&#91;64];\n\n        snprintf(seldb, sizeof(seldb), \"%d\", dictid);\n        buf = sdscatprintf(buf, \"*2\\r\\n<\/span>6\\r\\nSELECT\\r\\n$%lu\\r\\n%s\\r\\n\",\n                           (unsigned long)strlen(seldb), seldb);\n\n        server.aof_selected_db = dictid;\n    }\n\n    \/\/ EXPIRE \u3001 PEXPIRE \u548c EXPIREAT \u547d\u4ee4\n    if (cmd-&gt;proc == expireCommand || cmd-&gt;proc == pexpireCommand ||\n        cmd-&gt;proc == expireatCommand)\n    {\n        \/* Translate EXPIRE\/PEXPIRE\/EXPIREAT into PEXPIREAT \n         *\n         * \u5c06 EXPIRE \u3001 PEXPIRE \u548c EXPIREAT \u90fd\u7ffb\u8bd1\u6210 PEXPIREAT\n         *\/\n        buf = catAppendOnlyExpireAtCommand(buf, cmd, argv&#91;1], argv&#91;2]);\n\n        \/\/ SETEX \u548c PSETEX \u547d\u4ee4\n    }\n    else if (cmd-&gt;proc == setexCommand || cmd-&gt;proc == psetexCommand)\n    {\n        \/* Translate SETEX\/PSETEX to SET and PEXPIREAT \n         *\n         * \u5c06\u4e24\u4e2a\u547d\u4ee4\u90fd\u7ffb\u8bd1\u6210 SET \u548c PEXPIREAT\n         *\/\n\n        \/\/ SET\n        tmpargv&#91;0] = createStringObject(\"SET\", 3);\n        tmpargv&#91;1] = argv&#91;1];\n        tmpargv&#91;2] = argv&#91;3];\n        buf = catAppendOnlyGenericCommand(buf, 3, tmpargv);\n\n        \/\/ PEXPIREAT\n        decrRefCount(tmpargv&#91;0]);\n        buf = catAppendOnlyExpireAtCommand(buf, cmd, argv&#91;1], argv&#91;2]);\n\n        \/\/ \u5176\u4ed6\u547d\u4ee4\n    }\n    else\n    {\n        \/* All the other commands don't need translation or need the\n         * same translation already operated in the command vector\n         * for the replication itself. *\/\n        buf = catAppendOnlyGenericCommand(buf, argc, argv);\n    }\n\n    \/* Append to the AOF buffer. This will be flushed on disk just before\n     * of re-entering the event loop, so before the client will get a\n     * positive reply about the operation performed. \n     *\n     * \u5c06\u547d\u4ee4\u8ffd\u52a0\u5230 AOF \u7f13\u5b58\u4e2d\uff0c\n     * \u5728\u91cd\u65b0\u8fdb\u5165\u4e8b\u4ef6\u5faa\u73af\u4e4b\u524d\uff0c\u8fd9\u4e9b\u547d\u4ee4\u4f1a\u88ab\u51b2\u6d17\u5230\u78c1\u76d8\u4e0a\uff0c\n     * \u5e76\u5411\u5ba2\u6237\u7aef\u8fd4\u56de\u4e00\u4e2a\u56de\u590d\u3002\n     *\/\n    if (server.aof_state == REDIS_AOF_ON)\n        server.aof_buf = sdscatlen(server.aof_buf, buf, sdslen(buf));\n\n    \/* If a background append only file rewriting is in progress we want to\n     * accumulate the differences between the child DB and the current one\n     * in a buffer, so that when the child process will do its work we\n     * can append the differences to the new append only file. \n     *\n     * \u5982\u679c BGREWRITEAOF \u6b63\u5728\u8fdb\u884c\uff0c\n     * \u90a3\u4e48\u6211\u4eec\u8fd8\u9700\u8981\u5c06\u547d\u4ee4\u8ffd\u52a0\u5230\u91cd\u5199\u7f13\u5b58\u4e2d\uff0c\n     * \u4ece\u800c\u8bb0\u5f55\u5f53\u524d\u6b63\u5728\u91cd\u5199\u7684 AOF \u6587\u4ef6\u548c\u6570\u636e\u5e93\u5f53\u524d\u72b6\u6001\u7684\u5dee\u5f02\u3002\n     *\/\n    if (server.aof_child_pid != -1)\n        aofRewriteBufferAppend((unsigned char *)buf, sdslen(buf));\n\n    \/\/ \u91ca\u653e\n    sdsfree(buf);\n}\n\n\/\/ \u5c06aof_buf\u4e2d\u7684\u547d\u4ee4\u5237\u5230\u6587\u4ef6\nvoid flushAppendOnlyFile(int force)\n{\n    ssize_t nwritten;\n    int sync_in_progress = 0;\n\n    \/\/ \u7f13\u51b2\u533a\u4e2d\u6ca1\u6709\u4efb\u4f55\u5185\u5bb9\uff0c\u76f4\u63a5\u8fd4\u56de\n    if (sdslen(server.aof_buf) == 0)\n        return;\n\n    \/\/ \u7b56\u7565\u4e3a\u6bcf\u79d2 FSYNC\n    if (server.aof_fsync == AOF_FSYNC_EVERYSEC)\n        \/\/ \u662f\u5426\u6709 SYNC \u6b63\u5728\u540e\u53f0\u8fdb\u884c\uff1f\n        sync_in_progress = bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC) != 0;\n\n    \/\/ \u6bcf\u79d2 fsync \uff0c\u5e76\u4e14\u5f3a\u5236\u5199\u5165\u4e3a\u5047\n    if (server.aof_fsync == AOF_FSYNC_EVERYSEC &amp;&amp; !force)\n    {\n\n        \/* With this append fsync policy we do background fsyncing.\n         *\n         * \u5f53 fsync \u7b56\u7565\u4e3a\u6bcf\u79d2\u949f\u4e00\u6b21\u65f6\uff0c fsync \u5728\u540e\u53f0\u6267\u884c\u3002\n         *\n         * If the fsync is still in progress we can try to delay\n         * the write for a couple of seconds. \n         *\n         * \u5982\u679c\u540e\u53f0\u4ecd\u5728\u6267\u884c FSYNC \uff0c\u90a3\u4e48\u6211\u4eec\u53ef\u4ee5\u5ef6\u8fdf\u5199\u64cd\u4f5c\u4e00\u4e24\u79d2\n         * \uff08\u5982\u679c\u5f3a\u5236\u6267\u884c write \u7684\u8bdd\uff0c\u670d\u52a1\u5668\u4e3b\u7ebf\u7a0b\u5c06\u963b\u585e\u5728 write \u4e0a\u9762\uff09\n         *\/\n        if (sync_in_progress)\n        {\n\n            \/\/ \u6709 fsync \u6b63\u5728\u540e\u53f0\u8fdb\u884c \u3002\u3002\u3002\n\n            if (server.aof_flush_postponed_start == 0)\n            {\n                \/* No previous write postponinig, remember that we are\n                 * postponing the flush and return. \n                 *\n                 * \u524d\u9762\u6ca1\u6709\u63a8\u8fdf\u8fc7 write \u64cd\u4f5c\uff0c\u8fd9\u91cc\u5c06\u63a8\u8fdf\u5199\u64cd\u4f5c\u7684\u65f6\u95f4\u8bb0\u5f55\u4e0b\u6765\n                 * \u7136\u540e\u5c31\u8fd4\u56de\uff0c\u4e0d\u6267\u884c write \u6216\u8005 fsync\n                 *\/\n                server.aof_flush_postponed_start = server.unixtime;\n                return;\n            }\n            else if (server.unixtime - server.aof_flush_postponed_start &lt; 2)\n            {\n                \/* We were already waiting for fsync to finish, but for less\n                 * than two seconds this is still ok. Postpone again. \n                 *\n                 * \u5982\u679c\u4e4b\u524d\u5df2\u7ecf\u56e0\u4e3a fsync \u800c\u63a8\u8fdf\u4e86 write \u64cd\u4f5c\n                 * \u4f46\u662f\u63a8\u8fdf\u7684\u65f6\u95f4\u4e0d\u8d85\u8fc7 2 \u79d2\uff0c\u90a3\u4e48\u76f4\u63a5\u8fd4\u56de\n                 * \u4e0d\u6267\u884c write \u6216\u8005 fsync\n                 *\/\n                return;\n            }\n\n            \/* Otherwise fall trough, and go write since we can't wait\n             * over two seconds. \n             *\n             * \u5982\u679c\u540e\u53f0\u8fd8\u6709 fsync \u5728\u6267\u884c\uff0c\u5e76\u4e14 write \u5df2\u7ecf\u63a8\u8fdf &gt;= 2 \u79d2\n             * \u90a3\u4e48\u6267\u884c\u5199\u64cd\u4f5c\uff08write \u5c06\u88ab\u963b\u585e\uff09\n             *\/\n            server.aof_delayed_fsync++;\n            redisLog(REDIS_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.\");\n        }\n    }\n\n    \/* If you are following this code path, then we are going to write so\n     * set reset the postponed flush sentinel to zero. \n     *\n     * \u6267\u884c\u5230\u8fd9\u91cc\uff0c\u7a0b\u5e8f\u4f1a\u5bf9 AOF \u6587\u4ef6\u8fdb\u884c\u5199\u5165\u3002\n     *\n     * \u6e05\u96f6\u5ef6\u8fdf write \u7684\u65f6\u95f4\u8bb0\u5f55\n     *\/\n    server.aof_flush_postponed_start = 0;\n\n    \/* We want to perform a single write. This should be guaranteed atomic\n     * at least if the filesystem we are writing is a real physical one.\n     *\n     * \u6267\u884c\u5355\u4e2a write \u64cd\u4f5c\uff0c\u5982\u679c\u5199\u5165\u8bbe\u5907\u662f\u7269\u7406\u7684\u8bdd\uff0c\u90a3\u4e48\u8fd9\u4e2a\u64cd\u4f5c\u5e94\u8be5\u662f\u539f\u5b50\u7684\n     *\n     * While this will save us against the server being killed I don't think\n     * there is much to do about the whole server stopping for power problems\n     * or alike \n     *\n     * \u5f53\u7136\uff0c\u5982\u679c\u51fa\u73b0\u50cf\u7535\u6e90\u4e2d\u65ad\u8fd9\u6837\u7684\u4e0d\u53ef\u6297\u73b0\u8c61\uff0c\u90a3\u4e48 AOF \u6587\u4ef6\u4e5f\u662f\u53ef\u80fd\u4f1a\u51fa\u73b0\u95ee\u9898\u7684\n     * \u8fd9\u65f6\u5c31\u8981\u7528 redis-check-aof \u7a0b\u5e8f\u6765\u8fdb\u884c\u4fee\u590d\u3002\n     *\/\n    nwritten = write(server.aof_fd, server.aof_buf, sdslen(server.aof_buf));\n    if (nwritten != (signed)sdslen(server.aof_buf))\n    {\n\n        static time_t last_write_error_log = 0;\n        int can_log = 0;\n\n        \/* Limit logging rate to 1 line per AOF_WRITE_LOG_ERROR_RATE seconds. *\/\n        \/\/ \u5c06\u65e5\u5fd7\u7684\u8bb0\u5f55\u9891\u7387\u9650\u5236\u5728\u6bcf\u884c AOF_WRITE_LOG_ERROR_RATE \u79d2\n        if ((server.unixtime - last_write_error_log) &gt; AOF_WRITE_LOG_ERROR_RATE)\n        {\n            can_log = 1;\n            last_write_error_log = server.unixtime;\n        }\n\n        \/* Lof the AOF write error and record the error code. *\/\n        \/\/ \u5982\u679c\u5199\u5165\u51fa\u9519\uff0c\u90a3\u4e48\u5c1d\u8bd5\u5c06\u8be5\u60c5\u51b5\u5199\u5165\u5230\u65e5\u5fd7\u91cc\u9762\n        if (nwritten == -1)\n        {\n            if (can_log)\n            {\n                redisLog(REDIS_WARNING, \"Error writing to the AOF file: %s\",\n                         strerror(errno));\n                server.aof_last_write_errno = errno;\n            }\n        }\n        else\n        {\n            if (can_log)\n            {\n                redisLog(REDIS_WARNING, \"Short write while writing to \"\n                                        \"the AOF file: (nwritten=%lld, \"\n                                        \"expected=%lld)\",\n                         (long long)nwritten,\n                         (long long)sdslen(server.aof_buf));\n            }\n\n            \/\/ \u5c1d\u8bd5\u79fb\u9664\u65b0\u8ffd\u52a0\u7684\u4e0d\u5b8c\u6574\u5185\u5bb9\n            if (ftruncate(server.aof_fd, server.aof_current_size) == -1)\n            {\n                if (can_log)\n                {\n                    redisLog(REDIS_WARNING, \"Could not remove short write \"\n                                            \"from the append-only file.  Redis may refuse \"\n                                            \"to load the AOF the next time it starts.  \"\n                                            \"ftruncate: %s\",\n                             strerror(errno));\n                }\n            }\n            else\n            {\n                \/* If the ftrunacate() succeeded we can set nwritten to\n                 * -1 since there is no longer partial data into the AOF. *\/\n                nwritten = -1;\n            }\n            server.aof_last_write_errno = ENOSPC;\n        }\n\n        \/* Handle the AOF write error. *\/\n        \/\/ \u5904\u7406\u5199\u5165 AOF \u6587\u4ef6\u65f6\u51fa\u73b0\u7684\u9519\u8bef\n        if (server.aof_fsync == AOF_FSYNC_ALWAYS)\n        {\n            \/* We can't recover when the fsync policy is ALWAYS since the\n             * reply for the client is already in the output buffers, and we\n             * have the contract with the user that on acknowledged write data\n             * is synched on disk. *\/\n            redisLog(REDIS_WARNING, \"Can't recover from AOF write error when the AOF fsync policy is 'always'. Exiting...\");\n            exit(1);\n        }\n        else\n        {\n            \/* Recover from failed write leaving data into the buffer. However\n             * set an error to stop accepting writes as long as the error\n             * condition is not cleared. *\/\n            server.aof_last_write_status = REDIS_ERR;\n\n            \/* Trim the sds buffer if there was a partial write, and there\n             * was no way to undo it with ftruncate(2). *\/\n            if (nwritten &gt; 0)\n            {\n                server.aof_current_size += nwritten;\n                sdsrange(server.aof_buf, nwritten, -1);\n            }\n            return; \/* We'll try again on the next call... *\/\n        }\n    }\n    else\n    {\n        \/* Successful write(2). If AOF was in error state, restore the\n         * OK state and log the event. *\/\n        \/\/ \u5199\u5165\u6210\u529f\uff0c\u66f4\u65b0\u6700\u540e\u5199\u5165\u72b6\u6001\n        if (server.aof_last_write_status == REDIS_ERR)\n        {\n            redisLog(REDIS_WARNING,\n                     \"AOF write error looks solved, Redis can write again.\");\n            server.aof_last_write_status = REDIS_OK;\n        }\n    }\n\n    \/\/ \u66f4\u65b0\u5199\u5165\u540e\u7684 AOF \u6587\u4ef6\u5927\u5c0f\n    server.aof_current_size += nwritten;\n\n    \/* Re-use AOF buffer when it is small enough. The maximum comes from the\n     * arena size of 4k minus some overhead (but is otherwise arbitrary). \n     *\n     * \u5982\u679c AOF \u7f13\u5b58\u7684\u5927\u5c0f\u8db3\u591f\u5c0f\u7684\u8bdd\uff0c\u90a3\u4e48\u91cd\u7528\u8fd9\u4e2a\u7f13\u5b58\uff0c\n     * \u5426\u5219\u7684\u8bdd\uff0c\u91ca\u653e AOF \u7f13\u5b58\u3002\n     *\/\n    if ((sdslen(server.aof_buf) + sdsavail(server.aof_buf)) &lt; 4000)\n    {\n        \/\/ \u6e05\u7a7a\u7f13\u5b58\u4e2d\u7684\u5185\u5bb9\uff0c\u7b49\u5f85\u91cd\u7528\n        sdsclear(server.aof_buf);\n    }\n    else\n    {\n        \/\/ \u91ca\u653e\u7f13\u5b58\n        sdsfree(server.aof_buf);\n        server.aof_buf = sdsempty();\n    }\n\n    \/* Don't fsync if no-appendfsync-on-rewrite is set to yes and there are\n     * children doing I\/O in the background. \n     *\n     * \u5982\u679c no-appendfsync-on-rewrite \u9009\u9879\u4e3a\u5f00\u542f\u72b6\u6001\uff0c\n     * \u5e76\u4e14\u6709 BGSAVE \u6216\u8005 BGREWRITEAOF \u6b63\u5728\u8fdb\u884c\u7684\u8bdd\uff0c\n     * \u90a3\u4e48\u4e0d\u6267\u884c fsync \n     *\/\n    if (server.aof_no_fsync_on_rewrite &amp;&amp;\n        (server.aof_child_pid != -1 || server.rdb_child_pid != -1))\n        return;\n\n    \/* Perform the fsync if needed. *\/\n\n    \/\/ \u603b\u662f\u6267\u884c fsnyc\n    if (server.aof_fsync == AOF_FSYNC_ALWAYS)\n    {\n        \/* aof_fsync is defined as fdatasync() for Linux in order to avoid\n         * flushing metadata. *\/\n        aof_fsync(server.aof_fd); \/* Let's try to get this data on the disk *\/\n\n        \/\/ \u66f4\u65b0\u6700\u540e\u4e00\u6b21\u6267\u884c fsnyc \u7684\u65f6\u95f4\n        server.aof_last_fsync = server.unixtime;\n\n        \/\/ \u7b56\u7565\u4e3a\u6bcf\u79d2 fsnyc \uff0c\u5e76\u4e14\u8ddd\u79bb\u4e0a\u6b21 fsync \u5df2\u7ecf\u8d85\u8fc7 1 \u79d2\n    }\n    else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC &amp;&amp;\n              server.unixtime &gt; server.aof_last_fsync))\n    {\n        \/\/ \u653e\u5230\u540e\u53f0\u6267\u884c\n        if (!sync_in_progress)\n            aof_background_fsync(server.aof_fd);\n        \/\/ \u66f4\u65b0\u6700\u540e\u4e00\u6b21\u6267\u884c fsync \u7684\u65f6\u95f4\n        server.aof_last_fsync = server.unixtime;\n    }\n\n    \/\/ \u5176\u5b9e\u4e0a\u9762\u65e0\u8bba\u6267\u884c if \u90e8\u5206\u8fd8\u662f else \u90e8\u5206\u90fd\u8981\u66f4\u65b0 fsync \u7684\u65f6\u95f4\n    \/\/ \u53ef\u4ee5\u5c06\u4ee3\u7801\u632a\u5230\u4e0b\u9762\u6765\n    \/\/ server.aof_last_fsync = server.unixtime;\n}\n\n\/\/ \u6bcf\u6b21\u5904\u7406\u4e8b\u4ef6\u4e4b\u524d\u6267\u884c\nvoid beforeSleep(struct aeEventLoop *eventLoop)\n{\n    \/* Write the AOF buffer on disk *\/\n    \/\/ \u5c06 AOF \u7f13\u51b2\u533a\u7684\u5185\u5bb9\u5199\u5165\u5230 AOF \u6587\u4ef6\n    flushAppendOnlyFile(0);\n}\n\nint serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData)\n{\n\n    \/\/ \u6839\u636e AOF \u653f\u7b56\uff0c\n    \/\/ \u8003\u8651\u662f\u5426\u9700\u8981\u5c06 AOF \u7f13\u51b2\u533a\u4e2d\u7684\u5185\u5bb9\u5199\u5165\u5230 AOF \u6587\u4ef6\u4e2d\n    \/* AOF postponed flush: Try at every cron cycle if the slow fsync\n     * completed. *\/\n    if (server.aof_flush_postponed_start)\n        flushAppendOnlyFile(0);\n\n    \/* AOF write errors: in this case we have a buffer to flush as well and\n     * clear the AOF error in case of success to make the DB writable again,\n     * however to try every second is enough in case of 'hz' is set to\n     * an higher frequency. *\/\n    run_with_period(1000)\n    {\n        if (server.aof_last_write_status == REDIS_ERR)\n            flushAppendOnlyFile(0);\n    }\n\n\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=437\">\u672c\u6587\u5730\u5740<\/a>\uff0chttps:\/\/www.ccagml.com\/?p=437<\/p>\n","protected":false},"excerpt":{"rendered":"<p>aof\u4fdd\u5b58aof\u662fredis\u7684\u4e00\u79cd\u6301\u4e45\u5316\u65b9\u5f0f,\u53ef\u4ee5\u6839\u636e\u914d\u7f6e\u81ea\u52a8\u89e6\u53d1\u4fdd\u5b58,\u4e5f\u53ef\u4ee5\u624b\u52a8\u6267\u884c\u4fdd\u5b58\/\/\u5728\u914d\u7f6e\u4e2dappe<a href=\"https:\/\/www.ccagml.com\/?p=437\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">redis\u6e90\u7801\u4ecemain\u5f00\u59cb18<\/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\/437"}],"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=437"}],"version-history":[{"count":3,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts\/437\/revisions"}],"predecessor-version":[{"id":441,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=\/wp\/v2\/posts\/437\/revisions\/441"}],"wp:attachment":[{"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=437"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=437"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ccagml.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=437"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}