redis的主從、集群、哨兵
參考:
https://blog.csdn.net/robertohuang/article/details/70741575
https://blog.csdn.net/robertohuang/article/details/70766809
https://blog.csdn.net/robertohuang/article/details/70768922
https://blog.csdn.net/robertohuang/article/details/70833231
https://blog.csdn.net/u011204847/article/details/51307044
Redis簡介及單機版編譯安裝詳細教程
1.Redis簡介
Redis(Remote Dictionary Server)是一種Nosql技術,它是一個開源的高級kv數據結構存儲系統,它經常拿來和Memcached相比較,但是Memcached不提供持久化的數據保存機制而Redis可以將數據存在磁盤中,Redis不僅僅是能夠存儲key和value這種簡單的鍵值對,還能存儲例如集合、hash表、列表、字典等。Redis在整個運行過程中,數據統統都是存儲在內存中的,因此,性能是相當高的,由於此特性,Redis對於內存的要求比較高,它會周期性的將內存中的數據寫入在磁盤中,從而實現數據持久化的訪問能力,但是這種存儲只是保證Redis在下次啟動還有數據可以讀取,而不是提供訪問。Redis是單線程服務的,只有一個線程。Redis還支持主從模式以及支持通過lua腳本去編寫擴展,並且支持高可用和分布式集群解決方案。
2.Redis特點
1.異常快速:Redis數據庫完全在內存中,因此處理速度非常快,每秒能執行約11萬集合,每秒約81000+條記錄。 2.數據持久化:Redis支持數據持久化,可以將內存中的數據存儲到磁盤上,方便在宕機等突發情況下快速恢復。 3.數據一致性:所有Redis操作是原子的,這保證了如果兩個客戶端同時訪問的Redis服務器將獲得更新后的值。 4.支持豐富的數據類型:相比許多其他的鍵值對存儲數據庫,Redis擁有一套較為豐富的數據類型。支持存儲string、list、hash、set、Sorted Set,Bitmap,HyperLoglogs。 5.多功能實用工具:Redis是一個多實用的工具,可以在多個用例如緩存,消息,隊列使用(Redis原生支持發布/訂閱),任何短暫的數據,應用程序,如Web應用程序會話,網頁命中計數等。
備注:Redis是單線程,但是這並不意味着會成為運行時的瓶頸。
3.Redis單機版的安裝
3.1 編譯和安裝所需的包:
# yum install gcc tcl
3.2 解壓Redis(此處須自行去官網下載Redis安裝包,並上傳到服務器)
# tar -zxvf redis-3.2.8.tar.gz
3.3 進入Redis所在文件夾
# cd redis-3.2.8
3.4 編譯安裝Redis
# make PREFIX=/opt/redis/redis-3.2.8 install
3.5 安裝完成后,可以看到/opt/redis/redis-3.2.8目錄下有一個bin目錄,bin目錄里就是redis的命令腳本:
redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server
3.6 采用默認配置文件方式啟動Redis
./redis-server
3.7 如需指定配置文件,在./redis-server后拼接上配置文件路徑,如:
./redis-server /opt/redis/redis-3.2.8/redis.conf
3.8 啟動redis后,使用ps -ef | grep redis查看redis運行狀態,如下圖所示則說明啟動成功:
Redis主從架構和主從從架構集群搭建詳細步驟
本文主要介紹Redis主從架構和主從從架構,耐心閱讀完本文,相信你會對Redis主從架構和主從從架構有一個清晰的認識。
Redis主從復制的功能非常強大,它有以下好處:
1.避免Redis單點故障
2.構建讀寫分離架構,滿足讀多寫少的應用場景
1.主從架構
1.1 Redis主從架構拓撲圖結構
1.2 主從結構搭建
Redis集群不用安裝多個Redis,只需復制多個配置文件,修改即可。所以如果要進行主從結構搭建,需先安裝單機版Redis。單機版Redis安裝可參照:單機版Redis安裝教程
1.2.1 在安裝好單機版的前提下,復制三份配置文件
進入redis所在目錄
# cd /opt/redis/redis-3.2.8 創建6379、6380、6381目錄,分別將安裝目錄下的redis.conf拷貝到這三個目錄下。 # mkdir -p /opt/redis/6379 && cp redis.conf /opt/redis/6379/6379.conf # mkdir -p /opt/redis/6380 && cp redis.conf /opt/redis/6380/6380.conf # mkdir -p /opt/redis/6381 && cp redis.conf /opt/redis/6381/6381.conf
1.2.2 分別修改配置文件
# vim /opt/redis/6379/6379.conf # Redis使用后台模式 daemonize yes # 關閉保護模式 protected-mode no # 注釋以下內容開啟遠程訪問 # bind 127.0.0.1 # 修改啟動端口為6379 port 6379 # 修改pidfile指向路徑 pidfile /opt/redis/6379/redis_6379.pid 以此類推,修改端口6380及6381配置。
1.2.3 分別啟動三個Redis實例
/opt/redis/redis-3.2.8/bin/redis-server /opt/redis/6379/6379.conf /opt/redis/redis-3.2.8/bin/redis-server /opt/redis/6380/6380.conf /opt/redis/redis-3.2.8/bin/redis-server /opt/redis/6381/6381.conf
1.2.4 設置主從
在Redis中設置主從有2種方式:
1.在redis.conf中設置slaveof
a) slaveof <masterip> <masterport> 2、 使用redis-cli客戶端連接到redis服務,執行slaveof命令 a) slaveof <masterip> <masterport> 第二種方式在重啟后將失去主從復制關系。 我們這里使用第二種方式設置主從: 使用Redis客戶端連接上6380端口 # redis-cli -h 192.168.29.128 -p 6380 設置6380端口Redis為6379的從 192.168.29.128:6380> slaveof 192.168.29.128 6379 OK 使用Redis客戶端連接上6381端口 # redis-cli -h 192.168.29.128 -p 6381 設置6381端口Redis為6379的從 192.168.29.128:6381> slaveof 192.168.29.128 6379 OK
1.2.5 查看Redis主從關系
使用Redis客戶端連接上6379端口 # redis-cli -h 192.168.29.128 -p 6379 查看Redis主從關系 如下圖所示 192.168.29.128:6379> info replication
role:角色信息
slaveX:從庫信息
connected_slaves:從庫數量
1.2.6 測試
在主庫寫入數據
在從庫讀取數據
2. 主從從架構
2.1 Redis主從從架構拓撲圖結構
2.2 主從從架構搭建
Redis的主從架構的缺點是所有的slave節點數據的復制和同步都由master節點來處理,會照成master節點壓力太大,所以我們使用主從從結構來處理
2.2.1 前面步驟同主從架構一致,只是在設置主從結構時,設置6380為6379的從,6381為6380的從
使用Redis客戶端連接上6380端口 # redis-cli -h 192.168.29.128 -p 6380 設置6380端口Redis為6379的從 192.168.29.128:6380> slaveof 192.168.29.128 6379 OK 使用Redis客戶端連接上6381端口 # redis-cli -h 192.168.29.128 -p 6381 設置6381端口Redis為6380的從 192.168.29.128:6381> slaveof 192.168.29.128 6380 OK
2.2.2 查看主從從架構信息如下:
2.2.3 測試
在主庫寫入數據
在從庫查詢數據
3.從庫只讀
默認情況下redis數據庫充當slave角色時是只讀的不能進行寫操作
可以在配置文件中開啟非只讀:slave-read-only no
4.主從復制的過程原理
1.當從庫和主庫建立MS關系后,會向主數據庫發送SYNC命令
2.主庫接收到SYNC命令后會開始在后台保存快照(RDB持久化過程),並將期間接收到的寫命令緩存起來
3.當快照完成后,主Redis會將快照文件和所有緩存的寫命令發送給從Redis
4.從Redis接收到后,會載入快照文件並且執行收到的緩存的命令
5.之后,主Redis每當接收到寫命令時就會將命令發送從Redis,從而保證數據的一致
5.無磁盤復制
通過前面的復制過程我們了解到,主庫接收到SYNC的命令時會執行RDB過程,即使在配置文件中禁用RDB持久化也會生成,那么如果主庫所 在的服務器磁盤IO性能較差,那么這個復制過程就會出現瓶頸,慶幸的是,Redis在2.8.18版本開始實現了無磁盤復制功能(不過該功能 還是處於試驗階段)。 原理:Redis在與從數據庫進行復制初始化時將不會將快照存儲到磁盤,而是直接通過網絡發送給從數據庫,避免了IO性能差問題。 開啟無磁盤復制:repl-diskless-sync yes
注:如果要取消Redis主從關系,可以在對應的從庫執行SLAVEOF NO ONE命令,取消主從關系
Redis容災部署哨兵(sentinel)機制配置詳解及原理介紹
1.為什么要用到哨兵
哨兵(Sentinel)主要是為了解決在主從復制架構中出現宕機的情況,主要分為兩種情況:
1.從Redis宕機 這個相對而言比較簡單,在Redis中從庫重新啟動后會自動加入到主從架構中,自動完成同步數據。在Redis2.8版本后,主從斷線后恢復 的情況下實現增量復制。 2.主Redis宕機 這個相對而言就會復雜一些,需要以下2步才能完成 i.第一步,在從數據庫中執行SLAVEOF NO ONE命令,斷開主從關系並且提升為主庫繼續服務 ii.第二步,將主庫重新啟動后,執行SLAVEOF命令,將其設置為其他庫的從庫,這時數據就能更新回來 由於這個手動完成恢復的過程其實是比較麻煩的並且容易出錯,所以Redis提供的哨兵(sentinel)的功能來解決
2.什么是哨兵
Redis-Sentinel是用於管理Redis集群,該系統執行以下三個任務: 1.監控(Monitoring):Sentinel會不斷地檢查你的主服務器和從服務器是否運作正常 2.提醒(Notification):當被監控的某個Redis服務器出現問題時,Sentinel可以通過API向管理員或者其他應用程序發送通知 3.自動故障遷移(Automatic failover):當一個主服務器不能正常工作時,Sentinel 會開始一次自動故障遷移操作,它會將失效主 服務器的其中一個從服務器升級為新的主服務器,並讓失效主服務器的其他從服務器改為復制新的主服務器;當客戶端試圖連接失效的主 服務器時,集群也會向客戶端返回新主服務器的地址,使得集群可以使用新主服務器代替失效服務器
3.Sentinel集群搭建
3.1 Sentinel集群拓撲圖
多個哨兵,不僅同時監控主從數據庫,而且哨兵之間互為監控
3.2 在保證Redis主從架構集群可用的前提下,復制三份配置文件
進入redis所在目錄
# cd /opt/redis/redis-3.2.8 創建6379、6380、6381目錄,分別將安裝目錄下的sentinel.conf拷貝到這三個目錄下 # mkdir -p /opt/redis/6379 && cp sentinel.conf /opt/redis/6379/26379.conf # mkdir -p /opt/redis/6380 && cp sentinel.conf /opt/redis/6380/26380.conf # mkdir -p /opt/redis/6381 && cp sentinel.conf /opt/redis/6381/26381.conf
3.3 分別配置哨兵
修改sentinel配置文件
vim /opt/redis/6379/26379.conf 修改內容: # 添加守護進程模式 daemonize yes # 添加指明日志文件名 logfile "/opt/redis/6379/sentinel26379.log" # 修改工作目錄 dir "/opt/redis/6379" # 修改啟動端口 port 26379 # 關閉保護模式 protected-mode no # 修改sentinel monitor sentinel monitor redis-test-master 192.168.29.128 6379 2 # 將配置文件中mymaster全部替換redis-test-master 依次修改26380,26381配置 說明: redis-test-master:監控主數據的名稱,自定義即可,可以使用大小寫字母和“.-_”符號 192.168.29.128:監控的主數據庫的IP 6379:監控的主數據庫的端口 2:最低通過票數
3.4 啟動哨兵進程
redis-sentinel /opt/redis/6379/26379.conf 或者 redis-server /opt/redis/6379/26379.conf --sentinel redis-sentinel /opt/redis/6380/26380.conf 或者 redis-server /opt/redis/6380/26380.conf --sentinel redis-sentinel /opt/redis/6380/26380.conf 或者 redis-server /opt/redis/6381/26381.conf --sentinel
3.5 哨兵模式常用命令
1.查看sentinel的基本狀態信息 127.0.0.1:26379> INFO 2.列出所有被監視的主服務器,以及這些主服務器的當前狀態 127.0.0.1:26379> SENTINEL MASTERS redis-test-master 3.列出給定主服務器的所有從服務器,以及這些從服務器的當前狀態 127.0.0.1:26379> SENTINEL SLAVES redis-test-master 4.返回給定名字的主服務器的IP地址和端口號 127.0.0.1:26379> SENTINEL GET-MASTER-ADDR-BY-NAME redis-test-master 5.重置所有名字和給定模式pattern相匹配的主服務器,重置操作清除主服務器目前的所有狀態,包括正在執行中的故障轉移,並移除目 前已經發現和關聯的,主服務器的所有從服務器和Sentinel 127.0.0.1:26379> SENTINEL RESET redis-test-master 6.當主服務器失效時,在不詢問其他Sentinel意見的情況下,強制開始一次自動故障遷移,但是它會給其他Sentinel發送一個最新的配 置,其他sentinel會根據這個配置進行更新 127.0.0.1:26379> SENTINEL FAILOVER redis-test-master 7.查看其它哨兵信息 127.0.0.1:26379> SENTINEL sentinels redis-test-master
3.6 查看配置中是否多了如下內容
3.7 Java代碼測試哨兵
public class RedisTest { public static void main(String[] args) { Set<String> sentinels = new HashSet<String>(); sentinels.add(new HostAndPort("192.168.29.128", 26379).toString()); sentinels.add(new HostAndPort("192.168.29.128", 26380).toString()); sentinels.add(new HostAndPort("192.168.29.128", 26381).toString()); JedisSentinelPool sentinelPool = new JedisSentinelPool("redis-test-master", sentinels); System.out.println("Current master: " + sentinelPool.getCurrentHostMaster().toString()); Jedis master = sentinelPool.getResource(); master.set("username", "RobertoHuang"); sentinelPool.returnResource(master); Jedis master2 = sentinelPool.getResource(); String value = master2.get("username"); System.out.println("username: " + value); master2.close(); sentinelPool.destroy(); } } 輸出結果: Current master: 192.168.29.128:6379 username: RobertoHuang
3.8 測試Sentinel是否正常工作
3.8.1 測試集群環境如下
3.8.2 關閉端口為6379的Redis
3.8.3 查看新的集群架構
3.8.4 重新啟動端口號為6379的Redis 查看集群架構
該過程是6379Redis宕機->6380切換成Master->6379和6381切換為6380的SLAVE->6379重新啟動->6379為6380SLAVE
3.8.5 Sentinel日志分析
26379日志
26380日志
26381日志
4.Sentinel原理介紹
首先解釋2個名詞:SDOWN和ODOWN.
SDOWN:subjectively down,直接翻譯的為”主觀”失效,即當前sentinel實例認為某個redis服務為”不可用”狀態.
ODOWN:objectively down,直接翻譯為”客觀”失效,即多個sentinel實例都認為master處於”SDOWN”狀態,那么此時master將處於ODOWN,ODOWN可以簡單理解為master已經被集群確定為”不可用”,將會開啟failover
SDOWN與ODOWN轉換過程:
i.每個sentinel實例在啟動后,都會和已知的slaves/master以及其他sentinels建立TCP連接,並周期性發送PING(默認為1秒),在交互中,如果redis-server無法在”down-after-milliseconds”時間內響應或者響應錯誤信息,都會被認為此redis-server處於SDOWN狀態.
ii.SDOWN的server為master,那么此時sentinel實例將會向其他sentinel間歇性(一秒)發送”is-master-down-by-addr <ip> <port>”指令並獲取響應信息,如果足夠多的sentinel實例檢測到master處於SDOWN,那么此時當前sentinel實例標記master為ODOWN…其他sentinel實例做同樣的交互操作.配置項”sentinel monitor <mastername><masterip> <masterport> <quorum>”,如果檢測到master處於SDOWN狀態的slave個數達到<quorum>,那么此時此sentinel實例將會認為master處於ODOWN.
每個sentinel實例將會間歇性(10秒)向master和slaves發送”INFO”指令,如果master失效且沒有新master選出時,每1秒發送一次”INFO”;”INFO”的主要目的就是獲取並確認當前集群環境中slaves和master的存活情況.
經過上述過程后,所有的sentinel對master失效達成一致后,開始failover.
Sentinel與slaves”自動發現”機制:
在sentinel的配置文件中,都指定了port,此port就是sentinel實例偵聽其他sentinel實例建立鏈接的端口.在集群穩定后,最終會每個sentinel實例之間都會建立一個tcp鏈接,此鏈接中發送”PING”以及類似於”is-master-down-by-addr”指令集,可用用來檢測其他sentinel實例的有效性以及”ODOWN”和”failover”過程中信息的交互.在sentinel之間建立連接之前,sentinel將會盡力和配置文件中指定的master建立連接.sentinel與master的連接中的通信主要是基於pub/sub來發布和接收信息,發布的信息內容包括當前sentinel實例的偵聽端口.
Redis Cluster高可用(HA)集群環境搭建詳細步驟
1.為什么要有集群
由於Redis主從復制架構每個數據庫都要保存整個集群中的所有數據,容易形成木桶效應,所以Redis3.0之后的版本添加特性就是集群(Cluster)
2.Redis集群架構說明
架構細節:
(1)所有的redis節點彼此互聯(PING-PONG機制),內部使用二進制協議優化傳輸速度和帶寬.
(2)節點的fail是通過集群中超過半數的master節點檢測失效時才生效.
(3)客戶端與redis節點直連,不需要中間proxy層.客戶端不需要連接集群所有節點,連接集群中任何一個可用節點即可
(4)redis-cluster把所有的物理節點映射到[0-16383]slot上,cluster 負責維護node<->slot<->key
3.Redis Cluster環境搭建
3.1 分別修改配置文件,將端口分別設置為:6379、6380、6381,同時要設置pidfile文件為不同的路徑。並且允許集群模式,修改集群配置文件指向地址,並且開啟遠程訪問
修改配置文件
# vim /opt/redis/6379/6379.conf # 開啟守護進程模式 daemonize yes # 修改啟動端口為6379 port 6379 # 修改pidfile指向路徑 pidfile /opt/redis/6379/redis_6379.pid # 開啟允許集群 cluster-enabled yes # 修改集群配置文件指向路徑 cluster-config-file nodes-6379.conf # 注釋一下內容開啟遠程訪問 # bind 127.0.0.1 # 關閉保護模式 protected-mode no 以此類推,修改端口6380及6381配置。
3.2 分別啟動redis實例
# cd /opt/redis/redis-3.2.8/bin # ./redis-server /opt/redis/6379/6379.conf # ./redis-server /opt/redis/6380/6380.conf # ./redis-server /opt/redis/6381/6381.conf
3.3 查看redis狀態
說明redis已經是以集群方式啟動了,但是redis之間關系還沒確定下來
3.4 因為redis-trib.rb是由ruby語言編寫的所以需要安裝ruby環境
安裝ruby環境
# yum -y install zlib ruby rubygems 自行上傳redis-3.2.1.gem然后安裝 # gem install -l redis-3.2.1.gem
3.5 建立集群Redis關系
首先,進入redis的安裝包路徑下
# cd /opt/redis/redis-3.2.8/src 執行命令: # ./redis-trib.rb create --replicas 0 192.168.29.128:6379 192.168.29.128:6380 192.168.29.128:6381 說明:--replicas 0:指定了從數據的數量為0 注意:這里不能使用127.0.0.1,否則在Jedis客戶端使用時無法連接到!
3.6 如果出現如下異常
/usr/local/share/gems/gems/redis-3.2.1/lib/redis/client.rb:113:in `call': ERR Slot 0 is already busy (Redis::CommandError) from /usr/local/share/gems/gems/redis-3.2.1/lib/redis.rb:2556:in `block in method_missing' from /usr/local/share/gems/gems/redis-3.2.1/lib/redis.rb:37:in `block in synchronize' from /usr/share/ruby/monitor.rb:211:in `mon_synchronize' from /usr/local/share/gems/gems/redis-3.2.1/lib/redis.rb:37:in `synchronize' from /usr/local/share/gems/gems/redis-3.2.1/lib/redis.rb:2555:in `method_missing' from ./redis-trib.rb:212:in `flush_node_config' from ./redis-trib.rb:776:in `block in flush_nodes_config' from ./redis-trib.rb:775:in `each' from ./redis-trib.rb:775:in `flush_nodes_config' from ./redis-trib.rb:1296:in `create_cluster_cmd' from ./redis-trib.rb:1701:in `<main>'
經檢查,這是由於上一次配置集群失敗時留下的配置信息導致的。 只要把redis.conf中定義的 cluster-config-file 所在的文件刪除,重新啟動redis-server及運行redis-trib即可。
3.7 建立集群Redis關系正常執行響應如下
>>> Creating cluster
>>> Performing hash slots allocation on 3 nodes... Using 3 masters: 192.168.29.128:6379 192.168.29.128:6380 192.168.29.128:6381 M: d5d0951bb185a67a44d29dd2142170dbce84d977 192.168.29.128:6379 slots:0-5460 (5461 slots) master M: e41fe58ef571836d891656b482307628b3f7ab35 192.168.29.128:6380 slots:5461-10922 (5462 slots) master M: ddbc810661f81500059e0b22b1550713a0e3766d 192.168.29.128:6381 slots:10923-16383 (5461 slots) master Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join... >>> Performing Cluster Check (using node 192.168.29.128:6379) M: d5d0951bb185a67a44d29dd2142170dbce84d977 192.168.29.128:6379 slots:0-5460 (5461 slots) master 0 additional replica(s) M: ddbc810661f81500059e0b22b1550713a0e3766d 192.168.29.128:6381 slots:10923-16383 (5461 slots) master 0 additional replica(s) M: e41fe58ef571836d891656b482307628b3f7ab35 192.168.29.128:6380 slots:5461-10922 (5462 slots) master 0 additional replica(s) [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. 成功
3.8 查看集群節點信息
3.9 測試
3.9.1 測試插入數據
因為abc的hash槽信息是在6380上,現在使用redis-cli連接的6379,無法完成set操作,需要客戶端跟蹤重定向。使用redis-cli -c
3.9.2 重新測試插入數據
4. 插槽的概念及插槽分配
整個Redis提供了16384個插槽,也就是說集群中的每個節點分得的插槽數總和為16384。./redis-trib.rb 腳本實現了是將16384個插槽平均分配給了N個節點。當我們執行set abc 123命令時,redis是如何將數據保存到集群中的呢?執行步驟:
i.接收命令set abc 123 ii.通過key(abc)計算出插槽值,然后根據插槽值找到對應的節點。abc的插槽值為:7638 iii.重定向到該節點執行命令
注意:如果插槽數有部分是沒有指定到節點的,那么這部分插槽所對應的key將不能使用。
5.新增集群節點
5.1 再開啟一個實例的端口為6382 配置同上
5.2 執行腳本建立6382節點與集群的關系
5.3 查看集群狀態,發現新增的節點沒有插槽
5.4 給6382節點分配插槽
5.5 查看集群節點狀態
6.刪除集群節點
想要刪除集群節點中的某一個節點,需要嚴格執行2步:
6.1.將這個節點上的所有插槽轉移到其他節點上
6.1.1執行腳本:./redis-trib.rb reshard 192.168.29.128:6382
6.1.2選擇需要轉移的插槽的數量,因為6382有100個,所以轉移100個
6.1.3輸入轉移的節點的id,我們轉移到6379節點
6.1.4輸入插槽來源id,也就是6382的id
6.1.5輸入done,開始轉移
6.1.6查看集群節點信息,可以看到6380節點已經沒有插槽了
6.2.刪除節點
6.2.1 刪除節點
6.2.2 查看集群節點信息
7. Redis Cluster高可用
7.1 假設集群中某一節點宕機 測試數據寫入操作
我們嘗試執行set命令,結果發現無法執,行集群不可用了?? 這集群也太弱了吧??
7.2 集群中的主從復制架構
7.3 本教程不詳細介紹集群中主從復制架構的具體安裝,只提一下過程
7.3.1 為每個集群節點添加Slave,形成主從復制架構,主從復制架構可參考:主從復制架構,搭建結構如下所示
6379(Master) 6479(Slave of 6379) 6579(Slave of 6379) 6380(Master) 6480(Slave of 6380) 6580(Slave of 6380) 6381(Master) 6481(Slave of 6381) 6581(Slave of 6381)
7.3.2 為每個主從復制架構添加哨兵集群,哨兵模式集群可參考:哨兵模式集群
7.3.3 創建集群 使用如下命令
./redis-trib.rb create --replicas 2 192.168.29.128:6379 192.168.29.128:6380 192.168.29.128:6381 192.168.29.128:6479 192.168.29.128:6480 192.168.29.128:6481 192.168.29.128:6579 192.168.29.128:6580 192.168.29.128:6581
7.4.4 自行測試高可用Cluster環境
注意在集群環境中:
多鍵的命令操作(如MGET、MSET),如果每個鍵都位於同一個節點,則可以正常支持,否則會提示錯誤。
集群中的節點只能使用0號數據庫,如果執行SELECT切換數據庫會提示錯誤。
Redis主從復制和集群配置
redis主從復制
概述
1、redis的復制功能是支持多個數據庫之間的數據同步。一類是主數據庫(master)一類是從數據庫(slave),主數據庫可以進行讀寫操作,當發生寫操作的時候自動將數據同步到從數據庫,而從數據庫一般是只讀的,並接收主數據庫同步過來的數據,一個主數據庫可以有多個從數據庫,而一個從數據庫只能有一個主數據庫。
2、通過redis的復制功能可以很好的實現數據庫的讀寫分離,提高服務器的負載能力。主數據庫主要進行寫操作,而從數據庫負責讀操作。
主從復制過程
主從復制過程:見下圖
過程:
1:當一個從數據庫啟動時,會向主數據庫發送sync命令,
2:主數據庫接收到sync命令后會開始在后台保存快照(執行rdb操作),並將保存期間接收到的命令緩存起來
3:當快照完成后,redis會將快照文件和所有緩存的命令發送給從數據庫。
4:從數據庫收到后,會載入快照文件並執行收到的緩存的命令。
注意:redis2.8之前的版本:當主從數據庫同步的時候從數據庫因為網絡原因斷開重連后會重新執行上述操作,不支持斷點續傳。
redis2.8之后支持斷點續傳。
配置
Redis主從結構支持一主多從
主節點:192.168.33.130
從節點:192.168.33.131
注意:所有從節點的配置都一樣
方式1:手動修改配置文件
只需要額外修改從節點中redis的配置文件中的slaveof屬性即可
- slaveof 192.168.33.130 6379
配置修改圖示:
配置效果圖示:
1、192.168.33.130主機:啟動130主節點上面的redis,查看redis的info信息
2、192.168.33.131主機:啟動131從節點上面的redis,查看redis的info信息
方式2:動態設置
通過redis-cli 連接到從節點服務器,執行下面命令即可。
slaveof 192.168.33.130 6379
演示結果和手動方式一致。
注意事項
如果你使用主從復制,那么要確保你的master激活了持久化,或者確保它不會在當掉后自動重啟。原因:
slave是master的完整備份,因此如果master通過一個空數據集重啟,slave也會被清掉。
在配置redis復制功能的時候如果主數據庫設置了密碼,需要在從數據的配置文件中通過masterauth參數設置主數據庫的密碼,這樣從數據庫在連接主數據庫時就會自動使用auth命令認證了。相當於做了一個免密碼登錄。
redis的Sentinel
sentinel功能
redis的sentinel系統用於管理多個redis服務器,該系統主要執行三個任務:監控、提醒、自動故障轉移。
1、監控(Monitoring): Redis Sentinel實時監控主服務器和從服務器運行狀態,並且實現自動切換。
2、提醒(Notification):當被監控的某個 Redis 服務器出現問題時, Redis Sentinel 可以向系統管理員發送通知, 也可以通過 API 向其他程序發送通知。
3、自動故障轉移(Automatic failover): 當一個主服務器不能正常工作時,Redis Sentinel 可以將一個從服務器升級為主服務器, 並對其他從服務器進行配置,讓它們使用新的主服務器。當應用程序連接Redis 服務器時, Redis Sentinel會告之新的主服務器地址和端口。
注意:在使用sentinel監控主從節點的時候,從節點需要是使用動態方式配置的,如果直接修改配置文件,后期sentinel實現故障轉移的時候會出問題。
圖示sentinel
主觀下線和客觀下線:
1、主觀下線狀態:當一個sentinel認為一個redis服務連接不上的時候,會給這個服務打個標記為下線狀態。
2、客觀下線狀態:當多個sentinel認為一個redids連接不上的時候,則認為這個redis服務確實下線了。這里的多個sentinel的個數可以在配置文件中設置。
主節點:主觀下線和客觀下線
從節點:主觀下線狀態
sentinel配置
修改sentinel.conf文件
- sentinel monitor mymaster 192.168.33.130 6379 2 #最后一個參數視情況決定
最后一個參數為需要判定客觀下線所需的主觀下線sentinel個數,這個參數不可以大於sentinel個數。
啟動sentinel
- redis-sentinel sentinel.conf
啟動后結果圖示:
sentinel日志明細說明
http://redisdoc.com/topic/sentinel.html
通過訂閱指定的頻道信息,當服務器出現故障得時候通知管理員
客戶端可以將 Sentinel 看作是一個只提供了訂閱功能的 Redis 服務器,你不可以使用 PUBLISH 命令向這個服務器發送信息,但你可以用 SUBSCRIBE 命令或者 PSUBSCRIBE 命令, 通過訂閱給定的頻道來獲取相應的事件提醒。
一個頻道能夠接收和這個頻道的名字相同的事件。 比如說, 名為 +sdown 的頻道就可以接收所有實例進入主觀下線(SDOWN)狀態的事件。
sentinel的一些命令
- INFO
sentinel的基本狀態信息
- SENTINEL masters
列出所有被監視的主服務器,以及這些主服務器的當前狀態
- SENTINEL slaves <master name>
列出給定主服務器的所有從服務器,以及這些從服務器的當前狀態
- SENTINEL get-master-addr-by-name <master name>
返回給定名字的主服務器的 IP 地址和端口號
- SENTINEL reset <pattern>
重置所有名字和給定模式 pattern 相匹配的主服務器。重置操作清除主服務器目前的所有狀態, 包括正在執行中的故障轉移, 並移除目前已經發現和關聯的, 主服務器的所有從服務器和 Sentinel 。
- SENTINEL failover <master name>
當主服務器失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移,但是它會給其他sentinel發送一個最新的配置,其他sentinel會根據這個配置進行更新
java操作sentinel
代碼示例:
- import java.util.HashSet;
- //需要在pom.xml文件中引入jedis依賴
- import redis.clients.jedis.HostAndPort;
- import redis.clients.jedis.Jedis;
- import redis.clients.jedis.JedisPoolConfig;
- import redis.clients.jedis.JedisSentinelPool;
- public class SentinelTest {
- public static void main(String[] args) {
- // 使用HashSet添加多個sentinel
- HashSet<String> sentinels = new HashSet<String>();
- // 添加sentinel主機和端口
- sentinels.add("192.168.33.131:26379");
- // 創建config
- JedisPoolConfig poolConfig = new JedisPoolConfig();
- // 控制一個pool最多有多少個狀態為idle(空閑的)的jedis實例。
- poolConfig.setMaxIdle(10);
- // 控制一個pool最多有多少個jedis實例。
- poolConfig.setMaxTotal(100);
- // 表示當borrow(引入)一個jedis實例時,最大的等待時間,如果超過等待時間,則直接拋出JedisConnectionException;
- poolConfig.setMaxWaitMillis(2000);
- // 在borrow一個jedis實例時,是否提前進行validate操作;如果為true,則得到的jedis實例均是可用的;
- poolConfig.setTestOnBorrow(true);
- // 通過Jedis連接池創建一個Sentinel連接池
- JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,poolConfig);
- // 獲取master的主機和端口
- HostAndPort currentHostMaster = pool.getCurrentHostMaster();
- System.out.println(currentHostMaster.getHost() + "--"+ currentHostMaster.getPort());
- // 從Sentinel池中獲取資源
- Jedis resource = pool.getResource();
- // 打印資源中key為name的值
- System.out.println(resource.get("name"));
- // 關閉資源
- resource.close();
- }
- }
打印結果:
redis集群
簡介
redis集群是一個無中心的分布式Redis存儲架構,可以在多個節點之間進行數據共享,解決了Redis高可用、可擴展等問題。redis集群提供了以下兩個好處
1、將數據自動切分(split)到多個節點
2、當集群中的某一個節點故障時,redis還可以繼續處理客戶端的請求。
一個 Redis 集群包含 16384 個哈希槽(hash slot),數據庫中的每個數據都屬於這16384個哈希槽中的一個。集群使用公式 CRC16(key) % 16384 來計算鍵 key 屬於哪個槽。集群中的每一個節點負責處理一部分哈希槽。
集群中的主從復制
集群中的每個節點都有1個至N個復制品,其中一個為主節點,其余的為從節點,如果主節點下線了,集群就會把這個主節點的一個從節點設置為新的主節點,繼續工作。這樣集群就不會因為一個主節點的下線而無法正常工作。
注意:
1、如果某一個主節點和他所有的從節點都下線的話,redis集群就會停止工作了。redis集群不保證數據的強一致性,在特定的情況下,redis集群會丟失已經被執行過的寫命令
2、使用異步復制(asynchronous replication)是 Redis 集群可能會丟失寫命令的其中一個原因,有時候由於網絡原因,如果網絡斷開時間太長,redis集群就會啟用新的主節點,之前發給主節點的數據就會丟失。
安裝配置
修改配置文件redis.conf
- daemonize yes
- port 6379
- cluster-enabled yes
- cluster-config-file nodes.conf
- cluster-node-timeout 5000
要讓集群正常運作至少需要三個主節點
我們這里就簡單在一台主機上創建6個redis節點來演示集群配置,實際生產環境中需要每個節點一台主機。
我們要創建的6個redis節點,其中三個為主節點,三個為從節點,對應的redis節點的ip和端口對應關系如下:
- 192.168.33.130:7000
- 192.168.33.130:7001
- 192.168.33.130:7002
- 192.168.33.130:7003
- 192.168.33.130:7004
- 192.168.33.130:7005
1、首先我們創建6個以端口為名稱的文件夾(由於每個redis節點啟動的時候,都會在當前文件夾下創建快照文件,所以我們需要創建每個節點的啟動目錄)
- mkdir 7000
- mkdir 7001
- mkdir 7002
- mkdir 7003
- mkdir 7004
- mkdir 7005
2、接下來把每個節點啟動所需要的配置文件拷貝到相應的啟動目錄:
- cp redis.conf 7000
- cp redis.conf 7001
- cp redis.conf 7002
- cp redis.conf 7003
- cp redis.conf 7004
- cp redis.conf 7005
3、然后我們進入每個啟動目錄,修改之前拷貝的redis.conf文件中的端口port 為上面列出的對應端口。
最終每個節點的配置類似於:
- daemonize yes
- port 6379 #只有端口不同,其他相同
- cluster-enabled yes
- cluster-config-file nodes.conf
- cluster-node-timeout 5000
4、進入每個啟動目錄,以每個目錄下的redis.conf文件啟動
使用命令查看redis節點是否啟動
- ps -ef | grep redis
5、創建集群命令
- redis-trib.rb create --replicas 1 192.168.33.130:7000 192.168.33.130:7001 192.168.33.130:7002 192.168.33.130:7003 192.168.33.130:7004 192.168.33.130:7005
注意:
5.1、執行上面的命令的時候可能會報錯,因為是執行的ruby的腳本,需要ruby的環境
錯誤內容:
所以我們需要安裝ruby的環境,這里推薦使用yum安裝:
- yum install ruby
5.2、安裝ruby后,執行命令可能還會報錯,提示缺少rubygems組件,使用yum安裝
解決方法:
- yum install rubygems
5.3、上面兩個步驟后,執行創建集群目錄可能還會報錯,提示不能加載redis,是因為缺少redis和ruby的接口,使用gem 安裝。
解決方法:
- gem install redis
上面三個問題解決后,啟動創建集群應該可以正常啟動了:
這里輸入yes
最后結果:
到此,我們的集群搭建成功了。
6、接下來我們使用命令進入集群環境
- redis-cli -c -p 7000
redis集群操作
使用redis-cli客戶端來操作redis集群,使用命令 :
- redis-cli -c -p [port]
查看集群中的所有主節點信息
- redis-cli -c -p 7000 cluster nodes [| grep master]
redis集群添加節點
根據添加節點類型的不同,有兩種方法來添加新節點
1、主節點:如果添加的是主節點,那么我們需要創建一個空節點,然后將某些哈希槽移動到這個空節點里面
2、從節點:如果添加的是從節點,我們也需要創建一個空節點,然后把這個新節點設置成集群中某個主節點的復制品。
添加節點:
1、首先把需要添加的節點啟動
創建7006目錄,拷貝7000中的redis.conf到7006中,然后修改端口port為7006,修改好后進入7006目錄啟動這個節點:
- redis-server redis.conf
2、執行以下命令,將這個新節點添加到集群中:
- redis-trib.rb add-node 192.168.33.130:7006 192.168.33.130:7000
結果圖示:
3、執行命令查看剛才新增的節點:
- redis-cli -c -p 7000 cluster nodes
4、增加了新的節點之后,這個新的節點可以成為主節點或者是從節點
4.1將這個新增節點變成從節點
前面我們已經把這個新節點添加到集群中了,現在我們要讓新節點成為192.168.33.130:7001的從節點,只需要執行下面的命令就可以了,命令后面的節點ID就是192.168.33.130:7001的節點ID。(注意,這個從節點哈希槽必須為空,如果不為空,則需要轉移掉哈希槽使之為空)
- redis-cli -c -p 7006 cluster replicate a246963893faf03c45cc19ef4188f82f5393bfef
使用下面命令來確認一下192.168.33.130:7006是否已經成為192.168.33.130:7001的從節點。
- redis-cli -p 7000 cluster nodes | grep slave | grep a246963893faf03c45cc19ef4188f82f5393bfef
4.2、將這個新增節點變成主節點:
使用redis-trib程序,將集群中的某些哈希槽移動到新節點里面,這個新節點就成為真正的主節點了。執行下面的命令對集群中的哈希槽進行移動:
- redis-trib.rb reshard 192.168.33.130:7000
命令執行后,系統會提示我們要移動多少哈希槽,這里移動1000個
然后還需要指定把這些哈希槽轉移到哪個節點上
輸入我們剛才新增的節點的ID
d113e0f033c98e2f6b88fb93e6e98866256d85c4
然后需要我們指定轉移哪幾個幾點的哈希槽
輸入all 表示從所有的主節點中隨機轉移,湊夠1000個哈希槽
然后再輸入yes,redis集群就開始分配哈希槽了。
至此,一個新的主節點就添加完成了,執行命令查看現在的集群中節點的狀態
- redis-cli -c -p 7000 cluster nodes
結果圖示:
Redis集群刪除節點
1、如果刪除的節點是主節點,這里我們刪除192.168.33.130:7006節點,這個節點有1000個哈希槽
首先要把節點中的哈希槽轉移到其他節點中,執行下面的命令:
- redis-trib.rb reshard 192.168.33.130:7000
系統會提示我們要移動多少哈希槽,這里移動1000個,因為192.168.33.130:7006節點有1000個哈希槽。
然后系統提示我們輸入要接收這些哈希槽的節點的ID,這里使用192.168.33.130:7001的節點ID
然后要我們選擇從那些節點中轉出哈希槽,這里一定要輸入192.168.33.130:7006這個節點的ID
最后輸入done表示輸入完畢。
最后一步,使用下面的命令把這個節點刪除
- redis-trib.rb del-node 192.168.33.130:7000 d113e0f033c98e2f6b88fb93e6e98866256d85c4 //最后一個參數為需要刪除的節點ID
2、如果是從節點,直接刪除即可。
- redis-trib.rb del-node 192.168.33.130:7000 d113e0f033c98e2f6b88fb93e6e98866256d85c4 //最后一個參數為需要刪除節點的ID
java操作redis集群
向Redis集群中存入鍵值:
代碼示例:
- import java.util.HashSet;
- //需要再pom.xml中引入jedis依賴
- import redis.clients.jedis.HostAndPort;
- import redis.clients.jedis.JedisCluster;
- import redis.clients.jedis.JedisPool;
- import redis.clients.jedis.JedisPoolConfig;
- public class RedisCluster {
- public static void main(String[] args) {
- //初始化集合,用於裝下面的多個主機和端口
- HashSet<HostAndPort> nodes = new HashSet<HostAndPort>();
- //創建多個主機和端口實例
- HostAndPort hostAndPort = new HostAndPort("192.168.33.130", 7000);
- HostAndPort hostAndPort1 = new HostAndPort("192.168.33.130", 7001);
- HostAndPort hostAndPort2 = new HostAndPort("192.168.33.130", 7002);
- HostAndPort hostAndPort3 = new HostAndPort("192.168.33.130", 7003);
- HostAndPort hostAndPort4 = new HostAndPort("192.168.33.130", 7004);
- HostAndPort hostAndPort5 = new HostAndPort("192.168.33.130", 7005);
- //添加多個主機和端口到集合中
- nodes.add(hostAndPort);
- nodes.add(hostAndPort1);
- nodes.add(hostAndPort2);
- nodes.add(hostAndPort3);
- nodes.add(hostAndPort4);
- nodes.add(hostAndPort5);
- //創建config
- JedisPoolConfig poolConfig = new JedisPoolConfig();
- //通過config創建集群實例
- JedisCluster jedisCluster = new JedisCluster(nodes,poolConfig);
- //獲取集群中的key為name鍵的值
- String str = jedisCluster.get("name");
- System.out.println(str);
- }
- }
打印結果: