今天小編給大家分享一下redis高可用架構(gòu)如何搭建的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
成都一家集口碑和實(shí)力的網(wǎng)站建設(shè)服務(wù)商,擁有專業(yè)的企業(yè)建站團(tuán)隊(duì)和靠譜的建站技術(shù),十余年企業(yè)及個(gè)人網(wǎng)站建設(shè)經(jīng)驗(yàn) ,為成都上千家客戶提供網(wǎng)頁設(shè)計(jì)制作,網(wǎng)站開發(fā),企業(yè)網(wǎng)站制作建設(shè)等服務(wù),包括成都營(yíng)銷型網(wǎng)站建設(shè),品牌網(wǎng)站制作,同時(shí)也為不同行業(yè)的客戶提供網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)的服務(wù),包括成都電商型網(wǎng)站制作建設(shè),裝修行業(yè)網(wǎng)站制作建設(shè),傳統(tǒng)機(jī)械行業(yè)網(wǎng)站建設(shè),傳統(tǒng)農(nóng)業(yè)行業(yè)網(wǎng)站制作建設(shè)。在成都做網(wǎng)站,選網(wǎng)站制作建設(shè)服務(wù)商就選創(chuàng)新互聯(lián)建站。
在理解集群架構(gòu)前,先要介紹一下redis的持久化機(jī)制,因?yàn)樵诤竺娴募褐袝?huì)涉及到持久化。redis持久化是將緩存在內(nèi)存中的數(shù)據(jù)根據(jù)一些規(guī)則進(jìn)行落盤,以防止在redis服務(wù)宕機(jī)時(shí)可以進(jìn)行數(shù)據(jù)恢復(fù)或者是集群架構(gòu)中進(jìn)行主從節(jié)點(diǎn)數(shù)據(jù)同步。redis持久化的方式有RDB和AOF兩種,在4.0版本后新出了混合持久化模式。
RDB是redis默認(rèn)開啟的持久化機(jī)制,其持久化方式是按照用戶配置的規(guī)則"X秒內(nèi)至少發(fā)生過Y次改動(dòng)"
,生成快照并落盤到dump.rdb二進(jìn)制文件中。默認(rèn)情況下,redis配置了三種,分別為900秒內(nèi)至少發(fā)生過1次緩存key的改動(dòng),300秒內(nèi)至少發(fā)生過10次緩存key的改動(dòng)以及60秒內(nèi)至少發(fā)生過10000次改動(dòng)。
除了redis自動(dòng)快照持久化數(shù)據(jù)外,還有兩個(gè)命令可以幫助我們手動(dòng)進(jìn)行內(nèi)存數(shù)據(jù)快照,這兩個(gè)命令分別為save
和bgsave
。
save:以同步的方式進(jìn)行數(shù)據(jù)快照,當(dāng)緩存數(shù)據(jù)量大,會(huì)阻塞其他命令的執(zhí)行,效率不高。
bgsave:以異步的方式進(jìn)行數(shù)據(jù)快照,有redis主線程fork出一個(gè)子進(jìn)程來進(jìn)行數(shù)據(jù)快照,不會(huì)阻塞其他命令的執(zhí)行,效率較高。由于是采用異步快照的方式,那么就有可能發(fā)生在快照的過程中,有其他命令對(duì)數(shù)據(jù)進(jìn)行了修改。為了避免這個(gè)問題reids采用了寫時(shí)復(fù)制(Cpoy-On-Write)的方式,因?yàn)榇藭r(shí)進(jìn)行快照的進(jìn)程是由主線程fork出來的,所以享有主線程的資源,當(dāng)快照過程中發(fā)生數(shù)據(jù)改動(dòng)時(shí),那么該數(shù)據(jù)會(huì)被復(fù)制一份并生成副本數(shù)據(jù),子進(jìn)程會(huì)將改副本數(shù)據(jù)寫入到dump.rdb文件中。
RDB快照是以二進(jìn)制的方式進(jìn)行存儲(chǔ)的,所以在數(shù)據(jù)恢復(fù)時(shí),速度會(huì)比較快,但是它存在數(shù)據(jù)丟失的風(fēng)險(xiǎn)。假如設(shè)置的快照規(guī)則為60秒內(nèi)至少發(fā)生100次數(shù)據(jù)改動(dòng),那么在50秒時(shí),redis服務(wù)由于某種原因突然宕機(jī)了,那在這50秒內(nèi)的所有數(shù)據(jù)將會(huì)丟失。
AOF是Redis的另一種持久化方式,與RDB不同時(shí)是,AOF記錄著每一條更改數(shù)據(jù)的命令并保存到磁盤下的appendonly.aof文件中,當(dāng)redis服務(wù)重啟時(shí),會(huì)加載該文將并再次執(zhí)行文件中保存的命令,從而達(dá)到數(shù)據(jù)恢復(fù)的效果。默認(rèn)情況下,AOF是關(guān)閉的,可以通過修改conf配置文件來進(jìn)行開啟。
AOF提供了三種方式,可以讓命令保存到磁盤。默認(rèn)情況下,AOF采用 開啟AOF后需要重新啟動(dòng)redis服務(wù),當(dāng)再次執(zhí)行相關(guān)改寫命令時(shí),aof文件中會(huì)記錄操作的命令。 # appendonly no 關(guān)閉AOF持久化
appendonly yes # 開啟AOF持久化
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof" # 持久化文件名
appendfsync everysec
的方式進(jìn)行命令持久化。appendfsync always #每次有新的改寫命令時(shí),都會(huì)追加到磁盤的aof文件中。數(shù)據(jù)安全性最高,但效率最慢。
appendfsync everysec # 每一秒,都會(huì)將改寫命令追加到磁盤中的aof文件中。如果發(fā)生宕機(jī),也只會(huì)丟失1秒的數(shù)據(jù)。
appendfsync no #不會(huì)主動(dòng)進(jìn)行命令落盤,而是由操作系統(tǒng)決定什么時(shí)候?qū)懭氲酱疟P。數(shù)據(jù)安全性不高。
相對(duì)于RDB,雖然AOF的數(shù)據(jù)安全性更高,但是隨著服務(wù)的持續(xù)運(yùn)行,aof的文件也會(huì)越來越大,等到下次恢復(fù)數(shù)據(jù)時(shí),速度會(huì)越來越慢。如果RDB和AOF都開啟,在恢復(fù)數(shù)據(jù)時(shí),redis會(huì)優(yōu)先選擇AOF,畢竟AOF丟失的數(shù)據(jù)更少啊。
RDB | AOF | |
---|---|---|
恢復(fù)效率 | 高 | 低 |
數(shù)據(jù)安全性 | 低 | 高 |
空間占用 | 低 | 高 |
由于RDB持久化方式容易造成數(shù)據(jù)丟失,AOF持久化方式數(shù)據(jù)恢復(fù)較慢,所以在redis4.0版本后,新出來混合持久化模式。混合持久化將RDB和AOF的優(yōu)點(diǎn)進(jìn)行了集成,并而且依賴于AOF,所以在使用混合持久化前,需要開啟AOF。在開啟混合持久化后,當(dāng)發(fā)生AOF重寫時(shí),會(huì)將內(nèi)存中的數(shù)據(jù)以RDB的數(shù)據(jù)格式保存到aof文件中,在下一次的重寫之前,混合持久化會(huì)追加保存每條改寫命令到aof文件中。當(dāng)需要恢復(fù)數(shù)據(jù)時(shí),會(huì)加載保存的rdb內(nèi)容數(shù)據(jù),然后再繼續(xù)同步aof指令。
AOF重寫是指當(dāng)aof文件越來越大時(shí),redis會(huì)自動(dòng)優(yōu)化aof文件中無用的命令,從而減少文件體積。比如在處理文章閱讀量時(shí),每查看一次文章就會(huì)執(zhí)行一次Incr命令,但是隨著閱讀量的不斷增加,aof文件中的incr命令也會(huì)積累的越來越多。在AOF重寫后,將會(huì)刪除這些沒用的Incr命令,將這些命令直接替換為set key value命令。除了redis自動(dòng)重寫AOF,如果需要,也可以通過 # AOF重寫配置,當(dāng)aof文件達(dá)到60MB并且比上次重寫后的體量多100%時(shí)自動(dòng)觸發(fā)AOF重寫 auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-use-rdb-preamble yes # 開啟混合持久化# aof-use-rdb-preamble no # 關(guān)閉混合持久化
bgrewriteaof
命令手動(dòng)觸發(fā)。
在生產(chǎn)環(huán)境中,一般不會(huì)直接配置單節(jié)點(diǎn)的redis服務(wù),這樣壓力太大。為了緩解redis服務(wù)壓力,可以搭建主從復(fù)制,做讀寫分離。redis主從復(fù)制,是有一個(gè)主節(jié)點(diǎn)Master和多個(gè)從節(jié)點(diǎn)Slave組成。主從節(jié)點(diǎn)間的數(shù)據(jù)同步只能是單向傳輸?shù)?,只能由Master節(jié)點(diǎn)傳輸?shù)絊lave節(jié)點(diǎn)。
準(zhǔn)備三臺(tái)linux服務(wù)器,其中一臺(tái)作為redis的主節(jié)點(diǎn),兩臺(tái)作為reids的從節(jié)點(diǎn)。如果沒有足夠的機(jī)器可以在同一臺(tái)機(jī)器上面將redis文件多復(fù)制兩份并更改端口號(hào),這樣可以搭建一個(gè)偽集群。
IP | 主/從節(jié)點(diǎn) | 端口 | 版本 |
---|---|---|---|
192.168.36.128 | 主 | 6379 | 5.0.14 |
192.168.36.130 | 從 | 6379 | 5.0.14 |
192.168.36.131 | 從 | 6379 | 5.0.14 |
配置從節(jié)點(diǎn)36.130,36.131機(jī)器中reids.conf
修改redis.conf文件中的replicaof,配置主節(jié)點(diǎn)的ip和端口號(hào),并且開啟從節(jié)點(diǎn)只讀。
啟動(dòng)主節(jié)點(diǎn)36.128機(jī)器中reids服務(wù)
./src/redis-server redis.conf
3. 依次啟動(dòng)從節(jié)點(diǎn)36.130,36.131機(jī)器中的redis服務(wù)
./src/redis-server redis.conf
啟動(dòng)成功后可以看到日志中顯示已經(jīng)與Master節(jié)點(diǎn)建立的連接。如果出現(xiàn)與Master節(jié)點(diǎn)的連接被拒,那么先檢查Master節(jié)點(diǎn)的服務(wù)器是否開啟防火墻,如果開啟,可以開放6379端口或者關(guān)閉防火墻。如果防火墻被關(guān)閉但連接仍然被拒,那么可以修改Master節(jié)點(diǎn)服務(wù)中的redis.conf文件。將bing 127.0.0.1修改為本機(jī)對(duì)外的網(wǎng)卡ip或者直接注釋掉即可,然后重啟服務(wù)器即可。
查看狀態(tài)
全部節(jié)點(diǎn)啟動(dòng)成功后,Master節(jié)點(diǎn)可以查看從節(jié)點(diǎn)的連接狀態(tài),offset偏移量等信息。
info replication # 主節(jié)點(diǎn)查看連接信息
全量數(shù)據(jù)同步主從節(jié)點(diǎn)之間的數(shù)據(jù)同步是通過建立socket長(zhǎng)連接來進(jìn)行傳輸?shù)?。?dāng)Slave節(jié)點(diǎn)啟動(dòng)時(shí),會(huì)與Master節(jié)點(diǎn)建立長(zhǎng)連接,并且發(fā)送psync同步數(shù)據(jù)命令。當(dāng)Master節(jié)點(diǎn)收到psync命令時(shí),會(huì)執(zhí)行pgsave進(jìn)行rdb內(nèi)存數(shù)據(jù)快照(這里的rdb快照與conf文件中是否開啟rdb無關(guān)),如果在快照過程中有新的改寫命令,那么Master節(jié)點(diǎn)會(huì)將這些命令保存到repl buffer緩沖區(qū)中。當(dāng)快照結(jié)束后,會(huì)將rdb傳輸給Slave節(jié)點(diǎn)。Slave節(jié)點(diǎn)在接收到rdb后,如果存在舊數(shù)據(jù),那么會(huì)將這些舊數(shù)據(jù)清除并加載rdb。加載完成后會(huì)接受master緩存在repl buffer中的新命令。在這些步驟全部執(zhí)行完成后,主從節(jié)點(diǎn)已經(jīng)算連接成功了,后續(xù)Master節(jié)點(diǎn)的命令會(huì)不斷的發(fā)送到Slave節(jié)點(diǎn)。如果在高并發(fā)的情況下,可能會(huì)存在數(shù)據(jù)延遲的情況。
部分?jǐn)?shù)據(jù)同步
部分?jǐn)?shù)據(jù)同步發(fā)生在Slave節(jié)點(diǎn)發(fā)生宕機(jī),并且在短時(shí)間內(nèi)進(jìn)行了服務(wù)恢復(fù)。短時(shí)間內(nèi)主從節(jié)點(diǎn)之間的數(shù)據(jù)差額不會(huì)太大,如果執(zhí)行全量數(shù)據(jù)同步將會(huì)比較耗時(shí)。部分?jǐn)?shù)據(jù)同步時(shí),Slave會(huì)向Master節(jié)點(diǎn)建立socket長(zhǎng)連接并發(fā)送帶有一個(gè)offset偏移量的數(shù)據(jù)同步請(qǐng)求,這個(gè)offset可以理解數(shù)據(jù)同步的位置。Master節(jié)點(diǎn)在收到數(shù)據(jù)同步請(qǐng)求后,會(huì)根據(jù)offset結(jié)合buffer緩沖區(qū)內(nèi)新的改寫命令進(jìn)行位置確定。如果確定了offset的位置,那么就會(huì)將這個(gè)位置往后的所有改寫命令發(fā)送到Slave節(jié)點(diǎn)。如果沒有確定offset的位置,那么會(huì)再次執(zhí)行全量數(shù)據(jù)同步。比如,在Slave節(jié)點(diǎn)沒有宕機(jī)之前命令已經(jīng)同步到了offset=11這個(gè)位置,當(dāng)該節(jié)點(diǎn)重啟后,向Master節(jié)點(diǎn)發(fā)送該offset,Master根據(jù)offset在緩沖區(qū)中進(jìn)行定位,在定位到11這個(gè)位置后,將該位置往后的所有命令發(fā)送給Slave。在數(shù)據(jù)同步完成后,后續(xù)Master節(jié)點(diǎn)的命令會(huì)不斷的發(fā)送到該Slave節(jié)點(diǎn)
優(yōu)點(diǎn)
可以實(shí)現(xiàn)一主多從,讀寫分離,減輕Master節(jié)點(diǎn)讀操作壓力
是哨兵,集群架構(gòu)的基礎(chǔ)
缺點(diǎn)
不具備自動(dòng)主從切換功能,當(dāng)Master節(jié)點(diǎn)宕機(jī)后,需要手動(dòng)切換主節(jié)點(diǎn)
容易出現(xiàn)數(shù)據(jù)不一致,當(dāng)Master節(jié)點(diǎn)宕機(jī)前,如果有數(shù)據(jù)未同步,則會(huì)造成數(shù)據(jù)丟失
哨兵模式對(duì)主從復(fù)制進(jìn)行了進(jìn)一步優(yōu)化,獨(dú)立出單獨(dú)的哨兵進(jìn)程用于監(jiān)控主從架構(gòu)中的服務(wù)器狀態(tài),一旦發(fā)生宕機(jī),哨兵會(huì)在短時(shí)間內(nèi)選舉出新的Master節(jié)點(diǎn)并進(jìn)行主從切換。不僅如此,在多哨兵的節(jié)點(diǎn)下,每個(gè)哨兵都會(huì)相互進(jìn)行監(jiān)控,監(jiān)控哨兵節(jié)點(diǎn)是否宕機(jī)。
IP | 主/從節(jié)點(diǎn) | 端口 | 哨兵端口 | 版本 |
---|---|---|---|---|
192.168.36.128 | 主 | 6379 | 26379 | 5.0.14 |
192.168.36.130 | 從 | 6379 | 26379 | 5.0.14 |
192.168.36.131 | 從 | 6379 | 26379 | 5.0.14 |
主從復(fù)制是哨兵模式的基礎(chǔ),所以在搭建哨兵前需要完成主從復(fù)制的配置。在搭建完主從后,哨兵的搭建就容易很多。
找到安裝目錄下的sentinel.conf
文件并進(jìn)行修改。主要修改兩個(gè)地方,分別為哨兵端口port和監(jiān)控的主節(jié)點(diǎn)ip地址和端口號(hào)。
在配置完成后,可以使用命令啟動(dòng)各機(jī)器的哨兵服務(wù)。啟動(dòng)成功后,可查看redis服務(wù)和哨兵服務(wù)的進(jìn)行信息。
搭建成功后,就來通過代碼演示主節(jié)點(diǎn)宕機(jī)的情況下,哨兵是否會(huì)幫助系統(tǒng)自動(dòng)進(jìn)行主備切換。在springboot項(xiàng)目中引入對(duì)應(yīng)的pom,并配置對(duì)應(yīng)的redis哨兵信息。
當(dāng)啟動(dòng)服務(wù)后,通過節(jié)后向后端傳遞數(shù)據(jù),可以看到輸出的日志,表示redis哨兵集群已經(jīng)可以正常運(yùn)行了。那么這個(gè)時(shí)候kill掉36.128機(jī)器上的主節(jié)點(diǎn),模擬服務(wù)宕機(jī)。通過日志可以知道,服務(wù)出現(xiàn)異常了,在過十幾秒發(fā)現(xiàn)哨兵已經(jīng)自動(dòng)幫系統(tǒng)進(jìn)行了主從切換,并且服務(wù)也可以正常訪問了。server:
port: 8081spring:
redis:
sentinel:
master: mymaster # 主服務(wù)節(jié)點(diǎn)
nodes: 192.168.36.128:26379,192.168.36.130:26379,192.168.36.131:26379 #哨兵節(jié)點(diǎn)
timeout: 3000 #連接超時(shí)時(shí)間
@Slf4j
@RestController
public class RedisTest {
@Resource
private StringRedisTemplate stringRedisTemplate;
/*
* 每秒鐘向redis中寫入數(shù)據(jù),中途kill掉主節(jié)點(diǎn)進(jìn)程,模擬宕機(jī)
*/
@GetMapping("/redis/testSet")
public void test(@RequestParam(name = "key") String key,
@RequestParam(name = "value") String value) throws InterruptedException {
int idx=0;
for(;;){
try {
idx++;
stringRedisTemplate.opsForValue().set(key+idx, value);
log.info("=====存儲(chǔ)成功:{},{}=====",key+idx,value);
}catch (Exception e){
log.error("====連接redis服務(wù)器失敗:{}====",e.getMessage());
}
Thread.sleep(1000);
}
}
}
2022-11-14 22:20:23.134 INFO 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : =====存儲(chǔ)成功:test14,123=====
2022-11-14 22:20:24.142 INFO 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : =====存儲(chǔ)成功:test15,123=====
2022-11-14 22:20:24.844 INFO 8764 --- [xecutorLoop-1-1] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was /192.168.36.128:6379
2022-11-14 22:20:26.909 WARN 8764 --- [ioEventLoop-4-4] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect to [192.168.36.128:6379]: Connection refused: no further information: /192.168.36.128:6379
2022-11-14 22:20:28.165 ERROR 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : ====連接redis服務(wù)器失敗:Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 3 second(s)====
2022-11-14 22:20:31.199 INFO 8764 --- [xecutorLoop-1-1] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was 192.168.36.128:6379
2022-11-14 22:20:52.189 ERROR 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : ====連接redis服務(wù)器失敗:Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 3 second(s)====
2022-11-14 22:20:53.819 WARN 8764 --- [ioEventLoop-4-2] i.l.core.protocol.ConnectionWatchdog : Cannot reconnect to [192.168.36.128:6379]: Connection refused: no further information: /192.168.36.128:6379
2022-11-14 22:20:56.194 ERROR 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : ====連接redis服務(wù)器失敗:Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 3 second(s)====
2022-11-14 22:20:57.999 INFO 8764 --- [xecutorLoop-1-2] i.l.core.protocol.ConnectionWatchdog : Reconnecting, last destination was 192.168.36.128:6379
2022-11-14 22:20:58.032 INFO 8764 --- [ioEventLoop-4-4] i.l.core.protocol.ReconnectionHandler : Reconnected to 192.168.36.131:6379
2022-11-14 22:20:58.040 INFO 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : =====存儲(chǔ)成功:test24,123=====
2022-11-14 22:20:59.051 INFO 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : =====存儲(chǔ)成功:test25,123=====
2022-11-14 22:21:00.057 INFO 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : =====存儲(chǔ)成功:test26,123=====
2022-11-14 22:21:01.065 INFO 8764 --- [nio-8081-exec-2] com.gz.redis.RedisTest : =====存儲(chǔ)成功:test27,123=====
在多個(gè)哨兵的模式下,每個(gè)哨兵都會(huì)向redis節(jié)點(diǎn)發(fā)送心跳包來檢測(cè)節(jié)點(diǎn)的運(yùn)行狀態(tài)。如果某個(gè)哨兵發(fā)現(xiàn)主節(jié)點(diǎn)連接超時(shí)了,沒有收到心跳,那么系統(tǒng)并不會(huì)立刻進(jìn)行故障轉(zhuǎn)移,這種情況叫做主觀下線
。如果后續(xù)的哨兵節(jié)點(diǎn)發(fā)現(xiàn),與主節(jié)點(diǎn)的心跳也失敗了并且哨兵數(shù)量超過2個(gè),那么這個(gè)時(shí)候就會(huì)認(rèn)為主節(jié)點(diǎn)客觀下線
,并且會(huì)進(jìn)行故障轉(zhuǎn)移,這個(gè)客觀下線的數(shù)值可以在哨兵的配置文件中進(jìn)行配置。
登錄后復(fù)制sentinel monitor master 192.168.36.128 6378 2
在故障轉(zhuǎn)移前,需要選舉出一個(gè)哨兵leader來進(jìn)行Master節(jié)點(diǎn)的重新選舉。哨兵的選舉過程大致可以分為三步:
當(dāng)某個(gè)的哨兵確定主節(jié)點(diǎn)已經(jīng)下線時(shí),會(huì)像其他哨兵發(fā)送is-master-down-by-addr命令,要求將自己設(shè)為leader,并處理故障轉(zhuǎn)移工作。
其他哨兵在收到命令后,進(jìn)行投票選舉
如果票數(shù)過半時(shí),那么發(fā)送命令的哨兵節(jié)點(diǎn)將成為主節(jié)點(diǎn),并進(jìn)行故障轉(zhuǎn)移。
當(dāng)選舉出主哨兵后,那么這個(gè)主哨兵就會(huì)過濾掉宕機(jī)的redis節(jié)點(diǎn),重新選舉出Master節(jié)點(diǎn)。首先會(huì)根據(jù)redis節(jié)點(diǎn)的優(yōu)先級(jí)進(jìn)行選舉(slave-priority),數(shù)值越大的從節(jié)點(diǎn)將會(huì)被選舉為主節(jié)點(diǎn)。如果這個(gè)優(yōu)先級(jí)相同,那么主哨兵節(jié)點(diǎn)就會(huì)選擇數(shù)據(jù)最全的從節(jié)點(diǎn)作為新的主節(jié)點(diǎn)。如果還是選舉失敗,那么就會(huì)選舉出進(jìn)程id最小的從節(jié)點(diǎn)作為主節(jié)點(diǎn)。
在集群環(huán)境下會(huì)由于網(wǎng)絡(luò)等原因出現(xiàn)腦裂的情況,所謂的腦裂就是由于主節(jié)點(diǎn)和從節(jié)點(diǎn)和哨兵處于不同的網(wǎng)絡(luò)分區(qū),由于網(wǎng)絡(luò)波動(dòng)等原因,使得哨兵沒有能夠即使接收到主節(jié)點(diǎn)的心跳,所以通過選舉的方式選舉了一個(gè)從節(jié)點(diǎn)為新的主節(jié)點(diǎn),這樣就存在了兩個(gè)主節(jié)點(diǎn),就像一個(gè)人有兩個(gè)大腦一樣,這樣會(huì)導(dǎo)致客戶端還在像老的主節(jié)點(diǎn)那里寫入數(shù)據(jù),新節(jié)點(diǎn)無法同步數(shù)據(jù),當(dāng)網(wǎng)絡(luò)恢復(fù)后,哨兵會(huì)將老的主節(jié)點(diǎn)降為從節(jié)點(diǎn),這時(shí)再?gòu)男轮鞴?jié)點(diǎn)同步數(shù)據(jù),這會(huì)導(dǎo)致大量數(shù)據(jù)丟失。如果需要避免腦裂的問題,可以配置下面兩行信息。
min-replicas-to-write 3 # 最少?gòu)墓?jié)點(diǎn)為3
min-replicas-max-lag 10 # 表示數(shù)據(jù)復(fù)制和同步的延遲不能超過10秒
優(yōu)點(diǎn):除了擁有主從復(fù)制的優(yōu)點(diǎn)外,還可以進(jìn)行故障轉(zhuǎn)移,主從切換,系統(tǒng)更加可靠。
缺點(diǎn):故障轉(zhuǎn)移需要花費(fèi)一定的時(shí)間,在高并發(fā)場(chǎng)景下容易出現(xiàn)數(shù)據(jù)丟失。不容易實(shí)現(xiàn)在線擴(kuò)容。
哨兵模式中雖然在主節(jié)點(diǎn)宕機(jī)的情況下能夠做到主從切換,但是在切換的過程中需要花費(fèi)十幾秒或者更久的時(shí)間,會(huì)造成部分?jǐn)?shù)據(jù)的丟失。如果在并發(fā)量不高的情況下,可以使用該集群模式,但是在高并發(fā)的情況下,這十幾秒的時(shí)間可能會(huì)造成嚴(yán)重的后果,所以,在很多互聯(lián)網(wǎng)公司都是采用Cluster集群架構(gòu)。Cluster集群中由多個(gè)redis節(jié)點(diǎn)組成,每個(gè)redis服務(wù)節(jié)點(diǎn)都有一個(gè)Master節(jié)點(diǎn)和多個(gè)Slave節(jié)點(diǎn),在進(jìn)行數(shù)據(jù)存儲(chǔ)時(shí),redis會(huì)對(duì)數(shù)據(jù)的key進(jìn)行hash運(yùn)算并根據(jù)運(yùn)算結(jié)果分配到不同的槽位。一般情況下,Cluster集群架構(gòu)要設(shè)置6個(gè)節(jié)點(diǎn)(三主三從)。
由于只有三臺(tái)虛擬機(jī),所以需要在每臺(tái)服務(wù)器上面搭建兩個(gè)redis服務(wù),端口分別為6379和6380,這個(gè)剛好可以構(gòu)建6個(gè)節(jié)點(diǎn)。
IP | 主/從節(jié)點(diǎn) | 端口 | 版本 |
---|---|---|---|
192.168.36.128 | - | 6379 | 5.0.14 |
192.168.36.128 | - | 6380 | 5.0.14 |
192.168.36.130 | - | 6379 | 5.0.14 |
192.168.36.130 | - | 6380 | 5.0.14 |
192.168.36.131 | - | 6379 | 5.0.14 |
192.168.36.131 | - | 6380 | 5.0.14 |
為了看起來不是那么混亂,可以為cluster新建一個(gè)文件夾,并將redis的文件拷貝到cluster文件夾中,并修改文件夾名為redis-6379,reids-6380。
新建完成后,修改每個(gè)節(jié)點(diǎn)的redis.conf配置文件,找到cluster相關(guān)的配置位置,將cluster-enable更改為yes,表示開啟集群模式。開啟后,需要修改集群節(jié)點(diǎn)連接的超時(shí)時(shí)間cluster-node-timeout,節(jié)點(diǎn)配置文件名cluster-config-file等等,需要注意的是,同一臺(tái)機(jī)器上面的服務(wù)節(jié)點(diǎn)記得更改端口號(hào)。
在每個(gè)節(jié)點(diǎn)都配置完成后,可以依次啟動(dòng)各節(jié)點(diǎn)。啟動(dòng)成功后,可以查看redis的進(jìn)程信息,后面有明顯的標(biāo)識(shí)為[cluster]。
現(xiàn)在雖然每個(gè)節(jié)點(diǎn)的redis都已經(jīng)正常啟動(dòng)了,但是每個(gè)節(jié)點(diǎn)之間并沒有任何聯(lián)系啊。所以這個(gè)時(shí)候還需要最后一步,將各節(jié)點(diǎn)建立關(guān)系。在任意一臺(tái)機(jī)器上運(yùn)行下面的命令-- cluster create ip:port,進(jìn)行集群創(chuàng)建。命令執(zhí)行成功后,可以看到槽位的分布情況和主從關(guān)系。
./src/redis-cli --cluster create 192.168.36.128:6379 192.168.36.128:6380 192.168.36.130:6379 192.168.36.130:6380 192.168.36.131:6379 192.168.36.131:6380 --cluster-replicas 1復(fù)制代碼
cluster成功啟動(dòng)后,可以在代碼中簡(jiǎn)單的測(cè)試一下,這里的代碼依舊采用哨兵模式中的測(cè)試代碼,只是將sentinel相關(guān)的信息注釋掉并加上cluster的節(jié)點(diǎn)信息即可。
spring:
redis:
cluster:
nodes: 192.168.36.128:6379,192.168.36.128:6380,192.168.36.130:6379,192.168.36.130:6380,192.168.36.131:6379,192.168.36.131:6380# sentinel:# master: mymaster# nodes: 192.168.36.128:26379,192.168.36.130:26379,192.168.36.131:26379
timeout: 3000
lettuce:
pool:
max-active: 80
min-idle: 50
Cluster模式下由于存在多個(gè)Master節(jié)點(diǎn),所以在存儲(chǔ)數(shù)據(jù)時(shí),需要確定將這個(gè)數(shù)據(jù)存儲(chǔ)到哪臺(tái)機(jī)器上。上面在啟動(dòng)集群成功后可以看到每臺(tái)Master節(jié)點(diǎn)都有自己的一個(gè)槽位(Slots)范圍,Master[0]的槽位范圍是0 - 5460,Master[1]的槽位范圍是5461 - 10922,Master[2]的槽位范圍是10922 - 16383。redis在存儲(chǔ)前會(huì)通過CRC16方法計(jì)算出key的hash值,并與16383進(jìn)行位運(yùn)算來確定最終的槽位值。所以,可以知道確定槽位的方式就是 CRC16(key) & 16383
。計(jì)算出槽位后,此時(shí)在java服務(wù)端并不知道這個(gè)槽位對(duì)應(yīng)到哪一臺(tái)redis服務(wù),其實(shí)在java服務(wù)端啟動(dòng)服務(wù)時(shí)會(huì)將redis的相關(guān)槽位和映射的ip信息進(jìn)行一個(gè)本地緩存,所以知道槽位后,就會(huì)知道對(duì)應(yīng)槽位的ip。
cluster模式中的選舉與哨兵中的不同。當(dāng)某個(gè)從節(jié)點(diǎn)發(fā)現(xiàn)自己的主節(jié)點(diǎn)狀態(tài)變?yōu)閒ail狀態(tài)時(shí),便嘗試進(jìn)行故障轉(zhuǎn)移。由于掛掉的主節(jié)點(diǎn)可能會(huì)有多個(gè)從節(jié)點(diǎn),從而存在多個(gè)從節(jié)點(diǎn)競(jìng)爭(zhēng)成為新主節(jié)點(diǎn) 。其選舉過程大概如下:
從節(jié)點(diǎn)將自己記錄的集群currentEpoch加1,并廣播FAILOVER_AUTH_REQUEST信息,通知集群中的所有節(jié)點(diǎn),需要進(jìn)行重新選舉了。
其他節(jié)點(diǎn)收到該信息,但只有master節(jié)點(diǎn)會(huì)進(jìn)行響應(yīng),判斷請(qǐng)求者的合法性,并發(fā)送 FAILOVER_AUTH_ACK,對(duì)每一個(gè)epoch只發(fā)送一次ack。
發(fā)送通知的從節(jié)點(diǎn)會(huì)收集各master主節(jié)點(diǎn)返回的FAILOVER_AUTH_ACK。
如果該從節(jié)點(diǎn)收到的ack數(shù)過半,那么該節(jié)點(diǎn)就會(huì)被選舉為新的Master主節(jié)點(diǎn)。成為主節(jié)點(diǎn)后,廣播通知其他小集群節(jié)點(diǎn)
優(yōu)點(diǎn):
有多個(gè)主節(jié)點(diǎn),做到去中心化。
數(shù)據(jù)可以槽位進(jìn)行分布存儲(chǔ)
擴(kuò)展性更高,可用性更高。cluster集群中的節(jié)點(diǎn)可以在線添加或刪除,官方推薦節(jié)點(diǎn)數(shù)不超1000。當(dāng)部分Master節(jié)點(diǎn)不可用時(shí),整個(gè)集群任然可以正常工作。
缺點(diǎn):
數(shù)據(jù)通過異步復(fù)制,不保證數(shù)據(jù)的強(qiáng)一致性
Slave節(jié)點(diǎn)在集群中充當(dāng)冷備,不能緩解讀壓力
以上就是“Redis高可用架構(gòu)如何搭建”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。