原本最近打算學習Unix網絡編程,可是項目中項目中用到了Redis Cluster,本身對Redis集羣這方面並非很熟悉,因此打算花點時間來系統的學習一下Redis,Redis主要分四個部分;
1.數據結構與對象
2.單機數據庫實現
3.多機數據庫實現
4.獨立功能的實現
本文先簡單介紹下Redis 的集羣實現,後續會針對上面的在進行詳解;node
Redis由於具備豐富的數據結構和超高額性能以及簡單的協議,使其可以很好的做用爲數據庫的上游。可是當數據量變大的時候(如數據達到千萬級別時),會受限以多個地方,單機內存有限、單點問題、動態擴容問題等。
爲了解決上面的問題,Redis的集羣方案就顯得比較重要了。使用Redis集羣一般有三個途徑;redis
本文主要介紹一下官方提供的 Redis Cluster,Redis Cluster 是在Redis 3.0開始支持的,3.0主要是更新了多機方面的功能,在5.0以前Redis Cluster 主要是採用 Redis提供的 redis-trib.rb(Ruby實現的腳本,須要安裝相應的依賴環境)這個管理工具。5.0版本開始支持 --cluster 參數來進行管理。數據庫
Redis Cluster 並無使用一致性hash,而是引用了一個叫哈希槽的概念。 Redis Cluster 中有16384個哈希槽,每一個key經過CRC16校驗後對16384取模來決定放置哪一個槽。集羣的每一個節點分配一部分的哈希槽,這樣有一點很方便就是在增長和移除的時候,只須要分配相應的哈希槽就能夠了。
在單命令執行下和單機Redis並沒有區別,客戶端寫入命令,由Redis Cluster計算當前key屬於哪一個槽點而後返回相應數據。可是多命令的狀況下(如求集合的交集)有可能多個key不在同一個槽點裏,能夠採用{}來設置須要多命令執行的key。{key}:xxx它只對括號裏面的進行hash操做,因此能夠保證在同一個哈希槽中。編程
Redis Cluster 的每一個節點都須要維護兩個TCP端口,用於爲Redis提供服務的普通端口,例如6370,加上經過向數據端口添加10000得到的端口,如16379。
第二個端口是用於集羣總線,使用二進制節點到節點的通訊通道(gossip 協議)。總線端口的偏移量是固定的,始終爲10000。節點使用的集羣總線主要用來進行故障檢測、數據更新、故障轉移受權等 。爲了保證集羣的正常使用,客戶端永不該該嘗試與集羣總線通信,始終使用正常的端口通信。防火牆要打開這兩個端口,不然Redis節點將沒法通信。服務器
爲了提升可用性,Redis 採用了主從模型,其中每個節點擁有一個master N個slave,若是其中一個節點的 master出現問題,它的一個slave會被選舉爲master節點。若是某個節點的master和slave所有掛掉,那麼這個Redis Cluster將沒法服務。其中還有一點須要注意,選舉的時候須要有其它一半以上的master節點參加。若是沒有一半以上的master節點存活參與選舉則slave不會被選舉爲master。如兩個master服務,其中一個掛掉,掛掉服務的slave是不會被選舉成爲master的,由於存活的master不到一半以上。或者是master恰好分配在一臺服務器上,這個服務器掛掉,即便他的slave存在,集羣也是沒辦法將slave節點選舉爲master節點作到自動故障轉移的。因此咱們在分配節點的時候必定要注意合理分配,最好本身分配(默認自動分配)。網絡
首先咱們要知道Redis Cluster 並不提供強一致性。這意味着在某種條件下,Redis 會形成數據丟失。主要緣由是由於Redis Cluster 採用了異步複製:數據結構
基於這種狀況,若是出現了上面的故障問題,主機在崩潰後沒來得及通知其slave服務,而且這個slave被選爲master,那麼這個數據則會永久丟失。
Redis Cluster 也支持同步複製,經過WAIT命令實現,這樣會大大的下降數據丟失的可能性。但即便是同步複製,也不可能保證強一致性。在更復雜的狀況下老是能夠實現失敗場景,沒法接收寫入的slave被選爲master。
還有另外一個值得注意的狀況是,Redis Cluster將丟失寫入,這種狀況發生在網絡分區中 。客戶端向節點請求是有最大時間限制(cluster-node-timeout) 不推薦用redis事務機制,由於採用了分片處理。若是一個事物中涉及到多個key的操做的話,這麼多個key不必定都存儲在同一個節點上。
Redis 分佈式鎖
若是確實須要強一致性的話能夠考慮採用分佈式鎖:併發