redis中事務的取消
阿新 • • 發佈:2018-12-25
redis的事務不能實現回滾,但是可以在正在執行的事務中通過discard 命令來取消事務的執行。 struct redisCommand redisCommandTable[] = { {"discard",discardCommand,1,"rs",0,NULL,0,0,0,0,0}, } void discardCommand(redisClient *c) { // 可見這個命令是要在事務中進行沒負責直接返回error if (!(c->flags & REDIS_MULTI)) { addReplyError(c,"DISCARD without MULTI"); return; } // 呼叫這個函式清空redisClint.mstate.command這個陣列 discardTransaction(c); addReply(c,shared.ok); } void discardTransaction(redisClient *c) { // 刪除事務中已經入隊的命令 freeClientMultiState(c); // 重新初始化事務的佇列 initClientMultiState(c); // 取消在執行事務是設定的flags c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC);; // 取消對所有鍵的監視 unwatchAllKeys(c); } 我們首選看freeClientMultiState 是如此刪除事務中已經儲存的命令 void freeClientMultiState(redisClient *c) { int j; // 遍歷事務中已經儲存的命令,命令的總數用mstate.count表示 for (j = 0; j < c->mstate.count; j++) { int i; multiCmd *mc = c->mstate.commands+j; // 釋放所有命令引數 for (i = 0; i < mc->argc; i++) decrRefCount(mc->argv[i]); // 釋放參數陣列本身 zfree(mc->argv); } // 釋放儲存事務命令的陣列佔用的記憶體 zfree(c->mstate.commands); } 其次initClientMultiState 主要用於重新初始化命令儲存對了和命令總數 void initClientMultiState(redisClient *c) { // 儲存命令的陣列置 c->mstate.commands = NULL; // 命令計數歸零 c->mstate.count = 0; } 最後看看如何取消所有的key的監視 void unwatchAllKeys(redisClient *c) { listIter li; listNode *ln; //如果redisClient中的watched_keys 為零,說明沒有key 被監視,則就不用取消了,直接返回 if (listLength(c->watched_keys) == 0) return; // listRewind(c->watched_keys,&li); while((ln = listNext(&li))) { list *clients; watchedKey *wk; /* Lookup the watched key -> clients list and remove the client * from the list */ // 找到要刪除的key wk = listNodeValue(ln); // 根據key取出list *clients clients = dictFetchValue(wk->db->watched_keys, wk->key); // client 不能為null redisAssertWithInfo(c,NULL,clients != NULL); // 刪除連結串列中的客戶端節點 listDelNode(clients,listSearchKey(clients,c)); /* Kill the entry at all if this was the only client */ // 如果client已經為null,則刪除client 對應的key if (listLength(clients) == 0) dictDelete(wk->db->watched_keys, wk->key); /* Remove this watched key from the client->watched list */ // 從 listDelNode(c->watched_keys,ln); decrRefCount(wk->key); zfree(wk); } }