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服务线程的博客

redis BIO详解的更多相关文章

  1. redis配置详解

    ##redis配置详解 # Redis configuration file example. # # Note that in order to read the configuration fil ...

  2. CentOS7/RHEL7安装Redis步骤详解

    CentOS7/RHEL7安装Redis步骤详解 CentOS7/RHEL7安装Redis还是头一次测试安装了,因为centos7升级之后与centos6有比较大的区别了,下面我们就一起来看看Cent ...

  3. Redis协议详解

    smark Beetle可靠.高性能的.Net Socket Tcp通讯组件 支持flash amf3,protobuf,Silverlight,windows phone Redis协议详解 由于前 ...

  4. Redis学习——详解Redis配置文件(三)

    一.Redis脚本简介 在我们介绍Redis的配置文件之前,我们先来说一下Redis安装完成后生成的几个可执行文件: redis-server .redis-cli .redis-benchmark ...

  5. Redis:默认配置文件redis.conf详解

    转: Redis:默认配置文件redis.conf详解 # Redis配置文件样例 # Note on units: when memory size is needed, it is possibl ...

  6. Python操作redis学习系列之(集合)set,redis set详解 (六)

    # -*- coding: utf-8 -*- import redis r = redis.Redis(host=") 1. Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合 ...

  7. Redis配置文件redis.conf详解

    一.Redis配置文件redis.conf详解 # Note on units: when memory size is needed, it is possible to specifiy # it ...

  8. [转]使用python来操作redis用法详解

    转自:使用python来操作redis用法详解 class CommRedisBase(): def __init__(self): REDIS_CONF = {} connection_pool = ...

  9. linux离线部署redis及redis.conf详解

    一.离线部署redis 由于博主部署的虚拟机没有网络也没有gcc编译器,所以就寻找具备gcc编译器的编译环境把redis编译安装好,Copy Redis安装目录文件夹到目标虚拟机的目录下.copy时r ...

随机推荐

  1. CallableStatement的用法

    CallableStatement 对象为所有的 DBMS 提供了一种以标准形式调用已储存过程的方法.已储存过程储存在数据库中.对已储存过程的调用是 CallableStatement 对象所含的内容 ...

  2. Ubuntu Server下docker实战 02: docker进阶配置

    在上一篇文章里<Ubuntu Server下docker实战 01: 安装docker>,我们已经把docker安装起来了,并运行了一个hello-world 这一篇,我们继续讲进阶配置. ...

  3. 通过请求接口的办法获得本设备IP以及IP地址

    获取本设备IP接口(搜狐) http://pv.sohu.com/cityjson?ie=utf-8 result Content: {    "cip": "58.21 ...

  4. IntelliJ IDEA 和 webstorm更换主题

    1. 搜索http://color-themes.com/?view=index 2. 查找自己喜欢的主题,下载 3. 放在安装位置(个人习惯,放在哪都行,能找到就行) 4. 然后打开importSe ...

  5. iOS_25_彩票设置的cell的数据源模型的封装

    组模型的封装 SettingGroup // // SettingGroup.h // 25_彩票 // // Created by beyond on 14-8-28. // Copyright ( ...

  6. EditText焦点问题

    1.在一个Activity中加入一个EditText后,每次进入这个Activity时输入法都会自己主动弹出来.非常烦,找了些资料,在此记下解决的方法: 方法:在EditText的父控件中获得焦点.这 ...

  7. Android自己定义控件之轮播图控件

    背景 近期要做一个轮播图的效果.网上看了几篇文章.基本上都能找到实现,效果还挺不错,可是在写的时候感觉每次都要单独去又一次在Activity里写一堆代码.于是自己封装了一下.这里仅仅是做了下封装成一个 ...

  8. 安装10gR2的硬件要求

    1.至少1G的RAM. 2.RAM与swap关系: RAM                    swap 512M以上           2*RAM   (非常奇怪.至少1G的RAM.还写512的 ...

  9. Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader

    Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader 之前写了两篇文章,介绍了我在边缘检測上面的研究.实际上.使用GPU对渲染图像进行边缘检測.前提是须要进行两遍渲染.前 ...

  10. C#实体转换

    using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using S ...