<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                一個事務從開始到結束通常會經歷以下三個階段: 1. 事務開始。 2. 命令入隊。 3. 事務執行。 本節接下來的內容將對這三個階段進行介紹, 說明一個事務從開始到結束的整個過程。 ## 事務開始 MULTI?命令的執行標志著事務的開始: ~~~ redis> MULTI OK ~~~ MULTI?命令可以將執行該命令的客戶端從非事務狀態切換至事務狀態, 這一切換是通過在客戶端狀態的?`flags`?屬性中打開?`REDIS_MULTI`?標識來完成的,?MULTI?命令的實現可以用以下偽代碼來表示: ~~~ def MULTI(): # 打開事務標識 client.flags |= REDIS_MULTI # 返回 OK 回復 replyOK() ~~~ ## 命令入隊 當一個客戶端處于非事務狀態時, 這個客戶端發送的命令會立即被服務器執行: ~~~ redis> SET "name" "Practical Common Lisp" OK redis> GET "name" "Practical Common Lisp" redis> SET "author" "Peter Seibel" OK redis> GET "author" "Peter Seibel" ~~~ 與此不同的是, 當一個客戶端切換到事務狀態之后, 服務器會根據這個客戶端發來的不同命令執行不同的操作: * 如果客戶端發送的命令為?EXEC?、?DISCARD?、?WATCH?、?MULTI?四個命令的其中一個, 那么服務器立即執行這個命令。 * 與此相反, 如果客戶端發送的命令是?EXEC?、?DISCARD?、?WATCH?、?MULTI?四個命令以外的其他命令, 那么服務器并不立即執行這個命令, 而是將這個命令放入一個事務隊列里面, 然后向客戶端返回?`QUEUED`?回復。 服務器判斷命令是該入隊還是該立即執行的過程可以用流程圖 IMAGE_ENQUEUE_OR_EXEC 來描述。 ![](https://box.kancloud.cn/2015-09-13_55f5297ce7a3b.png) ## 事務隊列 每個 Redis 客戶端都有自己的事務狀態, 這個事務狀態保存在客戶端狀態的?`mstate`?屬性里面: ~~~ typedef struct redisClient { // ... // 事務狀態 multiState mstate; /* MULTI/EXEC state */ // ... } redisClient; ~~~ 事務狀態包含一個事務隊列, 以及一個已入隊命令的計數器 (也可以說是事務隊列的長度): ~~~ typedef struct multiState { // 事務隊列,FIFO 順序 multiCmd *commands; // 已入隊命令計數 int count; } multiState; ~~~ 事務隊列是一個?`multiCmd`?類型的數組, 數組中的每個?`multiCmd`?結構都保存了一個已入隊命令的相關信息, 包括指向命令實現函數的指針, 命令的參數, 以及參數的數量: ~~~ typedef struct multiCmd { // 參數 robj **argv; // 參數數量 int argc; // 命令指針 struct redisCommand *cmd; } multiCmd; ~~~ 事務隊列以先進先出(FIFO)的方式保存入隊的命令: 較先入隊的命令會被放到數組的前面, 而較后入隊的命令則會被放到數組的后面。 舉個例子, 如果客戶端執行以下命令: ~~~ redis> MULTI OK redis> SET "name" "Practical Common Lisp" QUEUED redis> GET "name" QUEUED redis> SET "author" "Peter Seibel" QUEUED redis> GET "author" QUEUED ~~~ 那么服務器將為客戶端創建圖 IMAGE_TRANSACTION_STATE 所示的事務狀態: * 最先入隊的?SET?命令被放在了事務隊列的索引?`0`?位置上。 * 第二入隊的?GET?命令被放在了事務隊列的索引?`1`?位置上。 * 第三入隊的另一個?SET?命令被放在了事務隊列的索引?`2`?位置上。 * 最后入隊的另一個?GET?命令被放在了事務隊列的索引?`3`?位置上。 ![](https://box.kancloud.cn/2015-09-13_55f5298089602.png) ## 執行事務 當一個處于事務狀態的客戶端向服務器發送?EXEC?命令時, 這個?EXEC?命令將立即被服務器執行: 服務器會遍歷這個客戶端的事務隊列, 執行隊列中保存的所有命令, 最后將執行命令所得的結果全部返回給客戶端。 舉個例子, 對于圖 IMAGE_TRANSACTION_STATE 所示的事務隊列來說, 服務器首先會執行命令: ~~~ SET "name" "Practical Common Lisp" ~~~ 接著執行命令: ~~~ GET "name" ~~~ 之后執行命令: ~~~ SET "author" "Peter Seibel" ~~~ 再之后執行命令: ~~~ GET "author" ~~~ 最后, 服務器會將執行這四個命令所得的回復返回給客戶端: ~~~ redis> EXEC 1) OK 2) "Practical Common Lisp" 3) OK 4) "Peter Seibel" ~~~ EXEC?命令的實現原理可以用以下偽代碼來描述: ~~~ def EXEC(): # 創建空白的回復隊列 reply_queue = [] # 遍歷事務隊列中的每個項 # 讀取命令的參數,參數的個數,以及要執行的命令 for argv, argc, cmd in client.mstate.commands: # 執行命令,并取得命令的返回值 reply = execute_command(cmd, argv, argc) # 將返回值追加到回復隊列末尾 reply_queue.append(reply) # 移除 REDIS_MULTI 標識,讓客戶端回到非事務狀態 client.flags &= ~REDIS_MULTI # 清空客戶端的事務狀態,包括: # 1)清零入隊命令計數器 # 2)釋放事務隊列 client.mstate.count = 0 release_transaction_queue(client.mstate.commands) # 將事務的執行結果返回給客戶端 send_reply_to_client(client, reply_queue) ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看