天天看點

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

一. 事務

1. 概念補充

(1). 原子性

  一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被恢複(Rollback)到事務開始前的狀态,就像這個事務從來沒有執行過一樣。

2. redis事務說明

 Redis的事務并不是我們傳統意義上了解的事務,我們都知道 單個 Redis 指令的執行是原子性的,但 Redis 沒有在事務上增加任何維持原子性的機制,是以 Redis 事務的執行并不是原子性的。事務可以了解為一個打包的批量執行腳本,但批量指令并非原子化的操作,中間某條指令的失敗不會導緻前面已做指令的復原,也不會造成後續的指令不做。

總結:

 (1). Redis事務中如果有某一條指令執行失敗,之前的指令不會復原,其後的指令仍然會被繼續執行→ →鑒于這個原因,是以說redis的事務嚴格意義上來說是不具備原子性的。

 (2). Redis事務中所有指令都會序列化、按順序地執行。事務在執行的過程中,不會被其他用戶端發送來的指令請求所打斷。

 (3). 在事務開啟之前,如果用戶端與伺服器之間出現通訊故障并導緻網絡斷開,其後所有待執行的語句都将不會被伺服器執行。然而如果網絡中斷事件是發生在用戶端執行EXEC指令之後,那麼該事務中的所有指令都會被伺服器執行。

 (4). 當使用Append-Only模式時,Redis會通過調用系統函數write将該事務内的所有寫操作在本次調用中全部寫入磁盤。然而如果在寫入的過程中出現系統崩潰,如電源故障導緻的當機,那麼此時也許隻有部分資料被寫入到磁盤,而另外一部分資料卻已經丢失。Redis伺服器會在重新啟動時執行一系列必要的一緻性檢測,一旦發現類似問題,就會立即退出并給出相應的錯誤提示。此時,我們就要充分利用Redis工具包中提供的redis-check-aof工具,該工具可以幫助我們定位到資料不一緻的錯誤,并将已經寫入的部分資料進行復原。修複之後我們就可以再次重新啟動Redis伺服器了。

3. 流程/指令

(1)multi 開啟事務

(2)大量指令入隊

(3)exec執行事務塊内指令,截止此處一個事務已經結束。

(4)discard 取消事務

(5)watch 監視一個或多個key,如果事務執行前key被改動,事務将打斷。unwatch 取消監視。

4. 測試

(1). 正常事務執行

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解
 (2). 取消事務
第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

5. Redis為什麼不支援事務復原?(官方解釋)

這種做法的優點:

 (1). Redis 指令隻會因為錯誤的文法而失敗,或是指令用在了錯誤類型的鍵上面,這些問題不能在入隊時發現,這也就是說,從實用性的角度來說,失敗的指令是由程式設計錯誤造成的,而這些錯誤應該在開發的過程中被發現,而不應該出現在生産環境中.

 (2). 因為不需要對復原進行支援,是以 Redis 的内部可以保持簡單且快速。

 有種觀點認為 Redis 處理事務的做法會産生 bug , 然而需要注意的是, 在通常情況下, 復原并不能解決程式設計錯誤帶來的問題。 舉個例子, 如果你本來想通過 INCR 指令将鍵的值加上 1 , 卻不小心加上了 2 , 又或者對錯誤類型的鍵執行了 INCR , 復原是沒有辦法處理這些情況的。鑒于沒有任何機制能避免程式員自己造成的錯誤, 并且這類錯誤通常不會在生産環境中出現, 是以 Redis 選擇了更簡單、更快速的無復原方式來處理事務。

補充一種情況:錯誤指令在入隊的時候,redis是能檢測出來的,當exec的時候,全部指令都不會執行。但是開發層次的錯誤如同上面所說 incr 1,但是不小 incr 2, redis無法判斷。

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

參考:https://www.runoob.com/redis/redis-transactions.html

二. 釋出訂閱(pub/sub)

1. 簡介

 Redis 釋出訂閱 (pub/sub) 是一種消息通信模式:發送者 (pub) 發送消息,訂閱者 (sub) 接收消息,Redis 用戶端可以訂閱任意數量的頻道。

 Redis 本身的 釋出訂閱 (pub/sub) 來實作消息隊列的功能,有個缺點就是消息無法持久化,如果出現網絡斷開、Redis 當機等,消息就會被丢棄。Redis Stream這個新的資料結構 提供了消息的持久化和主備複制功能,可以讓任何用戶端通路任何時刻的資料,并且能記住每一個用戶端的通路位置,還能保證消息不丢失。但還是建議使用專業的消息隊列,如:RabbitMq 、RocketMq等等。

2. 指令說明

(1). subscribe:訂閱給定的一個或多個頻道的資訊(頻道不存在的時候會建立頻道),傳回接收到的資訊。

SUBSCRIBE channel [channel2 ....]       

(2). publish:将資訊 message 發送到指定的頻道 channel,接收到資訊 message 的訂閱者數量。

publish channel message      

(3). unsubscribe:訓示用戶端退訂給定的頻道。

unsubscribe [channel [channel ...]]      

(4). psubscribe:訂閱一個或多個符合給定模式的頻道。

 每個模式以 * 作為比對符,比如 it* 比對所有以 it 開頭的頻道( it.news 、it.blog 、 it.tweets 等等), news.* 比對所有以 news. 開頭的頻道( news.it 、news.global.today 等等),諸如此類。

psubscribe pattern [pattern ...]      

(5). punsubscribe:訓示用戶端退訂所有給定模式。

punsubscribe [pattern [pattern ...]]      

3. 實操

(1). 開啟用戶端A和用戶端B,對頻道 chanel1 和 chanel2同時進行訂閱。

subscribe chanel1 chanel2      
第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

(2). 開啟一個用戶端C,向chanel1頻道進行發送資訊 。

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

(3). 檢視接收到的消息。

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

參考:https://www.runoob.com/redis/redis-pub-sub.html   和 redis指令文檔

三. PipeLine-管道

1. redis正常請求模型

 Redis是一種基于用戶端-服務端模型以及請求/響應協定的TCP服務。這意味着通常情況下一個請求會遵循以下步驟:

(1). 用戶端向服務端發送一個查詢請求,并監聽Socket傳回,通常是以阻塞模式,等待服務端響應。

(2). 服務端處理指令,并将結果傳回給用戶端。

2. 管道模型

 Redis 管道技術可以在服務端未響應時,用戶端可以繼續向服務端發送請求,并最終一次性讀取所有服務端的響應。

 用戶端可以一次性發送多個請求而不用等待伺服器的響應,待所有指令都發送完後再一次性讀取服務的響應,這樣可以極大的降低多條指令執行的網絡傳輸開銷,管道執行多條指令的網絡開銷實際上隻相當于一次指令執行的網絡開銷。需要注意到是用pipeline方式打包指令發送,redis必須在處理完所有指令前先緩存起所有指令的處理結果。打包的指令越多,緩存消耗記憶體也越多。是以并不是打包的指令越多越好。pipeline中發送的每個command都會被server立即執行,如果執行失敗,将會在此後的響應中得到資訊;也就是pipeline并不是表達“所有command都一起成功”的語義,管道中前面指令失敗,後面指令不會有影響,繼續執行。

jedis代碼:

Pipeline pl = jedis.pipelined();
 for (int i = 0; i < 10; i++) {
  pl.incr("pipelineKey");
  pl.set("zhuge" + i, "zhuge");
 }
 List<Object> results = pl.syncAndReturnAll();
 System.out.println(results);      

 參考:https://www.runoob.com/redis/redis-pipelining.html

四. benchmark性能測試

 1. 說明

  benchmark是位于redis安裝目錄下的一個性能測試工具,可以同時執行n個請求來檢測redis的性能。

常用指令:

#1. 用10000個請求檢測本機redis的各種指令的性能
./redis-benchmark -n 10000  -q
#2. 測試指定位址指定請求的redis性能(測試set和get性能)
./redis-benchmark -h 127.0.0.1 -p 6379 -t set,get -n 10000 -q      

參數說明:

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

2. 測試在win10下的redis3.2的性能

 電腦組態:4核16G

 redis預設配置情況下用10000個請求進行測試,測試結果如下圖:

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

3. 測試centos8下redis5.0的性能

 電腦組態:2核8G

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

4.測試centos8下redis6.0的性能

 電腦組態:2核8G,預設多線程是關閉的,需要手動開啟:

第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解
第八節: Redis事務、pub/sub、PipeLine-管道、benchmark性能測試詳解

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 部落格位址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 如有錯誤,歡迎讨論,請勿謾罵^_^。
  • 聲     明2 : 原創部落格請在轉載時保留原文連結或在文章開頭加上本人部落格位址,否則保留追究法律責任的權利。