數據ACID特性知足了幾條?
爲了保持簡單,redis事務保證了其中的一致性和隔離性;
不知足原子性和持久性;html
redis事務在執行的中途遇到錯誤,不會回滾,而是繼續執行後續命令;(違反原子性)redis
事務能夠理解爲一個打包的批量執行腳本,但批量指令並不是原子化的操做;
中間某條指令的失敗不會致使前面已作指令的回滾,也不會形成後續的指令不作;
好比:服務器
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 b bbb QUEUED redis 127.0.0.1:7000> set c ccc QUEUED redis 127.0.0.1:7000> exec 1) OK 2) OK 3) OK
若是在set b bbb處失敗,set a已成功不會回滾,set c還會繼續執行;網絡
事務不過是用隊列包裹起了一組 Redis 命令,並無提供任何額外的持久性功能,因此事務的持久性由 Redis 所使用的持久化模式決定:app
redis事務在執行的過程當中,不會處理其它命令,而是等全部命令都執行完後,再處理其它命令(知足隔離性)
redis事務在執行過程當中發生錯誤或進程被終結,都能保證數據的一致性;(詳見參考資料1)async
除了不保證原子性和持久性,在實際使用中還有如下問題:函數
1) 遇到有查詢的狀況穿插在事務中間,不會返回結果;
設置事務開始標誌後,全部的命令都是queued,即便是查詢指令;
若是後續的更新操做須要依賴於前面的查詢指令,那redis事務就沒法有效的完成任務;
例如:性能
redis 127.0.0.1:7000> multi OK redis 127.0.0.1:7000> set a aaa QUEUED redis 127.0.0.1:7000> get b QUEUED 業務邏輯... redis 127.0.0.1:7000> set c ccc QUEUED redis 127.0.0.1:7000> exec 1) OK 2) bbb 3) OK
第二步 get a 返回的是queued,並非a的查詢結果,
若是後續的set操做依賴於get的結果(存在依賴業務邏輯),就不能將get操做放在事務操做中;優化
2) 事務中的每條命令都與redis服務器進行了一次網絡交互;
redis 事務指定開始後,執行一個事務返回的都是queued,那這個入隊操做是在客戶端實現,仍是在服務器端實現的?
查看源碼,很容易發現是在服務器端實現;
在Redis.c中有這麼一段:lua
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事務(單庫),沒法知足這個要求;
可能的解決方案:
能夠考慮使用多個庫,讀寫分離,查詢庫只用來查詢,更新庫用來開事務作寫操做;
再也不使用redis的事務指令,本身在客戶端將待執行的命令批量打包,決定是否回滾仍是所有執行;這樣能夠在更新的間隙執行查詢邏輯;而不須要將查詢邏輯提早到事務指令multi以前;
將查詢業務邏輯提早;嚴格規範代碼編寫要求,全部的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服務器執行,減小網絡交互,優化性能,可能的解決方案:
http://redisbook.readthedocs.org/en/latest/feature/transaction.html
Posted by: 大CC | 10MAR,2015
博客:blog.me115.com [訂閱]
微博:新浪微博