Redis源碼分析(二十七)--- rio系統I/O的封裝

來源:互聯網
上載者:User

標籤:io   記憶體資料庫   redis   nosql資料庫   

        I/O操作對於每個系統來說都是必不可少的一部分。而且I/O操作的好壞,在一定程度上也會影響著系統的效率問題。今天我學習了一下在Redis中的I/O是怎麼處理的,同樣的,Redis在他自己的系統中,也封裝了一個I/O層。簡稱RIO。得先看看RIO中有什麼東西嘍:

struct _rio {    /* Backend functions.     * Since this functions do not tolerate short writes or reads the return     * value is simplified to: zero on error, non zero on complete success. */    /* 資料流的讀方法 */    size_t (*read)(struct _rio *, void *buf, size_t len);    /* 資料流的寫方法 */    size_t (*write)(struct _rio *, const void *buf, size_t len);    /* 擷取當前的讀寫位移量 */    off_t (*tell)(struct _rio *);    /* The update_cksum method if not NULL is used to compute the checksum of     * all the data that was read or written so far. The method should be     * designed so that can be called with the current checksum, and the buf     * and len fields pointing to the new block of data to add to the checksum     * computation. */    /* 當讀入新的資料區塊的時候,會更新當前的校正和 */    void (*update_cksum)(struct _rio *, const void *buf, size_t len);    /* The current checksum */    /* 當前的校正和 */    uint64_t cksum;    /* number of bytes read or written */    /* 當前讀取的或寫入的位元組大小 */    size_t processed_bytes;    /* maximum single read or write chunk size */    /* 最大的單次讀寫的大小 */    size_t max_processing_chunk;    /* Backend-specific vars. */    /* rio中I/O變數 */    union {    //buffer結構體        struct {        //buffer具體內容            sds ptr;            //位移量            off_t pos;        } buffer;        //檔案結構體        struct {            FILE *fp;            off_t buffered; /* Bytes written since last fsync. */            //同步的最小大小            off_t autosync; /* fsync after 'autosync' bytes written. */        } file;    } io;};
裡面除了3個必須的方法,read,write方法,還有擷取位移量的tell方法,還有2個結構體變數,一個buffer結構體,一個file結構體,作者針對不同的I/O情況,做了不同的處理,當執行臨時的I/O操作時,都與rio.buffer打交道,當與檔案進行I/O操作時,則執行與rio.file之間的操作。下面看看rio統一定義的讀寫方法:

/* The following functions are our interface with the stream. They'll call the * actual implementation of read / write / tell, and will update the checksum * if needed. *//* rio的寫方法 */static inline size_t rioWrite(rio *r, const void *buf, size_t len) {    while (len) {    //判斷當前操作位元組長度是否超過最大長度        size_t bytes_to_write = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len;        //寫入新的資料時,更新校正和        if (r->update_cksum) r->update_cksum(r,buf,bytes_to_write);        //執行寫方法        if (r->write(r,buf,bytes_to_write) == 0)            return 0;        buf = (char*)buf + bytes_to_write;        len -= bytes_to_write;        //操作位元組數增加        r->processed_bytes += bytes_to_write;    }    return 1;}/* rio的讀方法 */static inline size_t rioRead(rio *r, void *buf, size_t len) {    while (len) {    //判斷當前操作位元組長度是否超過最大長度        size_t bytes_to_read = (r->max_processing_chunk && r->max_processing_chunk < len) ? r->max_processing_chunk : len;        //讀資料方法        if (r->read(r,buf,bytes_to_read) == 0)            return 0;        //讀資料時,更新校正和        if (r->update_cksum) r->update_cksum(r,buf,bytes_to_read);        buf = (char*)buf + bytes_to_read;        len -= bytes_to_read;        r->processed_bytes += bytes_to_read;    }    return 1;}
這裡有一個比較不錯的地方,每次當有資料發生改變的時候,Redis都會做一個計算校正和的處理演算法,表明了資料操作的改變動作,用的演算法就是之前介紹過CRC64演算法,針對RIO的buffer IO和File IO,Redis定義了2個RIO結構體:

/* 根據上面描述的方法,定義了BufferRio */static const rio rioBufferIO = {    rioBufferRead,    rioBufferWrite,    rioBufferTell,    NULL,           /* update_checksum */    0,              /* current checksum */    0,              /* bytes read or written */    0,              /* read/write chunk size */    { { NULL, 0 } } /* union for io-specific vars */};/* 根據上面描述的方法,定義了FileRio */static const rio rioFileIO = {    rioFileRead,    rioFileWrite,    rioFileTell,    NULL,           /* update_checksum */    0,              /* current checksum */    0,              /* bytes read or written */    0,              /* read/write chunk size */    { { NULL, 0 } } /* union for io-specific vars */};
裡面分別定義了相對應的讀寫方法,比如buffer的Read方法和File的Read方法:

/* Returns 1 or 0 for success/failure. *//* 讀取rio中的buffer內容到傳入的參數 */static size_t rioBufferRead(rio *r, void *buf, size_t len) {    if (sdslen(r->io.buffer.ptr)-r->io.buffer.pos < len)        return 0; /* not enough buffer to return len bytes. */    memcpy(buf,r->io.buffer.ptr+r->io.buffer.pos,len);    r->io.buffer.pos += len;    return 1;}
/* Returns 1 or 0 for success/failure. *//* 讀取rio中的fp檔案內容 */static size_t rioFileRead(rio *r, void *buf, size_t len) {    return fread(buf,len,1,r->io.file.fp);}
作用的rio的物件變數不一樣,最後在Redis的聲明中給出了4種不同類型資料的寫入方法:

/* rio寫入不同類型資料方法,最終調用的是riowrite方法 */size_t rioWriteBulkCount(rio *r, char prefix, int count);size_t rioWriteBulkString(rio *r, const char *buf, size_t len);size_t rioWriteBulkLongLong(rio *r, long long l);size_t rioWriteBulkDouble(rio *r, double d);
舉其中的一個方法實現:

/* Write multi bulk count in the format: "*<count>\r\n". *//* rio寫入不同類型資料方法,調用的是riowrite方法 */size_t rioWriteBulkCount(rio *r, char prefix, int count) {    char cbuf[128];    int clen;    cbuf[0] = prefix;    clen = 1+ll2string(cbuf+1,sizeof(cbuf)-1,count);    cbuf[clen++] = '\r';    cbuf[clen++] = '\n';    if (rioWrite(r,cbuf,clen) == 0) return 0;    return clen;}
調用的還是裡面的rioWrite方法,根據你定義的是buffer IO還是File IO,.各自有各自不同的實現而已。在檔案的write方法時,有一個細節,當你把內容讀入到rio.file.buffer時,buffer超過給定的同步最小位元組,你得必須將buffer內容重新整理到檔案中了。

/* Returns 1 or 0 for success/failure. *//* 將buf寫入rio中的file檔案中 */static size_t rioFileWrite(rio *r, const void *buf, size_t len) {    size_t retval;    retval = fwrite(buf,len,1,r->io.file.fp);    r->io.file.buffered += len;    if (r->io.file.autosync &&        r->io.file.buffered >= r->io.file.autosync)    {    //判讀是否需要同步        fflush(r->io.file.fp);        aof_fsync(fileno(r->io.file.fp));        r->io.file.buffered = 0;    }    return retval;}

Redis源碼分析(二十七)--- rio系統I/O的封裝

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.