Redis源碼分析(十七)--- multi事務操作

來源:互聯網
上載者:User

標籤:nosql資料庫   源碼   redis   

        redis作為一非關係型資料庫,竟然同樣擁有與RDBMS的事務操作,不免讓我覺得比較驚訝。在redis就專門有檔案就是執行事務的相關操作的。也可以讓我們領略一下,在Redis的代碼中是如何?事務操作。首先亮出mulic.c下面的一些API。

/* ================================ MULTI/EXEC ============================== */void initClientMultiState(redisClient *c) /* 初始化用戶端操作 */void freeClientMultiState(redisClient *c) /* 釋放用戶端所有與multi/exec相關的資源 */void queueMultiCommand(redisClient *c) /* 用戶端的multi命令隊列添加一條新的命令 */void discardTransaction(redisClient *c) /* 撤銷事務操作 */void flagTransaction(redisClient *c) /* 標記一個事物為DIRTY_EXEC狀態,最後這個事物會執行失敗,,此方法調用於插入命令的時候 */void multiCommand(redisClient *c) /* 加入multi命令 */void discardCommand(redisClient *c) /* 撤銷命令 */void execCommandPropagateMulti(redisClient *c) /* 發送multi命令給所有的從用戶端和aof檔案 */void execCommand(redisClient *c) /* 客戶單執行Command命令 */void watchForKey(redisClient *c, robj *key) /* 為用戶端添加key監聽 */void unwatchAllKeys(redisClient *c) /* 用戶端移除所有的key */void touchWatchedKey(redisDb *db, robj *key) /* touch key的意思,表示key正在被監聽,下一條執行操作將會失敗 */void touchWatchedKeysOnFlush(int dbid) /* 根據key所在的的db,把此db下的watched-key統統touch一遍 */void watchCommand(redisClient *c) /* watch key 的命令方法,通過client中的參數傳值 */void unwatchCommand(redisClient *c) /* 取消監聽key的命令方法 */
方法不是很多,但是裡面出現了一個出現頻率很高的詞"key"。這個key在這裡的確是起到了關鍵的作用。在muli的代碼中主要包含了一些,加入命令,執行命令,還有一些撤銷指令的操作,比如下面的撤銷事務的操作。

/* 撤銷事務 */void discardTransaction(redisClient *c) {    freeClientMultiState(c);    initClientMultiState(c);    c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC);    //用戶端取消監聽所有的key    unwatchAllKeys(c);}
裡面有個unwatchAllKeys()的方法。下面是事務操作的關鍵原理了:

/* 在交易處理中,存在2種mapping映射,key-->client lists ,表示所有列表中的Client都在監聽這個key,當這個key的value發生改變了,可以標記這些Client為DIRTY狀態,需要更新了,同時在Client內部也會維護一個key of list,表示一個用戶端所監視的所有key,當Client發生free操作等,就要把key裡面維護的Client列表做更新*/

/* touch key的意思,表示key正在被監聽,下一條執行操作將會失敗 */
也就是說,正在用戶端正在監聽的key,他的下一步命令將會執行失敗,達到了同步的效果,

/* "Touch" a key, so that if this key is being WATCHed by some client the * next EXEC will fail. *//* touch key的意思,表示key正在被監聽,下一條執行操作將會失敗 */void touchWatchedKey(redisDb *db, robj *key) {    list *clients;    listIter li;    listNode *ln;    if (dictSize(db->watched_keys) == 0) return;    clients = dictFetchValue(db->watched_keys, key);    if (!clients) return;    /* Mark all the clients watching this key as REDIS_DIRTY_CAS */    /* Check if we are already watching for this key */    listRewind(clients,&li);    while((ln = listNext(&li))) {        redisClient *c = listNodeValue(ln);//遍曆該key擁有的Client,把flag標記為DIRTY_CAS狀態        c->flags |= REDIS_DIRTY_CAS;    }}
當用戶端嘗試用touch的方法去監聽key的時候,Client的flag狀態唄改為了DIRTY_CAS,不禁讓我猜測,同步的方法是用CAS演算法嘛,如果很多用戶端都在用此演算法,的確挺耗CPU的哦。總的來說,key維護了一個Client列表,一個Client同樣擁有它所有watch的key列表,key的結構體很簡單:

/* 定義了watchedKey結構體 */typedef struct watchedKey {    robj *key;    redisDb *db;} watchedKey;
key包含了它所屬於的哪個資料庫,所以剛剛撤銷事務的操作,就要把用戶端所監聽的key都給移除掉了。

Redis源碼分析(十七)--- multi事務操作

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.