zoukankan      html  css  js  c++  java
  • redis BIO详解

    BIO即background I/O service,后台I/O服务,是redis的aof持久化后台服务。
    redis把阻塞的同步I/O操作交给后台I/O服务来完成:close和fsync。
    close加入BIO的原因
    1.如果fd是特定文件描述符的最后一份拷贝,那么文件描述符相关的资源会被释放。
    2.如果fd是最后一个引用文件描述符的,并且文件描述符之前已经使用unlink进行删除,那么文件会被删除。
    资源释放和文件删除是非常慢的,会阻塞服务器
    fsync加入BIO的原因
    把内存中修改的文件数据同步到磁盘。调用者将被阻塞至磁盘报告同步完成。
    BIO的设计
    目前有两种任务:fsync和close。每种任务一个队列和一个线程。
    // 存放工作的队列
    static list *bio_jobs[REDIS_BIO_NUM_OPS];
    // 记录每种类型 job 队列里有多少 job 等待执行
    static unsigned long long bio_pending[REDIS_BIO_NUM_OPS];
    //初始化后台服务,启动后台线程
    void bioInit(void)
    //创建后台任务
    void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) 
    //处理后台任务,后台线程启动函数
    void *bioProcessBackgroundJobs(void *arg)
    {
        //当任务数为0的时候,调用pthread_cond_wait等待通知
        //任务数不为0的时候,从队列取任务并处理
            // 执行任务,type即线程启动的入参,每个后台线程处理一种任务
            if (type == REDIS_BIO_CLOSE_FILE) {
                close((long)job->arg1);
            } else if (type == REDIS_BIO_AOF_FSYNC) {
                aof_fsync((long)job->arg1);
            } else {
                redisPanic("Wrong job type in bioProcessBackgroundJobs().");
            }
    }
    BIO的结构

     

    BIO技术应用和优化
    aof有三种持久化方案
    1。内核同步,交给内核去缓存的数据到磁盘,大约30s一次。
    2.每秒同步,这是作者推荐的同步方案,和内核同步几乎一样快。
    3.每次都同步,性能极差,作者都恨不得删掉这个功能。
    fsync放在单独线程处理存在的问题
    fsync线程的使用和主线程的write存在冲突,在fsync进行的时候,write将被阻塞,fsync期间write不能执行,直到fsync完成。
    redis中实现了一种优化
    部分代码
    void flushAppendOnlyFile(int force) {
        // 策略为每秒 FSYNC 
        if (server.aof_fsync == AOF_FSYNC_EVERYSEC)
            // 是否有 SYNC 正在后台进行?
            sync_in_progress = bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC) != 0;
        // 每秒 fsync ,并且强制写入为假
        if (server.aof_fsync == AOF_FSYNC_EVERYSEC && !force) {
             * 如果后台仍在执行 FSYNC ,那么我们可以延迟写操作一两秒
             * (如果强制执行 write 的话,服务器主线程将阻塞在 write 上面)
             */
            if (sync_in_progress) {
                // 有 fsync 正在后台进行 。。。
                 * 如果后台还有 fsync 在执行,并且 write 已经推迟 >= 2 秒
                 * 那么执行写操作(write 将被阻塞)
                 */
        //write写入缓冲区
        nwritten = write(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));
    优化方案
    当aof同步方式为每秒同步时,主线程的write进行优化,如果执行write时fsync服务正在同步中,那么推迟write的时间,最多推迟两秒,如果等待两秒后fsync仍在同步,执行强制write操作,主线程将阻塞等待write完成。
    fsync服务线程和bgsave以及bgrewriteaof子进程的冲突
    这时候不应该执行fsync
        if (server.aof_no_fsync_on_rewrite &&
            (server.aof_child_pid != -1 || server.rdb_child_pid != -1))
                return;
    作者关于fsync服务线程的博客
  • 相关阅读:
    移动网页 ----仿淘宝使用flex布局实现页面 固定顶部和底部
    微信小程序 模板template的使用
    JQ 移动端返回顶部,往下滑动时显示返回按钮,往上滑动时隐藏返回按钮
    JQ模态框+简易评价
    JQ多行文本溢出省略号插件
    评论框字符串判断
    jQuery+ajax+本地josn文件数据 测试
    vue 移动端环境搭建
    移动端前端适配方案20170707
    城通网盘,千军万马,千脑网盘,119g网盘哪个适合做网赚?
  • 原文地址:https://www.cnblogs.com/learn-my-life/p/5662607.html
Copyright © 2011-2022 走看看