Heim > Datenbank > MySQL-Tutorial > Redis源码分析(十七)---multi事务操作

Redis源码分析(十七)---multi事务操作

WBOY
Freigeben: 2016-06-07 16:06:18
Original
788 Leute haben es durchsucht

redis作为一非关系型数据库,竟然同样拥有与RDBMS的事务操作,不免让我觉得比较惊讶。在redis就专门有文件就是执行事务的相关操作的。也可以让我们领略一下,在Redis的代码中是如何实现事务操作。首先亮出mulic.c下面的一些API。 /* =======================

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的命令方法 */
Nach dem Login kopieren
方法不是很多,但是里面出现了一个出现频率很高的词"key"。这个key在这里的确是起到了关键的作用。在muli的代码中主要包含了一些,加入命令,执行命令,还有一些撤销指令的操作,比如下面的撤销事务的操作。
/* 撤销事务 */
void discardTransaction(redisClient *c) {
    freeClientMultiState(c);
    initClientMultiState(c);
    c->flags &= ~(REDIS_MULTI|REDIS_DIRTY_CAS|REDIS_DIRTY_EXEC);
    //客户端取消监听所有的key
    unwatchAllKeys(c);
}
Nach dem Login kopieren
里面有个unwatchAllKeys()的方法。下面是事务操作的关键原理了:
/* 在事务处理中,存在2种mapping映射,key-->client lists ,表示所有列表中的Client都在监听这个key
	,当这个key的value发生改变了,可以标记这些Client为DIRTY状态,需要更新了,同时在Client内部也会维护
	一个key of list,表示一个客户端所监视的所有key,当Client发生free操作等,就要把key里面维护的Client列表
	做更新*/
Nach dem Login kopieren
/* touch key的意思,表示key正在被监听,下一条执行操作将会失败 */
Nach dem Login kopieren
也就是说,正在客户端正在监听的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;
    }
}
Nach dem Login kopieren
当客户端尝试用touch的方法去监听key的时候,Client的flag状态呗改为了DIRTY_CAS,不禁让我猜测,同步的方法是用CAS算法嘛,如果很多客户端都在用此算法,的确挺耗CPU的哦。总的来说,key维护了一个Client列表,一个Client同样拥有它所有watch的key列表,key的结构体很简单:
/* 定义了watchedKey结构体 */
typedef struct watchedKey {
    robj *key;
    redisDb *db;
} watchedKey;
Nach dem Login kopieren
key包含了它所属于的哪个数据库,所以刚刚撤销事务的操作,就要把客户端所监听的key都给移除掉了。
Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage