前言
前些天一直在忙線上環境部署的事情,初步想的是,nginx(keepalive雙機熱備)+3(tomcat)+2redis(雙機熱備),但是後來由於阿里雲伺服器傳統網路不提供虛擬IP,無法使用keepalive,nginx雙機熱備只能暫時先放棄,退而求其次,採用nginx+3tomcat+2redis(雙機熱備)。nginx+tomcat由於之前配置過,所以重點就落在redis雙機熱備上,畢竟是線上系統,適當的抗災能力還是需要的,咱可不能像測試系統那麼去玩,否則黑鍋就有的背了,畢竟碼代碼賺點生活費也不容易。
在網上也查了一些資料,redis叢集實現大概有以下幾種方式:
1.redis-cluster,官方提供的叢集搭建方案(過於重量級,比較適合後期資料量較大的時候的使用)
2.redis+keepalive(由於我們使用的阿里雲伺服器不支援虛擬IP,所以這套方案也就夭折了)
3.redis+zookeeper(需要引入zookeeper,對現有代碼變動較大)
4.redis+sentinel(redis內建監控中介軟體)(代碼變動小,配置少,而且能滿足雙機熱備的需求)
基於我們目前的情況以及需求,經過初略對比,我們團隊決定選用第四種方案redis+sentinel實現雙機熱備。 準備工作 1.安裝redis-001(主)
$ wget http://download.redis.io/releases/redis-3.2.3.tar.gz$ tar xzf redis-3.2.3.tar.gz$ mv redis-3.2.3 redis-001$ cd redis-001$ make
2.安裝redis-002(從)
$ wget http://download.redis.io/releases/redis-3.2.3.tar.gz$ tar xzf redis-3.2.3.tar.gz$ mv redis-3.2.3 redis-002$ cd redis-002$ make
3.修改redis-002連接埠為6380
$ cd /usr/tools/redis-002/$ vim redis.conf...找到port 6379改為6380...
4.修改redis預設配置
a.關閉ip綁定,注釋redis.conf中bind 127.0.0.1
b.關閉保護模式,將protected-mode yes改為protected-mode no 5.啟動redis-001,redis-002
$ cd tools/redis-001/$ ./src/redis-server redis.conf
出現以下資訊就表示啟動成功了:
12513:M 09 Oct 11:15:49.061 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.12513:M 09 Oct 11:15:49.061 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.12513:M 09 Oct 11:15:49.061 * DB loaded from disk: 0.000 seconds12513:M 09 Oct 11:15:49.061 * The server is now ready to accept connections on port 6379
redis主從複製 1.redis 複製的特點
1). 同一個Master可以同步多個Slaves。
2). Slave同樣可以接受其它Slaves的串連和同步請求,這樣可以有效分載Master的同步壓力。因此我們可以將Redis的Replication架構視為圖結構。
3). Master Server是以非阻塞的方式為Slaves提供服務。所以在Master-Slave同步期間,用戶端仍然可以提交查詢或修改請求。
4). Slave Server同樣是以非阻塞的方式完成資料同步。在同步期間,如果有用戶端提交查詢請求,Redis則返回同步之前的資料。
5). 為了分載Master的讀操作壓力,Slave伺服器可以為用戶端提供唯讀操作的服務,寫服務仍然必須由Master來完成。即便如此,系統的伸縮性還是得到了很大的提高。
6). Master可以將資料儲存操作交給Slaves完成,從而避免了在Master中要有獨立的進程來完成此操作。 2.redis複製原理
在Slave啟動並串連到Master之後,它將主動發送一個SYNC命令。此後Master將啟動後台存檔進程,同時收集所有接收到的用於修改資料集的命令,在後台進程執行完畢後,Master將傳送整個資料庫檔案到Slave,以完成一次完全同步。而Slave伺服器在接收到資料庫檔案資料之後將其存檔並載入到記憶體中。此後,Master繼續將所有已經收集到的修改命令,和新的修改命令依次傳送給Slaves,Slave將在本次執行這些資料修改命令,從而達到最終的資料同步。
如果Master和Slave之間的連結出現斷連現象,Slave可以自動重連Master,但是在串連成功之後,一次完全同步將被自動執行。 3.redis主從配置
前面也說了,redis主從配置很簡單,只需要一個slaveof就可以搞定。
串連redis-002,執行slaveof 192.168.231.130 6379:
C:\Users\lenovo\Desktop\redis>D:D:\>cd D:\Program Files\Redis-x64-3.0.5D:\Program Files\Redis-x64-3.0.5>redis-cli.exe -h 192.168.231.130 -p 6380192.168.231.130:6380> slaveof 192.168.231.130 6379OK192.168.231.130:6380>
執行完成後,可以看到伺服器上redis-001控制台輸出以下內容:
12513:M 09 Oct 11:15:49.061 * DB loaded from disk: 0.000 seconds12513:M 09 Oct 11:15:49.061 * The server is now ready to accept connections on port 637912513:M 09 Oct 11:41:59.371 * Slave 192.168.231.130:6380 asks for synchronization12513:M 09 Oct 11:41:59.371 * Full resync requested by slave 192.168.231.130:638012513:M 09 Oct 11:41:59.371 * Starting BGSAVE for SYNC with target: disk12513:M 09 Oct 11:41:59.372 * Background saving started by pid 1367313673:C 09 Oct 11:41:59.388 * DB saved on disk13673:C 09 Oct 11:41:59.388 * RDB: 6 MB of memory used by copy-on-write12513:M 09 Oct 11:41:59.462 * Background saving terminated with success12513:M 09 Oct 11:41:59.462 * Synchronization with slave 192.168.231.130:6380 succeeded
redis-002控制台輸出:
13581:S 09 Oct 11:41:59.361 * Connecting to MASTER 192.168.231.130:637913581:S 09 Oct 11:41:59.370 * MASTER <-> SLAVE sync started13581:S 09 Oct 11:41:59.370 * Non blocking connect for SYNC fired the event.13581:S 09 Oct 11:41:59.371 * Master replied to PING, replication can continue...13581:S 09 Oct 11:41:59.371 * Partial resynchronization not possible (no cached master)13581:S 09 Oct 11:41:59.374 * Full resync from master: e2f4e2608956ea6392482c2e0a9429efdebd2b53:113581:S 09 Oct 11:41:59.462 * MASTER <-> SLAVE sync: receiving 76 bytes from master13581:S 09 Oct 11:41:59.463 * MASTER <-> SLAVE sync: Flushing old data13581:S 09 Oct 11:41:59.463 * MASTER <-> SLAVE sync: Loading DB in memory13581:S 09 Oct 11:41:59.463 * MASTER <-> SLAVE sync: Finished with success
但是這樣做的話,重啟redis-002後又會複原,所以通常我們會直接修改redis-002設定檔redis.conf,在末尾加上slaveof 192.168.231.130 6379部分,就永久有效了。
現在我們往redis-001中寫入資料,就可以從redis-002中查詢出來了,我們來測試一下,往redis-001中寫入key為name,value為osc的資料。
192.168.231.130:6379> set name oscOK192.168.231.130:6379> keys *1) "name"192.168.231.130:6379>
查詢redis-002中的資料,會發現同樣存在name的key,並且值為osc
192.168.231.130:6380> keys *1) "name"192.168.231.130:6380> get name"osc"192.168.231.130:6380>
到目前為止,redis主從複製已經配置成功了,接下來就要開始重點工作,配置雙機熱備。 redis+sentinel雙機熱備 1.理論概念
雙機熱備特指基於高可用系統中的兩台伺服器的熱備(或高可用),因兩機高可用在國內使用較多,故得名雙機熱備,雙機高可用按工作中的切換方式分為:主-備方式(Active-Standby方式)和雙主機方式(Active-Active方式),主-備方式即指的是一台伺服器處於某種業務的啟用狀態(即Active狀態),另一台伺服器處於該業務的備用狀態(即Standby狀態)。而雙主機方式即指兩種不同業務分別在兩台伺服器上互為主備狀態(即Active-Standby和Standby-Active狀態)。
大白話就是,當主伺服器掛了之後,從伺服器立馬切換為主伺服器繼續工作,當原先主伺服器修複完善啟動後,會自動充當從伺服器的角色繼續工作。這樣就很好的避免了,由於一台主機出現故障,系統掛點的現象出現。
Sentinel(哨兵)是用於監控redis叢集中Master狀態的工具,已經整合在redis官方版本中,可以直接配置使用。 2.Sentinel命令
PING :返回 PONG 。
SENTINEL masters :列出所有被監視的主伺服器,以及這些主伺服器的目前狀態;
SENTINEL slaves <master name> :列出給定主伺服器的所有從伺服器,以及這些從伺服器的目前狀態;
SENTINEL get-master-addr-by-name <master name> : 返回給定名字的主伺服器的 IP 位址和連接埠號碼。 如果這個主伺服器正在執行容錯移轉操作, 或者針對這個主伺服器的容錯移轉操作已經完成, 那麼這個命令返回新的主伺服器的 IP 位址和連接埠號碼;
SENTINEL reset <pattern> : 重設所有名字和給定模式 pattern 相匹配的主伺服器。 pattern 參數是一個 Glob 風格的模式。 重設操作清楚主伺服器目前的所有狀態, 包括正在執行中的容錯移轉, 並移除目前已經發現和關聯的, 主伺服器的所有從伺服器和 Sentinel ;
SENTINEL failover <master name> : 當主伺服器失效時, 在不詢問其他 Sentinel 意見的情況下, 強制開始一次自動故障遷移。
用戶端可以通過SENTINEL get-master-addr-by-name <master name>擷取當前的主伺服器IP地址和連接埠號碼,以及SENTINEL slaves <master name>擷取所有的Slaves資訊 3.雙機熱備配置
a.關閉redis-001與redis-002
b.在redis-001和redis-002配置sentinel.conf中加上以下配置資訊:
sentinel monitor mymaster 192.168.231.130 6379 1
c.修改redis-002 sentinel.conf監聽連接埠:
$ cd /usr/tools/redis-002/$ vim sentinel.conf...找到port 26379改為26380...port 26380
d.分別啟動redis-001(主)與redis-002(從),redis 服務和sentinel服務
$ cd /usr/tools/redis-002/$ ./src/redis-server redis.conf$ ./src/redis-sentinel sentinel.conf
$ cd /usr/tools/redis-001/$ ./src/redis-server redis.conf$ ./src/redis-sentinel sentinel.conf
此時在主從redis,sentinel控制台會出現以下資訊:
14677:X 09 Oct 14:04:49.633 # Sentinel ID is 7b8fdc1e5e47426b0d62a3ddd22ede0fd712f45214677:X 09 Oct 14:04:49.633 # +monitor master mymaster 192.168.231.130 6379 quorum 114677:X 09 Oct 14:04:49.634 * +slave slave 192.168.231.130:6380 192.168.231.130 6380 @ mymaster 192.168.231.130 637914677:X 09 Oct 14:05:53.727 * +sentinel sentinel 31e660153984b606951c564395bdc8e193943f0b 192.168.231.130 26380 @ mymaster 192.168.231.130 6379
e.測試結果:
串連主伺服器sentinel,注意連接埠是sentinel.conf中配置的連接埠。
根據前面描述的sentinel命令查詢主伺服器資訊:
192.168.231.130:26379> SENTINEL masters1) 1) "name" 2) "mymaster" 3) "ip" 4) "192.168.231.130" 5) "port" 6) "6379" 7) "runid" 8) "fafb94fe9bff119e8a97f9183e3bcb5561933631" 9) "flags" 10) "master" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent"