• Redis的appendfsync参数详解


    redis.conf中的appendfysnc是对redis性能有重要影响的参数之一。可取三种值:alwayseverysecno

    设置为always时,会极大消弱Redis的性能,因为这种模式下每次write后都会调用fsyncLinux为调用fdatasync)。

    如果设置为no,则write后不会有fsync调用,由操作系统自动调度刷磁盘,性能是最好的。

    everysec为最多每秒调用一次fsync,这种模式性能并不是很糟糕,一般也不会产生毛刺,这归功于Redis引入了BIO线程,所有fsync操作都异步交给了BIO线程。

     

    另外,Redis在处理一条命令时,并不立即调用writeAOF文件,只是将数据写入到AOF bufferserver.aof_buf)中。调用write和命令处理是分开的,Redis只在每次进入epoll_wait之前做write操作。

    /* Write the append only file buffer on disk.

     *

     * Since we are required to write the AOF before replying to the client,

     * and the only way the client socket can get a write is entering when the

     * the event loop, we accumulate all the AOF writes in a memory

     * buffer and write it on disk using this function just before entering

     * the event loop again.

     *

     * About the 'force' argument:

     *

     * When the fsync policy is set to 'everysec' we may delay the flush if there

     * is still an fsync() going on in the background thread, since for instance

     * on Linux write(2) will be blocked by the background fsync anyway.

     * When this happens we remember that there is some aof buffer to be

     * flushed ASAP, and will try to do that in the serverCron() function.

     *

     * However if force is set to 1 we'll write regardless of the background

     * fsync. */

    #define AOF_WRITE_LOG_ERROR_RATE 30 /* Seconds between errors logging. */

    void flushAppendOnlyFile(int force) {

        // aofWrite调用write将AOF buffer写入到AOF文件,处理了ENTR,其它没什么

        ssize_t nwritten = aofWrite(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));

        。。。。。。

        /* Handle the AOF write error. */

        if (server.aof_fsync == AOF_FSYNC_ALWAYS) {

            /* We can't recover when the fsync policy is ALWAYS since the

             * reply for the client is already in the output buffers, and we

             * have the contract with the user that on acknowledged write data

             * is synced on disk. */

            serverLog(LL_WARNING,"Can't recover from AOF write error when the AOF fsync policy is 'always'. Exiting...");

            exit(1);

        } else {

            return; /* We'll try again on the next call... */

        } else {

            /* Successful write(2). If AOF was in error state, restore the

             * OK state and log the event. */

        }

        。。。。。。

        /* Perform the fsync if needed. */

        if (server.aof_fsync == AOF_FSYNC_ALWAYS) {

            // redis_fsync是一个宏,Linux实际为fdatasync,其它为fsync

            // 所以最好不要将redis.conf中的appendfsync设置为always,这极影响性能

            redis_fsync(server.aof_fd); /* Let's try to get this data on the disk */

        }

        else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC && server.unixtime > server.aof_last_fsync)) {

            // 如果已在sync状态,则不再重复

            // BIO线程会间隔设置sync_in_progress

            // if (server.aof_fsync == AOF_FSYNC_EVERYSEC)

            //     sync_in_progress = bioPendingJobsOfType(BIO_AOF_FSYNC) != 0;

            if (!sync_in_progress)

                // eversec性能并不那么糟糕,因为它:

                // 后台方式执行fsync

                // Redis并不是严格意义上的单线程,实际上它创建一组BIO线程,专门处理阻塞和慢操作

                // 这些操作就包括FSYNC,另外还有关闭文件和内存的free两个操作。

                // 不像always,EVERYSEC模式并不立即调用fsync,

                // 而是将这个操作丢给了BIO线程异步执行,

                // BIO线程在进程启动时被创建,两者间通过bio_jobs和bio_pending两个

                // 全局对象交互,其中主线程负责写,BIO线程负责消费。

                aof_background_fsync(server.aof_fd);

            server.aof_last_fsync = server.unixtime;

        }

    }

  • 相关阅读:
    远程推送(个推)
    transform3D实现翻页效果
    启发式搜索 A*算法的OC 实现
    IOS 高级开发 KVC(二)
    IOS 高级开发 KVC(一)
    IOS 应用程序启动加载过程(从点击图标到界面显示)
    堆排序的OC实现
    iOS 高级开发 runtime(三)
    IOS 高级开发 runtime(二)
    RxSwift
  • 原文地址:https://www.cnblogs.com/aquester/p/10080991.html
Copyright © 2020-2023  润新知