99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

Redis 事務(wù)的實(shí)現(xiàn)

2018-08-02 14:56 更新

一個(gè)事務(wù)從開(kāi)始到結(jié)束通常會(huì)經(jīng)歷以下三個(gè)階段:

  1. 事務(wù)開(kāi)始。
  2. 命令入隊(duì)。
  3. 事務(wù)執(zhí)行。

本節(jié)接下來(lái)的內(nèi)容將對(duì)這三個(gè)階段進(jìn)行介紹, 說(shuō)明一個(gè)事務(wù)從開(kāi)始到結(jié)束的整個(gè)過(guò)程。

事務(wù)開(kāi)始

MULTI 命令的執(zhí)行標(biāo)志著事務(wù)的開(kāi)始:

redis> MULTI
OK

MULTI 命令可以將執(zhí)行該命令的客戶端從非事務(wù)狀態(tài)切換至事務(wù)狀態(tài), 這一切換是通過(guò)在客戶端狀態(tài)的 flags 屬性中打開(kāi) REDIS_MULTI 標(biāo)識(shí)來(lái)完成的, MULTI 命令的實(shí)現(xiàn)可以用以下偽代碼來(lái)表示:

def MULTI():

    # 打開(kāi)事務(wù)標(biāo)識(shí)
    client.flags |= REDIS_MULTI

    # 返回 OK 回復(fù)
    replyOK()

命令入隊(duì)

當(dāng)一個(gè)客戶端處于非事務(wù)狀態(tài)時(shí), 這個(gè)客戶端發(fā)送的命令會(huì)立即被服務(wù)器執(zhí)行:

redis> SET "name" "Practical Common Lisp"
OK

redis> GET "name"
"Practical Common Lisp"

redis> SET "author" "Peter Seibel"
OK

redis> GET "author"
"Peter Seibel"

與此不同的是, 當(dāng)一個(gè)客戶端切換到事務(wù)狀態(tài)之后, 服務(wù)器會(huì)根據(jù)這個(gè)客戶端發(fā)來(lái)的不同命令執(zhí)行不同的操作:

  • 如果客戶端發(fā)送的命令為 EXEC 、 DISCARD 、 WATCH 、 MULTI 四個(gè)命令的其中一個(gè), 那么服務(wù)器立即執(zhí)行這個(gè)命令。
  • 與此相反, 如果客戶端發(fā)送的命令是 EXEC 、 DISCARD 、 WATCH 、 MULTI 四個(gè)命令以外的其他命令, 那么服務(wù)器并不立即執(zhí)行這個(gè)命令, 而是將這個(gè)命令放入一個(gè)事務(wù)隊(duì)列里面, 然后向客戶端返回 QUEUED 回復(fù)。

服務(wù)器判斷命令是該入隊(duì)還是該立即執(zhí)行的過(guò)程可以用流程圖 IMAGE_ENQUEUE_OR_EXEC 來(lái)描述。

事務(wù)隊(duì)列

每個(gè) Redis 客戶端都有自己的事務(wù)狀態(tài), 這個(gè)事務(wù)狀態(tài)保存在客戶端狀態(tài)的 mstate 屬性里面:

typedef struct redisClient {

    // ...

    // 事務(wù)狀態(tài)
    multiState mstate;      /* MULTI/EXEC state */

    // ...

} redisClient;

事務(wù)狀態(tài)包含一個(gè)事務(wù)隊(duì)列, 以及一個(gè)已入隊(duì)命令的計(jì)數(shù)器 (也可以說(shuō)是事務(wù)隊(duì)列的長(zhǎng)度):

typedef struct multiState {

    // 事務(wù)隊(duì)列,F(xiàn)IFO 順序
    multiCmd *commands;

    // 已入隊(duì)命令計(jì)數(shù)
    int count;

} multiState;

事務(wù)隊(duì)列是一個(gè) multiCmd 類型的數(shù)組, 數(shù)組中的每個(gè) multiCmd 結(jié)構(gòu)都保存了一個(gè)已入隊(duì)命令的相關(guān)信息, 包括指向命令實(shí)現(xiàn)函數(shù)的指針, 命令的參數(shù), 以及參數(shù)的數(shù)量:

typedef struct multiCmd {

    // 參數(shù)
    robj **argv;

    // 參數(shù)數(shù)量
    int argc;

    // 命令指針
    struct redisCommand *cmd;

} multiCmd;

事務(wù)隊(duì)列以先進(jìn)先出(FIFO)的方式保存入隊(duì)的命令: 較先入隊(duì)的命令會(huì)被放到數(shù)組的前面, 而較后入隊(duì)的命令則會(huì)被放到數(shù)組的后面。

舉個(gè)例子, 如果客戶端執(zhí)行以下命令:

redis> MULTI
OK

redis> SET "name" "Practical Common Lisp"
QUEUED

redis> GET "name"
QUEUED

redis> SET "author" "Peter Seibel"
QUEUED

redis> GET "author"
QUEUED

那么服務(wù)器將為客戶端創(chuàng)建圖 IMAGE_TRANSACTION_STATE 所示的事務(wù)狀態(tài):

  • 最先入隊(duì)的 SET 命令被放在了事務(wù)隊(duì)列的索引 0 位置上。
  • 第二入隊(duì)的 GET 命令被放在了事務(wù)隊(duì)列的索引 1 位置上。
  • 第三入隊(duì)的另一個(gè) SET 命令被放在了事務(wù)隊(duì)列的索引 2 位置上。
  • 最后入隊(duì)的另一個(gè) GET 命令被放在了事務(wù)隊(duì)列的索引 3 位置上。

執(zhí)行事務(wù)

當(dāng)一個(gè)處于事務(wù)狀態(tài)的客戶端向服務(wù)器發(fā)送 EXEC 命令時(shí), 這個(gè) EXEC 命令將立即被服務(wù)器執(zhí)行: 服務(wù)器會(huì)遍歷這個(gè)客戶端的事務(wù)隊(duì)列, 執(zhí)行隊(duì)列中保存的所有命令, 最后將執(zhí)行命令所得的結(jié)果全部返回給客戶端。

舉個(gè)例子, 對(duì)于圖 IMAGE_TRANSACTION_STATE 所示的事務(wù)隊(duì)列來(lái)說(shuō), 服務(wù)器首先會(huì)執(zhí)行命令:

SET "name" "Practical Common Lisp"

接著執(zhí)行命令:

GET "name"

之后執(zhí)行命令:

SET "author" "Peter Seibel"

再之后執(zhí)行命令:

GET "author"

最后, 服務(wù)器會(huì)將執(zhí)行這四個(gè)命令所得的回復(fù)返回給客戶端:

redis> EXEC
1) OK
2) "Practical Common Lisp"
3) OK
4) "Peter Seibel"

EXEC 命令的實(shí)現(xiàn)原理可以用以下偽代碼來(lái)描述:

def EXEC():

    # 創(chuàng)建空白的回復(fù)隊(duì)列
    reply_queue = []

    # 遍歷事務(wù)隊(duì)列中的每個(gè)項(xiàng)
    # 讀取命令的參數(shù),參數(shù)的個(gè)數(shù),以及要執(zhí)行的命令
    for argv, argc, cmd in client.mstate.commands:

        # 執(zhí)行命令,并取得命令的返回值
        reply = execute_command(cmd, argv, argc)

        # 將返回值追加到回復(fù)隊(duì)列末尾
        reply_queue.append(reply)

    # 移除 REDIS_MULTI 標(biāo)識(shí),讓客戶端回到非事務(wù)狀態(tài)
    client.flags &= ~REDIS_MULTI

    # 清空客戶端的事務(wù)狀態(tài),包括:
    # 1)清零入隊(duì)命令計(jì)數(shù)器
    # 2)釋放事務(wù)隊(duì)列
    client.mstate.count = 0
    release_transaction_queue(client.mstate.commands)

    # 將事務(wù)的執(zhí)行結(jié)果返回給客戶端
    send_reply_to_client(client, reply_queue)
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)