Redis作為高性能的鍵值存儲(chǔ)系統(tǒng),其高可用與可擴(kuò)展性架構(gòu)是實(shí)際應(yīng)用中的關(guān)鍵。本文將深入探討Redis的主從復(fù)制、哨兵模式,并詳細(xì)說明如何在Spring Boot項(xiàng)目中配置Redis,特別是如何指定只從某臺(tái)服務(wù)器讀取數(shù)據(jù)。
1. 核心概念
Redis主從復(fù)制(Replication)是數(shù)據(jù)冗余和備份的基礎(chǔ),也是實(shí)現(xiàn)高可用架構(gòu)(如哨兵、集群)的基石。其工作模式通常是“一主多從”:主節(jié)點(diǎn)(Master)負(fù)責(zé)處理寫操作,并將數(shù)據(jù)變更異步同步到多個(gè)從節(jié)點(diǎn)(Slave)。從節(jié)點(diǎn)默認(rèn)情況下只處理讀請(qǐng)求,從而實(shí)現(xiàn)讀寫分離,分擔(dān)主節(jié)點(diǎn)壓力。
2. 工作原理
- 當(dāng)從節(jié)點(diǎn)啟動(dòng)并連接到主節(jié)點(diǎn)時(shí),會(huì)發(fā)送一個(gè)SYNC命令(或更高效的PSYNC命令)。
- 主節(jié)點(diǎn)執(zhí)行BGSAVE生成RDB快照文件,同時(shí)緩沖快照生成期間的所有寫命令。
- 快照完成后,主節(jié)點(diǎn)將RDB文件傳輸給從節(jié)點(diǎn),從節(jié)點(diǎn)載入RDB文件恢復(fù)數(shù)據(jù)。
- 主節(jié)點(diǎn)再將緩沖區(qū)的寫命令發(fā)送給從節(jié)點(diǎn)執(zhí)行,實(shí)現(xiàn)增量同步。
- 此后,主節(jié)點(diǎn)每執(zhí)行一個(gè)寫命令,都會(huì)異步地發(fā)送給所有從節(jié)點(diǎn),保持?jǐn)?shù)據(jù)最終一致。
3. 優(yōu)勢(shì)與局限
- 優(yōu)勢(shì):數(shù)據(jù)備份、讀寫分離、擴(kuò)展讀性能。
- 局限:不具備自動(dòng)故障轉(zhuǎn)移能力(主節(jié)點(diǎn)宕機(jī)需手動(dòng)干預(yù)),寫操作仍然集中在單點(diǎn)主節(jié)點(diǎn)。
1. 核心概念
哨兵模式(Sentinel)是為了解決主從復(fù)制中主節(jié)點(diǎn)故障無法自動(dòng)切換而設(shè)計(jì)的高可用方案。哨兵是一個(gè)獨(dú)立的進(jìn)程,用于監(jiān)控Redis主從節(jié)點(diǎn)的健康狀態(tài)。當(dāng)主節(jié)點(diǎn)發(fā)生故障時(shí),哨兵能夠自動(dòng)將一個(gè)從節(jié)點(diǎn)升級(jí)為新的主節(jié)點(diǎn),并讓其他從節(jié)點(diǎn)指向新的主節(jié)點(diǎn),同時(shí)通知客戶端新的主節(jié)點(diǎn)地址。
2. 核心功能
- 監(jiān)控:哨兵會(huì)定期檢查主節(jié)點(diǎn)和從節(jié)點(diǎn)是否正常運(yùn)行。
- 通知:當(dāng)被監(jiān)控的Redis實(shí)例出現(xiàn)問題時(shí),哨兵可以通過API通知系統(tǒng)管理員或其他應(yīng)用程序。
- 自動(dòng)故障轉(zhuǎn)移:如果主節(jié)點(diǎn)不可用,哨兵可以啟動(dòng)一個(gè)故障轉(zhuǎn)移過程,選舉新的主節(jié)點(diǎn),并重新配置其他從節(jié)點(diǎn)和客戶端。
- 配置提供者:客戶端可以連接哨兵來獲取當(dāng)前Redis主節(jié)點(diǎn)的地址。
3. 工作原理
一個(gè)哨兵集群通常由多個(gè)哨兵實(shí)例組成,它們通過投票機(jī)制達(dá)成共識(shí),以避免單點(diǎn)誤判。當(dāng)多數(shù)哨兵認(rèn)為主節(jié)點(diǎn)“主觀下線”并經(jīng)過確認(rèn)后,會(huì)觸發(fā)選舉,選出一個(gè)領(lǐng)頭哨兵來執(zhí)行故障轉(zhuǎn)移。
1. 基礎(chǔ)依賴與配置
在Spring Boot項(xiàng)目中,通常使用spring-boot-starter-data-redis來集成Redis。`xml
`
在application.yml中,基礎(chǔ)的哨兵模式配置示例如下:`yaml
spring:
redis:
sentinel:
master: mymaster # 主節(jié)點(diǎn)名稱,需與哨兵配置一致
nodes: sentinel1:26379,sentinel2:26379,sentinel3:26379 # 哨兵節(jié)點(diǎn)地址列表`
在這種配置下,Spring Boot的Lettuce或Jedis客戶端會(huì)自動(dòng)通過哨兵獲取當(dāng)前可用的主節(jié)點(diǎn)和從節(jié)點(diǎn)列表,并進(jìn)行連接。默認(rèn)情況下,讀寫操作都會(huì)路由到主節(jié)點(diǎn)。
2. 指定只從某臺(tái)從服務(wù)器讀取數(shù)據(jù)
有時(shí),出于負(fù)載均衡、地理位置或特定業(yè)務(wù)邏輯(如數(shù)據(jù)處理服務(wù)只分析從節(jié)點(diǎn)的數(shù)據(jù)副本,不影響主節(jié)點(diǎn)性能)的考慮,我們需要強(qiáng)制讓某個(gè)服務(wù)只連接特定的從節(jié)點(diǎn)進(jìn)行讀操作。
實(shí)現(xiàn)方案:自定義配置,繞過哨兵或集群的自動(dòng)發(fā)現(xiàn),直接連接指定節(jié)點(diǎn)。
步驟示例:
a. 在配置文件中指定目標(biāo)從節(jié)點(diǎn)`yaml
app:
redis:
read-only-slave:
host: 192.168.1.100 # 指定從節(jié)點(diǎn)的IP
port: 6379 # 指定從節(jié)點(diǎn)的端口
password: yourpassword # 如果有密碼`
b. 創(chuàng)建自定義的Redis連接工廠和Template`java
@Configuration
public class ReadOnlyRedisConfig {
@Value("${app.redis.read-only-slave.host}")
private String host;
@Value("${app.redis.read-only-slave.port}")
private int port;
@Value("${app.redis.read-only-slave.password}")
private String password;
@Bean(name = "readOnlyRedisConnectionFactory")
public RedisConnectionFactory readOnlyRedisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPort(port);
config.setPassword(RedisPassword.of(password));
// 使用Lettuce客戶端
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.REPLICA) // 明確指定從副本讀取(雖然這里只有一個(gè)節(jié)點(diǎn))
.build();
return new LettuceConnectionFactory(config, clientConfig);
}
@Bean(name = "readOnlyRedisTemplate")
public RedisTemplate
RedisTemplate
template.setConnectionFactory(factory);
// 設(shè)置序列化方式,例如使用Jackson2JsonRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}`
c. 在數(shù)據(jù)處理服務(wù)中注入并使用專用的Template`java
@Service
public class DataProcessingService {
@Autowired
@Qualifier("readOnlyRedisTemplate") // 注入只讀的Template
private RedisTemplate
public void processData(String key) {
// 所有通過readOnlyRedisTemplate進(jìn)行的操作,都會(huì)指向配置的特定從節(jié)點(diǎn)
Object data = readOnlyRedisTemplate.opsForValue().get(key);
// ... 進(jìn)行數(shù)據(jù)處理邏輯
}
}`
slave-read-only yes(默認(rèn)就是),避免誤操作寫入從節(jié)點(diǎn)。通過以上配置,你的數(shù)據(jù)處理服務(wù)就可以穩(wěn)定地從指定的Redis從節(jié)點(diǎn)讀取數(shù)據(jù),實(shí)現(xiàn)與線上實(shí)時(shí)業(yè)務(wù)的讀寫分離,從而進(jìn)行數(shù)據(jù)分析、報(bào)表生成等后臺(tái)計(jì)算任務(wù),而不會(huì)對(duì)主業(yè)務(wù)鏈路的Redis造成性能壓力。
沖沖沖! 合理利用Redis的主從、哨兵特性,并結(jié)合Spring Boot靈活的配置能力,可以構(gòu)建出既穩(wěn)健又高效的緩存與數(shù)據(jù)存儲(chǔ)架構(gòu)。
如若轉(zhuǎn)載,請(qǐng)注明出處:http://www.pqbzh.cn/product/63.html
更新時(shí)間:2026-02-25 01:24:24
PRODUCT