redis之VM

aeCreateFileEvent(server.el, server.io_ready_pipe_read, AE_READABLE, vmThreadedIOCompletedJob, NULL)

主线程和后台线程通过pipe进行通信:

    后台线程每处理完一个job,就会给server.io_ready_pipe_write发送一个字节数据;

    主线程监听server.io_ready_pipe_read,当有数据可读时,表明有job处理完成,调用vmThreadedIOCompletedJob处理;


int vmSwapObjectThreaded(robj *key, robj *val, redisDb *db)

提交一个job给后台线程,将val交换到磁盘;

job类型为REDIS_IOJOB_PREPARE_SWAP;

val的storage更新为REDIS_VM_SWAPPING;

调用queueIOJob将job append到server.io_newjobs队列,后台线程将从这个队列取job执行;

queueIOJob时,如果server.io_active_threads < server.vm_max_threads,将会调用spawnIOThread(),创建后台工作线程;


void *IOThreadEntryPoint(void *arg)
后台工作线程函数;

从server.io_newjobs队首取下job,将其放入server.io_processing队尾,表示当前job正在处理;

处理job:

    REDIS_IOJOB_LOAD,vmReadObjectFromSwap将val从文件读入;

    REDIS_IOJOB_PREPARE_SWAP,开启swap过程,本次job计算存储val需要多少page,本次job成功后,转入REDIS_IOJOB_DO_SWAP类型job完成swap;

    REDIS_IOJOB_DO_SWAP,vmWriteObjectOnSwap将val存储到文件;

job独立完后,将job从server.io_processing队列取下,放入server.io_processed队尾,然后通过pipe(server.io_ready_pipe_write)给主线程发送一个字节数据("x")以通知主线程调用vmThreadedIOCompletedJob;


void vmThreadedIOCompletedJob(aeEventLoop *el, int fd, void *privdata, int mask)

主线程收到server.io_ready_pipe_read可读事件时调用;

读一个字节;

从server.io_processed队首取下一个已完成job;

如果job被cancel,直接忽略;

job类型为REDIS_IOJOB_LOAD:

    表明val从磁盘读入到内存;

    释放其占用的pages;

    将value从vmpointer替换为object;

    处理所有阻塞在该key上面的client,如果client需要的所有key都内存就绪,将其加入server.io_ready_clients队列;

job类型为REDIS_IOJOB_PREPARE_SWAP:

    保存val需要的page数目已经计算完毕;

    如果不能swapout或者vmFindContiguousPages(&j->page,j->pages)失败,则swap过程失败,终止swap过程,将storage设置为REDIS_VM_MEMORY;

    如果能够swapout且找到了块存储val,则调用vmMarkPagesUsed(j->page,j->pages)标记这些page已经被占用,将job类型更新为REDIS_IOJOB_DO_SWAP,调用queueIOJob提交job;

job类型为REDIS_IOJOB_DO_SWAP:

    表明val已经成功存储到磁盘;

    将value从object替换为vmpointer,释放object;

你可能感兴趣的:(key-value,redis)