redis代码 事务

typedef struct redisObject {
    unsigned type:4;        //0string  1list  2set 3zset 4hash
    unsigned notused:2;     /* Not used */
    unsigned encoding:4;    //0raw, 1int, 2hashtable 3zipmap ...
    unsigned lru:22;        /* lru time (relative to server.lruclock) */
    int refcount;           //记录有多少个指针指向该redisObject。为1时则释放(因为会decr一下),否则减1.
    void *ptr;         //sds类型, 即, char*类型。 ptr的前sizeof(struct sdshdr)是个结构体{len, free}表示该串的长度和可写内存长度
} robj;                //redis中的key和value都是这种类型的指针。



typedef struct redisDb {
    dict *dict;                 /* The keyspace for this DB */
    dict *expires;              /* Timeout of keys with a timeout set */
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */
    dict *ready_keys;           /* Blocked keys that received a PUSH */
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */ 维护的, list中表示watch了该key 的redisClient
    int id;
    long long avg_ttl;          /* Average TTL, just for stats */
} redisDb; 


/* With multiplexing we need to take per-client state.
 * Clients are taken in a liked list. */
typedef struct redisClient {
    int fd;
    redisDb *db;
    int dictid;
    robj *name;             /* As set by CLIENT SETNAME */
    sds querybuf;
    size_t querybuf_peak;   /* Recent (100ms or more) peak of querybuf size */
    int argc;
    robj **argv;
    struct redisCommand *cmd, *lastcmd;
    int reqtype;
    int multibulklen;       /* number of multi bulk arguments left to read */
    long bulklen;           /* length of bulk argument in multi bulk request */
    list *reply;
    unsigned long reply_bytes; /* Tot bytes of objects in reply list */
    int sentlen;            /* Amount of bytes already sent in the current
                               buffer or object being sent. */
    time_t ctime;           /* Client creation time */
    time_t lastinteraction; /* time of the last interaction, used for timeout */
    time_t obuf_soft_limit_reached_time;
    int flags;              /* REDIS_SLAVE | REDIS_MONITOR | REDIS_MULTI ... */
    int authenticated;      /* when requirepass is non-NULL */
    int replstate;          /* replication state if this is a slave */
    int repldbfd;           /* replication DB file descriptor */
    off_t repldboff;        /* replication DB file offset */
    off_t repldbsize;       /* replication DB file size */
    long long reploff;      /* replication offset if this is our master */
    long long repl_ack_off; /* replication ack offset, if this is a slave */
    long long repl_ack_time;/* replication ack time, if this is a slave */
    char replrunid[REDIS_RUN_ID_SIZE+1]; /* master run id if this is a master */
    int slave_listening_port; /* As configured with: SLAVECONF listening-port */
    multiState mstate;      /* MULTI/EXEC state */client每次发一个命令过来。 如果client开始watch或者事物,则client的相关命令queueMultiCommand存到此处。
    blockingState bpop;   /* blocking state */
    list *watched_keys;     /* Keys WATCHED for MULTI/EXEC CAS */ 该clientwatch的key的列表。
    dict *pubsub_channels;  /* channels a client is interested in (SUBSCRIBE) */
    list *pubsub_patterns;  /* patterns a client is interested in (SUBSCRIBE) */

    /* Response buffer */
    int bufpos;
    char buf[REDIS_REPLY_CHUNK_BYTES];
} redisClient;

/*
watch逻辑:先判断该client是否已watch过; 没有则在redisClient::watched_keys中增加、且在redisDB::watched_keys的该key列表下增加该redisClient
unwatch逻辑:上述逆过程
touchWatchedKey:遍历redisDB::watched_keys中该key的client列表, 将逐个client的flags |= REDIS_DIRTY_CAS。 client在exec时发现该标志则放弃事务。
在开启事务后, 该client后续的command都会被queue到redisClient::mstate中, 
如果中途用户discard则unwatch所有、回复相关状态, 否则直到exec时:先判断是否watch的被其他改变,否则逐条执行此前缓存的command

当key被修改时, 如set/del/rename?等操作时, 会将redisDB::watched_keys中该key的所有redisClient的flag设为DIRTY_CAS; redisClient后续exec时会检查该标记。

 */

struct redisCommand {
    char *name;
    redisCommandProc *proc;
    int arity;
    char *sflags; /* Flags as string representation, one char per flag. */
    int flags;    /* The actual flags, obtained from the 'sflags' field. */
    /* Use a function to determine keys arguments in a command line. */
    redisGetKeysProc *getkeys_proc;
    /* What keys should be loaded in background when calling this command? */
    int firstkey; /* The first argument that's a key (0 = no keys) */
    int lastkey;  /* The last argument that's a key */
    int keystep;  /* The step between first and last key */
    long long microseconds, calls;
};



/* Client MULTI/EXEC state */
typedef struct multiCmd {
    robj **argv;
    int argc;
    struct redisCommand *cmd;
} multiCmd;


typedef struct multiState {
    multiCmd *commands;     /* Array of MULTI commands */
    int count;              /* Total number of MULTI commands */
    int minreplicas;        /* MINREPLICAS for synchronous replication */
    time_t minreplicas_timeout; /* MINREPLICAS timeout as unixtime. */
} multiState;

 
  
 
 

你可能感兴趣的:(redis代码 事务)