
一、前言
redis在我們企業(yè)級開發(fā)中是很常見的,但是單個(gè)redis不能保證我們的穩(wěn)定使用,所以我們要建立一個(gè)集群。
redis有兩種高可用的方案:
- High availability with Redis Sentinel(哨兵)
- Scaling with Redis Cluster(分片集群)
第一個(gè)就是我們本次的要搭建的,就是高可用的哨兵,主redis掛掉,哨兵會(huì)進(jìn)行投票進(jìn)行??故障轉(zhuǎn)移?
?!
第二個(gè)就是分片集群,哨兵的一個(gè)缺點(diǎn)就是只能存在一個(gè)master節(jié)點(diǎn),寫的效率太低。分片集群就是解決哨兵的問題,可以水平擴(kuò)展,提高redis的性能!
哨兵最低配是三哨兵,以奇數(shù)遞增。
分片集群最低配是三主三從。
二、準(zhǔn)備
首先我們要準(zhǔn)備:
三臺(tái)服務(wù)器(沒有的條件的搭三個(gè)虛擬機(jī)),巧了小編就是虛擬機(jī)哈!
三臺(tái)機(jī)器的ip和名稱在表格里整理一下!
ip
| redis節(jié)點(diǎn)名稱
| sentinel節(jié)點(diǎn)名稱
|
192.168.239.131
| redis-master
| redis-sentinel-1
|
192.168.239.130
| redis-slave-1
| redis-sentinel-2
|
192.168.239.128
| redis-slave-2
| redis-sentinel-3
|
三、Sentinel概念
Redis Sentinel 在不使用Redis Cluster時(shí)為 Redis 提供高可用性。
Sentinel功能的完整列表:
- 監(jiān)控:Sentinel 不斷檢查您的主實(shí)例和副本實(shí)例是否按預(yù)期工作。
- 通知:Sentinel 可以通過 API 通知系統(tǒng)管理員或其他計(jì)算機(jī)程序,其中一個(gè)受監(jiān)控的 Redis 實(shí)例出現(xiàn)問題。
- 自動(dòng)故障轉(zhuǎn)移:如果 master 沒有按預(yù)期工作,Sentinel 可以啟動(dòng)一個(gè)故障轉(zhuǎn)移過程,其中一個(gè)副本被提升為 master,其他額外的副本被重新配置為使用新的 master,并且使用 Redis 服務(wù)器的應(yīng)用程序被告知要使用的新地址連接時(shí)。
- 自動(dòng)更新配置:Sentinel 充當(dāng)客戶端服務(wù)發(fā)現(xiàn)的權(quán)威來源:客戶端連接到 Sentinels 以詢問負(fù)責(zé)給定服務(wù)的當(dāng)前 Redis master 的地址。如果發(fā)生故障轉(zhuǎn)移,Sentinels 將報(bào)告新地址。
官方哨兵搭建條件:
- 您至少需要三個(gè) Sentinel 實(shí)例才能進(jìn)行可靠的部署。
- 三個(gè) Sentinel 實(shí)例應(yīng)該放置在被認(rèn)為以獨(dú)立方式發(fā)生故障的計(jì)算機(jī)或虛擬機(jī)中。因此,例如在不同可用區(qū)上執(zhí)行的不同物理服務(wù)器或虛擬機(jī)。
詳細(xì)介紹和使用:請見官網(wǎng) --->官網(wǎng)詳細(xì)文檔:https://redis.io/docs/management/sentinel/
四、一主二從搭建
話不多說,咱們直接開始搭建哈!
1、創(chuàng)建掛載目錄
三臺(tái)機(jī)器上新建目錄:
首先我們開啟三個(gè)xshell窗口,然后同時(shí)操作三個(gè)窗口創(chuàng)建。

然后再左下角選擇發(fā)送到全部窗口!
cd /
mkdir mydata
cd /mydata
mkdir redis
cd redis
mkdir data
mkdir conf
cd conf
2、在`192.168.239.131`機(jī)器上編輯文件
輸入以下內(nèi)容:
# 任何都可以連接redis
bind 0.0.0.0
# 配置master密碼
requirepass 123456
# 宕機(jī)后成為從要連接master的密碼
masterauth 123456
# 開啟持久化
appendonly yes

3、在`192.168.239.130`機(jī)器上編輯文件
輸入以下內(nèi)容:
# 配置master的ip和端口號
replicaof 192.168.239.131 6379
# 任何都可以連接redis
bind 0.0.0.0
# 成為master后的密碼
requirepass 123456
# 連接master密碼
masterauth 123456
# 開啟持久化
appendonly yes

4、在`192.168.239.128`機(jī)器上編輯文件
輸入以下內(nèi)容:
# 配置master的ip和端口號
replicaof 192.168.239.131 6379
# 任何都可以連接redis
bind 0.0.0.0
# 成為master后的密碼
requirepass 123456
# 連接master密碼
masterauth 123456
# 開啟持久化
appendonly yes
5、`192.168.239.131`啟動(dòng)redis
docker run -p 6379:6379 --name redis-master \
-v /mydata/redis/data:/usr/local/etc/redis/data \
-v /mydata/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \
-d redis redis-server /usr/local/etc/redis/redis.conf
查看啟動(dòng)日志:
docker logs -f redis-master

6、`192.168.239.130`啟動(dòng)redis
docker run -p 6379:6379 --name redis-slave-1 \
-v /mydata/redis/data:/usr/local/etc/redis/data \
-v /mydata/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \
-d redis redis-server /usr/local/etc/redis/redis.conf
可以看到已經(jīng)連接到master節(jié)點(diǎn)了!

7、`192.168.239.128`啟動(dòng)redis
docker run -p 6379:6379 --name redis-slave-2 \
-v /mydata/redis/data:/usr/local/etc/redis/data \
-v /mydata/redis/conf/redis.conf:/usr/local/etc/redis/redis.conf \
-d redis redis-server /usr/local/etc/redis/redis.conf

8、進(jìn)入`192.168.239.130`容器查看
我們查看master日志,可以看到兩個(gè)從節(jié)點(diǎn)已經(jīng)加入進(jìn)來了!

我們進(jìn)入容器進(jìn)行在次查看:
docker exec -it redis-master /bin/bash
連接redis:
登錄redis:

查看從節(jié)點(diǎn):
也是可以看到有兩個(gè)從節(jié)點(diǎn)!

五、搭建三哨兵sentinel
1、創(chuàng)建掛載目錄
還是三個(gè)虛擬機(jī)一起創(chuàng)建。
mkdir sentinel
cd sentinel
vim sentinel.conf
輸入下面內(nèi)容:
port 26379
sentinel monitor redis-master 192.168.239.131 6379 2
sentinel auth-pass redis-master 123456
sentinel down-after-milliseconds redis-master 6000
sentinel parallel-syncs redis-master 1
sentinel failover-timeout redis-master 6000
第二行:Redis 監(jiān)控一個(gè)名為redis-master的redis集群,我們可以隨意寫;后面就是ip,我們宿主機(jī)的ip即可,端口為主redis的端口;2為哨兵投票的票數(shù),當(dāng)主redis宕機(jī),三個(gè)哨兵必須兩個(gè)哨兵都投票的redis才會(huì)變?yōu)橹鳎。?br>第三行:配置master的密碼
第四行:Sentinel判斷實(shí)例進(jìn)入主觀下線所需的時(shí)間,毫秒單位。
第五行:限制在一次故障轉(zhuǎn)移之后,每次向新的主節(jié)點(diǎn)同時(shí)發(fā)起復(fù)制操作節(jié)點(diǎn)個(gè)數(shù),越大效率越慢。
第六行:在指定的時(shí)間內(nèi)未能完成failover故障轉(zhuǎn)移,則任務(wù)故障轉(zhuǎn)移失敗。

2、運(yùn)行`192.168.239.131`哨兵
docker run -p 26379:26379 --name redis-sentinel-1 \
-v /mydata/redis/sentinel/sentinel.conf:/usr/local/etc/redis/sentinel.conf \
-d redis redis-sentinel /usr/local/etc/redis/sentinel.conf
3、運(yùn)行`192.168.239.130`哨兵
docker run -p 26379:26379 --name redis-sentinel-2 \
-v /mydata/redis/sentinel/sentinel.conf:/usr/local/etc/redis/sentinel.conf \
-d redis redis-sentinel /usr/local/etc/redis/sentinel.conf
4、運(yùn)行`192.168.239.128`哨兵
docker run -p 26379:26379 --name redis-sentinel-3 \
-v /mydata/redis/sentinel/sentinel.conf:/usr/local/etc/redis/sentinel.conf \
-d redis redis-sentinel /usr/local/etc/redis/sentinel.conf
5、待解決問題
這里創(chuàng)建三個(gè)哨兵,查看卻是有四個(gè),不知道什么問題,換了虛擬機(jī)還是不行!有大佬懂的可以分享一下哈??!

六、測試主從和故障轉(zhuǎn)移
1、測試主從復(fù)制
master節(jié)點(diǎn)創(chuàng)建一個(gè)鍵值對:

從查看key是否存在:

主從沒有問題哈!
2、測試故障轉(zhuǎn)移
我們把master停掉,查看一個(gè)哨兵的日志:
docker stop redis-master
docker logs -f redis-sentinel-1
我們看到192.168.239.130成為master!

重新啟動(dòng)原來的master:
docker restart redis-master

故障轉(zhuǎn)移成功!!
七、整合springboot
1、導(dǎo)入依賴
小編的springboot版本為:2.7.4。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2、yml配置
password密碼和sentinel同級,不然找不到密碼,驗(yàn)證失敗。
server:
port: 8087
spring:
redis:
# 密碼和sentinel同級,不然找不到密碼,驗(yàn)證失敗
password: 123456
sentinel:
# sentinel.conf里的集群名稱
master: my-master
# 我們只需要連哨兵即可,哨兵內(nèi)部會(huì)幫我們找到redis
nodes:
- 192.168.239.131:26379
- 192.168.239.130:26379
- 192.168.239.128:26379
3、json序列化配置
/**
* @author wangzhenjun
* @date 2022/11/24 10:37
*/
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
{
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
// 使用StringRedisSerializer來序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
4、新建controller測試
/**
* @author wangzhenjun
* @date 2022/11/24 10:37
*/
@RestController
public class TestController {
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/redis")
public void saveRedis(){
redisTemplate.opsForValue().set("test","看到我就成功了");
}
}
5、測試
http://localhost:8087/test/redis

6、查看redis

八、總結(jié)
經(jīng)過一天的搭建,終于完成了,雖然不是完美的,但是大體功能是沒有問題的!但是不影響故障轉(zhuǎn)移和主從復(fù)制!
唯一的遺憾:三個(gè)哨兵,查看就是四個(gè)!從第三個(gè)哨兵加入后變?yōu)?個(gè)!