Redis as a database of non relational, unexpectedly also has the transaction operation with the RDBMS, let me feel quite surprised. In Redis, there are files that are involved in performing transactions. It also gives us a glimpse of how transaction operations are implemented in Redis code. First, some of the APIs below MULIC.C are illuminated.
/* ================================ multi/exec ==============================/void Initclientmultistate ( Redisclient *c) * Initialize client action/void Freeclientmultistate (Redisclient *c) * Release client all MULTI/EXEC-related resources/void Queuemulticomm and (Redisclient *c)/* Client's Multi command queue adds a new command/void Discardtransaction (Redisclient *c)/* undo transaction operation/Void Flagtransaction ( Redisclient *c)/* Mark a thing as a dirty_exec state, and the last thing fails, this method is used when inserting a command/void Multicommand (Redisclient *c)/* Join multi command/VO
ID Discardcommand (redisclient *c)/* Undo command/Void Execcommandpropagatemulti (redisclient *c) * Send Multi command to all from client and aof file * * void ExecCommand (Redisclient *c)/* Client orders execute command/void Watchforkey (Redisclient *c, RobJ *key)/* Add key monitor for client/void Unwatchallkeys (redisclient *c)/* Client removes all key/void Touchwatchedkey (Redisdb *db, RobJ *key)/* Touch key meaning that key is being monitored, under An operation will fail/void Touchwatchedkeysonflush (int dbid)/* The DB under which the key is located, the Watched-key is all in touch with the * * void Watchcommand ( Redisclient *c)/* Watch Key's command method, through the parameters in the clientTransfer value/void Unwatchcommand (Redisclient *c)/* Cancel the command method of the listener key.
The method is not much, but there is a very high frequency of the word "key." This key does play a pivotal role here. In Muli's code, there are a few, including commands, executing commands, and some undo instructions, such as the following undo transaction operations.
/* Undo Transaction
/void Discardtransaction (Redisclient *c) {
freeclientmultistate (c);
Initclientmultistate (c);
C->flags &= ~ (redis_multi| redis_dirty_cas| REDIS_DIRTY_EXEC);
The client cancels the listening of all key
Unwatchallkeys (c);
}
There is a Unwatchallkeys () method. The following are the key principles of transaction operations:
/* In transaction processing, there are 2 kinds of mapping mappings, key-->client lists, that all the client in the list is listening to this key
, when the value of this key has changed, You can mark these clients as dirty states, need to be updated, and also maintain a key of list within the client, which indicates that all keys that are being
monitored by a customer are free operations, The client list maintained in key will
be updated.
/* Touch key means that the key is being monitored, the next operation will fail.
In other words, the key that is being monitored by the client, his next command will fail to achieve the effect of synchronization,
/* "Touch" a key, so it if this is being watched by some client
the * next EXEC would fail. */* Touch
Key's meaning Think, the key is being monitored, the next operation will fail
/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);
Iterate over the client owned by the key, marking flag as Dirty_cas State
c->flags |= redis_dirty_cas;
}
When the client tries to use touch method to listen to key, the client's flag State Bai changed to Dirty_cas, let me guess, the synchronization method is to use the CAS algorithm, if a lot of clients are using this algorithm, it really consumes CPU oh. In general, Key maintains a client list, and a client also has all of its watch key listings, and the key structure is simple:
/* Defines the WATCHEDKEY structure body *
/typedef struct WATCHEDKEY {
robj *key;
Redisdb *db;
} Watchedkey;
Key contains which database it belongs to, so just undo the operation of the transaction, the client will be listening to the key removed.