Redis事務的分析及改進

來源:互聯網
上載者:User

標籤:

Redis事務的分析及改進Redis的事務特性

資料ACID特性滿足了幾條?
為了保持簡單,redis事務保證了其中的一致性和隔離性;
不滿足原子性和持久性;

原子性

redis事務在執行的中途遇到錯誤,不會復原,而是繼續執行後續命令;(違反原子性)

事務可以理解為一個打包的批量執行指令碼,但批量指令並非原子化的操作;
中間某條指令的失敗不會導致前面已做指令的復原,也不會造成後續的指令不做;
比如:

redis 127.0.0.1:7000> multiOKredis 127.0.0.1:7000> set a aaaQUEUEDredis 127.0.0.1:7000> set b bbbQUEUEDredis 127.0.0.1:7000> set c cccQUEUEDredis 127.0.0.1:7000> exec1) OK2) OK3) OK

如果在set b bbb處失敗,set a已成功不會復原,set c還會繼續執行;

持久性

事務不過是用隊列包裹起了一組 Redis 命令,並沒有提供任何額外的持久性功能,所以事務的持久性由 Redis 所使用的持久化模式決定:

  • 在單純的記憶體模式下,事務肯定是不持久的。
  • 在 RDB 模式下,伺服器可能在事務執行之後、RDB 檔案更新之前的這段時間失敗,所以 RDB 模式下的 Redis 事務也是不持久的。
  • 在 AOF 的“總是 SYNC ”模式下,事務的每條命令在執行成功之後,都會立即調用 fsync 或 fdatasync 將交易資料寫入到 AOF 檔案。但是,這種儲存是由後台線程進行的,主線程不會阻塞直到儲存成功,所以從命令執行成功到資料儲存到硬碟之間,還是有一段非常小的間隔,所以這種模式下的事務也是不持久的。
  • 其他 AOF 模式也和“總是 SYNC ”模式類似,所以它們都是不持久的。
隔離性和一致性

redis事務在執行的過程中,不會處理其它命令,而是等所有命令都執行完後,再處理其它命令(滿足隔離性)
redis事務在執行過程中發生錯誤或進程被終結,都能保證資料的一致性;(詳見參考資料1)

redis事務的缺陷

除了不保證原子性和持久性,在實際使用中還有以下問題:

1) 遇到有查詢的情況穿插在事務中間,不會返回結果;
設定事務開始標誌後,所有的命令都是queued,即使是查詢指令;
如果後續的更新操作需要依賴於前面的查詢指令,那redis事務就無法有效完成任務;
例如:

redis 127.0.0.1:7000> multiOKredis 127.0.0.1:7000> set a aaaQUEUEDredis 127.0.0.1:7000> get bQUEUED商務邏輯...redis 127.0.0.1:7000> set c cccQUEUEDredis 127.0.0.1:7000> exec1) OK2) bbb3) OK

第二步 get a 返回的是queued,並不是a的查詢結果,
如果後續的set操作依賴於get的結果(存在依賴商務邏輯),就不能將get操作放在事務操作中;

2) 事務中的每條命令都與redis伺服器進行了一次網路互動;
redis 事務指定開始後,執行一個事務返回的都是queued,那這個入隊操作是在用戶端實現,還是在伺服器端實現的?
查看源碼,很容易發現是在伺服器端實現;
在Redis.c中有這麼一段:

int processCommand(redisClient *c) {...    /* Exec the command */    if (c->flags & REDIS_MULTI &&        c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&        c->cmd->proc != multiCommand && c->cmd->proc != watchCommand)    {        queueMultiCommand(c); // 將事務中的命令都放入到隊列中,然後返回"QUEUED"        addReply(c,shared.queued);    } else {        if (server.vm_enabled && server.vm_max_threads > 0 &&            blockClientOnSwappedKeys(c)) return REDIS_ERR;        //調用該命令函數來處理命令        call(c);    }    return REDIS_OK;}

這裡就涉及到用戶端與伺服器端的多次互動,明明是需要一次批量執行的n條命令,還需要通過多次網路互動,有些浪費;

更新操作中的查詢實現

如果有這樣的需求:在事務開始後,中間穿插有查詢邏輯;
那麼使用redis事務(單庫),無法滿足這個要求;

可能的解決方案:

  1. 可以考慮使用多個庫,讀寫分離,查詢庫只用來查詢,更新庫用來開事務做寫操作;

  2. 不再使用redis的事務指令,自己在用戶端將待執行的命令批量打包,決定是否復原還是全部執行;這樣可以在更新的間隙執行查詢邏輯;而不需要將查詢邏輯提前到事務指令multi之前;

  3. 將查詢商務邏輯提前;嚴格規範代碼編寫要求,所有的redis查詢邏輯都放在事務之外:

     redis 127.0.0.1:7000> get b bbb 商務邏輯... redis 127.0.0.1:7000> multi OK redis 127.0.0.1:7000> set a aaa QUEUED redis 127.0.0.1:7000> set c ccc QUEUED redis 127.0.0.1:7000> exec 1) OK 2) OK
最佳化網路特性

將多個命令打包批量發送到redis伺服器執行,減少網路互動,最佳化效能,可能的解決方案:

  1. 對於所有的get/set操作,可使用現有的mget/mset指令;
  2. 對於各種不同類型的更新操作,可使用lua指令碼將命令打包後,發送到伺服器端一次執行;
參考

http://redisbook.readthedocs.org/en/latest/feature/transaction.html

Posted by: 大CC | 10MAR,2015
部落格:blog.me115.com [訂閱]
微博:新浪微博

Redis事務的分析及改進

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.