redis基礎之訂閱發佈、主從複製和事務(四)

前面已經學習了redis的基本的命令行操做和數據類型,下面開始redis一些有趣的功能。redis

訂閱和發佈機制

  • 定義:發佈者至關於電臺,訂閱者至關於客戶端,客戶端發到頻道的消息,將會被推送到全部訂閱此頻道的客戶端;客戶端不須要主動去獲取消息,只須要訂閱頻道,這個頻道的內容就會被推送過來;數據庫

  • 做用:發佈者和訂閱者的解耦合能夠帶來更大的擴展性和更加動態的網絡拓撲;緩存

相關命令

# 訂閱消息
subscribe 頻道1 頻道2   # 此時redis客戶端會一直處於監聽頻道的狀態,一有消息就處理;
# 取消訂閱
unsubcribe 頻道1 ...   # 若是不寫頻道名稱,則取消全部的訂閱;

# 推送消息
publish 頻道1 消息內容

重點說明

  • 發佈訂閱機制通常使用在對同一個redis實例來講,實現相似於生產者消費者模式;服務器

  • 在主從集羣中,master發佈的消息能夠推送到slave中,但slave中的消息不能推送到master中;網絡

訂閱發佈機制的不足:併發

  1. 若是消息接收方不能及時處理推送的消息,消息會在緩存隊列中,會致使緩存佔用的空間愈來愈大,最終致使redis崩潰;高併發

  2. 發佈的消息推送存在即時性,但網絡通常是不穩定的,對於客戶端來講,若是出現了斷網的現象,那麼接收的消息就會丟失,因此發佈訂閱模式不能用在對數據完整性要求高的場合;性能

簡單的主從複製配置

  • 定義:一臺redis服務器能夠做爲一個master,在其下面能夠有多個slave,每一個slave又能夠做爲一個master,從而能夠構建龐大的redis數據庫集羣;

配置方法

方式一:修改配置文件學習

# 設置主服務器的配置,綁定固定的ip
sudo vi redis.conf
bind 服務器的ip

# 設置從服務器的ip
sudo vi redis.conf
bind 服務器的ip
slaveof 主服務器的ip 主服務器redis端口     # 注意,ip與端口之間使用空格分割

# 分別啓動主從redis,主服務器redis負責寫,也能夠讀;從服務器只能讀,不能寫;

方式二:使用命令行的方式動態設置spa

# 從服務器鏈接主服務器
slaveof host port 
# 從服務器斷開主服務器
slaveof no one

重要說明

  • 從服務器與主服務器進行初始鏈接時,從服務器會丟棄全部的舊數據,而後載入主服務器的數據;

  • redis不支持主主複製,也就是說不能夠兩個redis相互設置對方爲主服務器,雖然不會報錯,但性能方面,以及對客戶端的請求均可能出現問題;

redis複製的啓動過程

  • 當主服務器收到從服務器發送的複製請求的時候,主服務器執行的動做有:

等待從服務器的命令進入-->執行bgsave,建立快照文件;使用緩存區記錄bgsave命令執行後全部的寫命令-->快照文件建立完畢後,向服務器發送快照文件-->發送快照文件完畢後向從服務器發送緩存區的寫命令-->完畢後每收到一個寫命令就向從服務器發送

  • 從服務器相應的動做有:

鏈接主服務器,發送sync命令-->等待響應-->丟棄全部的舊數據,載入主服務器的快照文件-->完成快照文件的解釋,開始接受命令請求-->執行從主服務器發送的全部的寫命令;

注意:redis支持主從鏈,即從服務器還能夠有從服務器,可是從服務器A複製從服務器B的過程和從服務器B複製主服務器是有區別的;從服務器B向從服務器A發送完畢快照文件後,會先斷開與從服務器A的鏈接,從服務器A須要從新鏈接而且請求同步;

redis的事務

  • redis有像關係型數據庫同樣的事務機制來保證多條命令做爲原子操做;事務中的命令要麼全執行,要麼全不執行;

  • 事務的完整過程:開始事務-->命令進入緩存-->執行事務;

事務的基本使用

# 開啓一個事務
multi      # 提交命令後,redis會將後面的操做保存起來
# 提交事務
exec   # 提交命令後,redis會執行前面保存的全部的命令

# 取消事務
discard   # 若是書寫命令隊列的過程當中須要取消事務時使用
  • redis事務中在寫命令隊列的時候,若是中間發生了語法錯誤,而且redis報了錯,那麼這個事務全部的命令都會取消執行;
> lpush list a b c 
(integer) 3
> multi
OK
> lpush list d
QUEUED
> lpuxh list f
(error) ERR unknown command 'lpuxh'
> lrange list 0 10
QUEUED
> exec
(error) EXECABORT Transaction discarded because of previous errors.
> lrange list 0 10
1) "c"
2) "b"
3) "a"

# 全部的命令都沒有執行
  • 但有一些錯誤redis在執行以前並不能感知,這時redis會執行全部的的命令,客戶端必須本身處理錯誤;
> lpush li blue red green
(integer) 3
> multi
OK
> get li
QUEUED
> lpush li white
QUEUED
> exec
1) (error) WRONGTYPE Operation against a key holding the wrong kind of value
2) (integer) 4
> lrange li 0 10
1) "white"
2) "green"
3) "red"
4) "blue"

# 全部的命令都執行了,只不過有的命令執行失敗

注意點

  • redis的開啓事務是將命令暫時保存在一個隊列裏,執行時依次操做;若是命令隊列有一條出現語法錯誤,整個事務建立會失敗;

  • redis沒有提供事務的回滾功能,客戶端必須本身處理失敗的命令;

事務鎖

# 基本命令
watch key key ..   # 監控鍵值

# 取消對全部鍵的監控
unwatch
  • 因爲redis的事務中的命令實際上是緩存隊列,而且redis能夠防止在事務的執行過程當中有其餘的命令插入,即具備隔離性;可是在多個客戶端進行併發操做時存在數據沒法同步的問題;如客戶端A、B同時操做鍵key的值加一,預期結果爲增長2,實際可能只有1.

  • 爲了解決這個問題,redis引入了watch監控鍵;

> watch num 
OK
> set num 7
OK
> multi
OK
> set num 5
QUEUED
> exec
(nil)
> get num
"7"
  • 能夠看到事務並無執行成功,wetch能夠監控鍵,若是在監控後,鍵的值發生了改變,那麼redis後面與這個鍵相關的事務操做將會失敗,同時在exec執行後,鍵的監控會被取消;

注意:不管監控多少個鍵或事務中有沒有與該鍵相關的命令,在最近的一個執行了exec,不管事務執行有沒有成功,watch監控的全部鍵都將會取消,後面的事務再也不受影響。

說明:使用watch監控實現併發修改鍵值,若是事務被取消,須要手動從新執行事務;

問題

  • 以上可知,redis實現的是相似樂觀鎖(即預期併發時沒有出現競爭修改同一個鍵值的情況),這種狀況在併發量低時影響不大,可是高併發時幾乎確定出現競爭,併發修改鍵值程序重試的次數愈來愈多,資源被白白浪費,須要使用其餘的方法實現悲觀鎖機制,這點後面會繼續研究;
  • 做者:天宇之遊
  • 出處:http://www.cnblogs.com/cwp-bg/
  • 本文版權歸做者和博客園共有,歡迎轉載、交流,但未經做者贊成必須保留此段聲明,且在文章明顯位置給出原文連接。
相關文章
相關標籤/搜索