Redis入門總結(二):主從複製,事務和發佈訂閱

(尊重勞動成果,轉載請註明出處:https://yangwenqiang.blog.csdn.net/article/details/90414751冷血之心的博客)

關注微信公衆號(文強的技術小屋),學習更多技術知識,一起遨遊知識海洋~

快速導航:

Redis入門總結(一):redis配置文件,五種數據結構,線程模型和持久化方式

Redis入門總結(二):主從複製,事務和發佈訂閱

Redis入門總結(三):redis實現分佈式鎖的正確姿勢

這篇文章主要總結了:redis的主從複製,redis的事務以及redis實現發佈訂閱。

  1. 主從複製:

    1. 背景:

      1. 隨着項目訪問量的增加,對Redis服務器的操作也越加頻繁,雖然Redis讀寫速度都很快,但是一定程度上也會造成一定的延時,那麼爲了解決訪問量大的問題,通常會採取的一種方式是主從架構Master/Slave,Master 以寫爲主,Slave 以讀爲主,Master 主節點更新後根據配置,自動同步到從機Slave 節點。

    2. 通過  info replication 命令查看節點角色

    3. 哨兵模式:

      1. 解決了主節點掛掉之後,從節點還是從節點,無法自動轉爲主節點,導致系統無法正常工作的問題

      2. 哨兵模式監控redis是否按照預期良好地運行(至少是保證主節點是存在的),若一臺主機出現問題時,哨兵會自動將該主機下的某一個從機設置爲新的主機,並讓其他從機和新主機建立主從關係。

      3. 哨兵模式也可以設置爲集羣模式,解決哨兵的單節點故障

    4. 主從複製原理:

      1. 舊版同步:

        1. 當從節點發出 SLAVEOF 命令,要求從服務器複製主服務器時,從服務器通過向主服務器發送 SYNC 命令來完成。該命令執行步驟:

          1. 從服務器向主服務器發送 SYNC 命令

          2. 收到 SYNC 命令的主服務器執行 BGSAVE 命令,在後臺生成一個 RDB 文件,並使用一個緩衝區記錄從開始執行的所有寫命令

          3. 當主服務器的 BGSAVE 命令執行完畢時,主服務器會將 BGSAVE 命令生成的 RDB 文件發送給從服務器,從服務器接收此 RDB 文件,並將服務器狀態更新爲RDB文件記錄的狀態。

          4. 主服務器將緩衝區的所有寫命令也發送給從服務器,從服務器執行相應命令。

      2. 命令傳播:

        1. 當同步操作完成之後,主服務器會進行相應的修改命令,這時候從服務器和主服務器狀態就會不一致。

        2. 爲了讓主服務器和從服務器保持狀態一致,主服務器需要對從服務器執行命令傳播操作,主服務器會將自己的寫命令發送給從服務器執行。從服務器執行相應的命令之後,主從服務器狀態繼續保持一致。

        3. 問題:

          1. 如果從服務器正在同步,但是斷開了連接,在其恢復之前,主服務器又進行了一系列的寫操作,那麼我們需要重新生成RDB文件來進行同步操作,這樣會導致效率降低。

          2. 這樣雖然能夠保證一致性,但是其實斷開連接之前主從服務器狀態是保持一致的,不一致的是從服務器斷開連接,而主服務器執行了一些寫命令,那麼從服務器恢復連接後能不能只要斷開連接的哪些寫命令,而不是整個RDB快照呢?

        4. 解決辦法:

          1. Redis從2.8版本之後,使用了新的同步命令 PSYNC 來代替 SYNC 命令。該命令的部分重同步功能用於處理斷線後重複製的效率問題。也就是說當從服務器在斷線後重新連接主服務器時,主服務器只將斷開連接後執行的寫命令發送給從服務器,從服務器只需要接收並執行這些寫命令即可保持主從一致。

      3. 主從複製的缺點:

        1. 當系統繁忙的時候,主從延遲會比較大。

  2. redis對事務的支持:

    1. redis 是單進程程序,並且它保證在執行事務時,不會對事務進行中斷,事務可以運行直到執行完所有事務隊列中的命令爲止。因此,Redis的事務支持隔離性

    2. redis會將一個事務中的所有命令序列化,然後按順序執行。Redis不可能在一個Redis事務的執行過程中插入執行另一個客戶端發出的請求。這樣便能保證Redis將這些命令作爲一個單獨的隔離操作執行。

    3. 操作事務的相關命令:

      1. MULTI  :標記一個事務塊的開始。

      2. EXEC :執行所有事務塊內的命令。

      3. DISCARD :取消事務,放棄執行事務塊內的所有命令。

      4. UNWATCH :取消 WATCH 命令對所有 key 的監視。

      5. WATCH key [key ...] :監視一個(或多個) key ,如果在事務執行之前這個(或這些) key 被其他命令所改動,那麼事務將被打斷。

    4. redis事務不支持回滾:

      1. 只有當被調用的Redis命令有語法錯誤時,這條命令纔會執行失敗(在將這個命令放入事務隊列期間,Redis能夠發現此類問題),或者對某個鍵執行不符合其數據類型的操作:實際上,這就意味着只有程序錯誤纔會導致Redis命令執行失敗,這種錯誤很有可能在程序開發期間發現,一般很少在生產環境發現。

      2. Redis已經在系統內部進行功能簡化,這樣可以確保更快的運行速度,因爲Redis不需要事務回滾的能力。

    5. redis以 MULTI 開始一個事務,然後將多個命令入隊到事務中,最後由 EXEC 命令觸發事務, 一併執行事務中的所有命令:

    6. 單個 Redis 命令的執行是原子性的,但 Redis 沒有在事務上增加任何維持原子性的機制,所以 Redis 事務的執行並不是原子性的

      1. 當EXEC調用之後,開始從隊列裏邊取出命令執行,一條命令執行失敗,並不會影響到其餘命令的繼續執行。

      2. redis事務爲什麼不支持原子性?

        1. 當我們開啓事務時,將一系列的命令都封裝塞進了一個隊列,當EXEC開始執行的時候,只有錯誤的命令纔會導致執行失敗,而這通常在將該命令塞進隊列的時候已經報錯,我們應該可以提前發現該錯誤纔對。

    7. 事務內部錯誤如何處理?

      1. 錯誤分類:

        1. 一個命令可能會在被放入隊列時失敗。因此,事務有可能在調用EXEC命令之前就發生錯誤。例如,這個命令可能會有語法錯誤(參數的數量錯誤、命令名稱錯誤,等等),或者可能會有某些臨界條件(例如:如果使用maxmemory指令,爲Redis服務器配置內存限制,那麼就可能會有內存溢出條件)。

        2. 在調用EXEC命令之後,事務中的某個命令可能會執行失敗。例如,我們對某個鍵執行了錯誤類型的操作(例如,對一個字符串(String)類型的鍵執行列表(List)類型的操作)。

      2. 解決辦法:

        1. 可以使用Redis客戶端檢測第一種類型的錯誤,在調用EXEC命令之前,這些客戶端可以檢查被放入隊列的命令的返回值:

          1. 如果命令的返回值是QUEUE字符串,那麼就表示已經正確地將這個命令放入隊列;

          2. 否則,Redis將返回一個錯誤。如果將某個命令放入隊列時發生錯誤,那麼大多數客戶端將會中止事務,並且丟棄這個事務。

        2. 在Redis 2.6.5版本之前,如果發生了上述的錯誤,那麼在客戶端調用了EXEC命令之後,Redis還是會運行這個出錯的事務,執行已經成功放入事務隊列的命令,而不會關心先前發生的錯誤。從2.6.5版本開始,Redis在遭遇上述錯誤時,服務器會記住事務積累命令期間發生的錯誤。然後,Redis會拒絕執行這個事務,在運行EXEC命令之後,便會返回一個錯誤消息。最後,Redis會自動丟棄這個事務。這樣便能輕鬆地混合使用事務和管道。在這種情況下,客戶端可以一次性地將整個事務發送至Redis服務器,稍後再一次性地讀取所有的返回值。

        3. 相反,在調用EXEC命令之後發生的事務錯誤,Redis不會進行任何特殊處理:在事務運行期間,即使某個命令運行失敗,所有其他的命令也將會繼續執行。

    8. redis通過WATCH監視命令實現樂觀鎖:

      1. redis使用 check-and-set 操作實現樂觀鎖。WATCH 命令可以爲 Redis 事務提供 check-and-set (CAS)行爲。

      2. 類似Java中的CompareAndSet機制,被 WATCH 的鍵會被監視,並會發覺這些鍵是否被改動過了。

      3. 如果有至少一個被監視的鍵在 EXEC 執行之前被修改了, 那麼整個事務都會被取消, EXEC 返回空多條批量回復(null multi-bulk reply)來表示事務已經失敗。

    9. redis事務總結:

      1. 單獨的隔離操作:事務中的所有命令會被序列化、按順序執行,在執行的過程中不會被其他客戶端發送來的命令打斷

      2. 沒有隔離級別的概念:隊列中的命令在事務沒有被提交之前不會被實際執行

      3. 不保證原子性:redis中的一個事務中如果存在命令執行失敗,那麼其他命令依然會被執行,沒有回滾機制

  3. redis信息通知(發佈/訂閱模式):

    1. 優點:

      1. 松耦合。生產者和消費者無需知道彼此的實現細節,只需要約定好任務的描述格式。這使得生產者和消費者可以由不同的團隊使用不同的編程語言編寫

      2. 易於擴展。消費者可以有多個,而且可以分佈在不同的服務器中, 藉此可以輕易地降低單臺服務器的負載

    2. 使用LPUSH和RPOP命令實現隊列

    3. 利用BRPOP命令可以檢測多個key的功能。如果多個鍵都有元素,則按照從左到右順序取第一個鍵中的一個元素。因此,要實現優先級隊列,把優先級高的key放到前面就ok了。

    4. 發佈訂閱模式:

      1. "發佈/訂閱"模式中包含兩種角色,分別是發佈者和訂閱者。

      2. 訂閱者可以訂閱一個或若干個頻道(channel)

      3. 發佈者可以向指定的頻道發送消息,所有訂閱此頻道的訂閱者都會收到此消息。

以上內容摘抄總結與網絡,感謝各位前輩的總結與鋪墊。接下來我會繼續更新Redis相關文章,全部會以這種筆記形式給出,大家對筆記中不太懂的地方,可以發表評論,我們一起研究學習,此處權當給大家列個學習提綱了。

如果對你有幫助,記得點贊哦~歡迎大家關注我的博客,可以進羣366533258一起交流學習哦~

本羣給大家提供一個學習交流的平臺,內設菜鳥Java管理員一枚、精通算法的金牌講師一枚、Android管理員一枚、藍牙BlueTooth管理員一枚、Web前端管理一枚以及C#管理一枚。歡迎大家進來交流技術。

關注微信公衆號(文強的技術小屋),學習更多技術知識,一起遨遊知識海洋~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章