搭建Redis-Sentinel 叢集環境
環境準備
- linux 系統 centOS 7.3 虛拟機一台(也可以放在多個虛拟機上)
- 端口配置設定
執行個體名稱 | ip | 端口 |
---|---|---|
redis-master | 127.0.0.1 | 7501 |
redis-slave1 | 127.0.0.1 | 7502 |
redis-slave2 | 127.0.0.1 | 7503 |
redis-slave3 | 127.0.0.1 | 7504 |
redis-sentinel1 | 127.0.0.1 | 7505 |
redis-sentinel2 | 127.0.0.1 | 7506 |
redis-sentinel3 | 127.0.0.1 | 7507 |
- 整體架構拓撲圖
安裝Redis
- 進入到想安裝的檔案路徑中
cd /root/jiachang/redis
- 下載下傳redis
wget http://download.redis.io/releases/redis-3.2.1.tar.gz
- 解壓
tar -xzf redis-3.2.1.tar.gz
- 進入解壓後的檔案夾
cd redis-3.2.1
- 檢查是否安裝gcc,沒有的話進行安裝,并編譯redis源碼
// 檢查是否安裝
yum list installed | grep gcc
// 安裝
yum -y install gcc
// 編譯
make [MALLOC=libc]
make install
- 在/usr/local/ 下建立一個目錄redis-sentinel,然後在此目錄下建立7501/ 7502/ 7503/ 7504/ 7505/ 7506/ 7507/七個目錄
mkdir /usr/local/redis-sentinel
mkdir /usr/local/redis-sentinel/{7501,7502,7503,7504,7505,7506,7507}
- 将redis安裝目錄下的reids.conf,拷貝到前4個目錄下,分别命名為:redis-7501.conf redis-7502.conf redis-7503.conf redis-7504.conf
cp /root/redis-3.2.1/redis.conf /usr/local/redis-sentinel/7501/redis-7501.conf
cp /root/redis-3.2.1/redis.conf /usr/local/redis-sentinel/7502/redis-7502.conf
cp /root/redis-3.2.1/redis.conf /usr/local/redis-sentinel/7503/redis-7503.conf
cp /root/redis-3.2.1/redis.conf /usr/local/redis-sentinel/7504/redis-7504.conf
- 修改redis的conf配置檔案,主從的配置幾乎都一樣(有些地方還是有差別的),以7501端口的redis執行個體為例進行分析
## 開啟守護模式
daemonize yes
pidfile /var/run/redis_7501.pid
## 端口号
port 7501
bind 127.0.0.1
## redis運作産生的日志
logfile "./redis-7501.log"
#資料目錄,資料庫的寫入會在這個目錄。rdb、aof檔案也會寫在這個目錄
dir "/usr/local/redis-sentinel/7501"
## redis配置密碼的話,需要以下配置
masterauth "123456"
requirepass "123456"
## 打開aof持久化
appendonly yes
其他子節點對應的conf檔案也要進行修改,跟上面差不多,不一樣的值:
port、pidfile 、logfile 、dir
需要新增的地方:
# 指定所屬的master
slaveof 127.0.0.1 7501
# 指定slave隻讀
slave-read-only yes
- 啟動redis執行個體
redis-server /usr/local/redis-sentinel/7501/redis-7501.conf
redis-server /usr/local/redis-sentinel/7502/redis-7502.conf
redis-server /usr/local/redis-sentinel/7503/redis-7503.conf
redis-server /usr/local/redis-sentinel/7504/redis-7504.conf
-
檢查Redis是否啟動成功
1> 使用ping指令
redis-cli -h 127.0.0.1 -p 7501 ping
PONG
2> 檢視redis程序
ps -ef | grep redis
root 7795 1 0 16:34 ? 00:00:17 redis-server 127.0.0.1:7501
root 31756 1 0 12:09 ? 00:00:25 ./redis-server 127.0.0.1:7502
root 31766 1 0 12:09 ? 00:00:29 ./redis-server 127.0.0.1:7503
root 31777 1 0 12:09 ? 00:00:25 ./redis-server 127.0.0.1:7504
- 啟動成功後,檢視Redis的主從關系
- 使用
登入到Redis執行個體上redis-cli -h 127.0.0.1 -p 7501
- 使用
info replication
檢視主從關系資訊
主節點資訊如下:
[[email protected] ~]# redis-cli -h 127.0.0.1 -p 7501
127.0.0.1:7501> info replication
# Replication
role:master // 代表目前節點是從節點
connected_slaves:3
// 下面是從節點的資訊
slave0:ip=127.0.0.1,port=7504,state=online,offset=12880468,lag=1
slave1:ip=127.0.0.1,port=7502,state=online,offset=12880600,lag=1
slave2:ip=127.0.0.1,port=7503,state=online,offset=12880600,lag=1
master_repl_offset:12880732
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:11832157
repl_backlog_histlen:1048576
從節點資訊如下:
[[email protected] ~]# redis-cli -h 127.0.0.1 -p 7502
127.0.0.1:7502> info replication
# Replication
role:slave // 代表目前節點是從節點
// 下面是主節點的資訊
master_host:127.0.0.1
master_port:7501
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:12935376
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
- 其他測試
1. 從節點隻讀權限
127.0.0.1:7502> set zhangsan www
(error) READONLY You can't write against a read only slave.
2. 主節點更新資料後,從節點進行檢視
[[email protected] ~]# redis-cli -h 127.0.0.1 -p 7501
127.0.0.1:7501> set key1 value1
OK
127.0.0.1:7501> exit
[[email protected] ~]# redis-cli -h 127.0.0.1 -p 7502
127.0.0.1:7502> get key1
"value1"
搭建Sentinel
- 将redis安裝目錄下的sentinel.conf拷貝到7505/ 7506/和7507/目錄下分别命名: sentinel-7505.conf sentinel-7506.conf sentinel-7507.conf
cp /root/jiachang/redis/redis-3.2.1/sentinel.conf /usr/local/redis-sentinel/7505/sentinel-7505.conf
cp /root/jiachang/redis/redis-3.2.1/sentinel.conf /usr/local/redis-sentinel/7505/sentinel-7506.conf
cp /root/jiachang/redis/redis-3.2.1/sentinel.conf /usr/local/redis-sentinel/7505/sentinel-7507.conf
- 修改配置項
daemonize yes
port 7505
#指定工作目錄
dir "/usr/local/redis-sentinel/7505"
logfile "./sentinel-7505.log"
#指定别名 主節點位址 端口 哨兵個數(有幾個哨兵監控到主節點當機執行轉移 判斷主節點失敗至少需要2個Sentinel節點節點同意)
sentinel monitor mymaster 127.0.0.1 7501 2
#如果哨兵3s内沒有收到主節點的心跳,哨兵就認為主節點當機了,預設是30秒
sentinel down-after-milliseconds mymaster 3000
## 當Sentinel節點集合對主節點故障判定達成一緻時,Sentinel上司者節點會做故障轉移操作,選出新的主節點,原來的從節點會向新的主節點發起複制操作,限制每次向新的主節點發起複制操作的從節點個數為1
sentinel parallel-syncs mymaster 1
# 故障轉移逾時時間
sentinel failover-timeout mymaster 10000
#配置連接配接redis主節點密碼
sentinel auth-pass mymaster 123456
- 啟動3個Sentinel
redis-sentinel /usr/local/redis-sentinel/7505/sentinel-7505.conf
redis-sentinel /usr/local/redis-sentinel/7506/sentinel-7506.conf
redis-sentinel /usr/local/redis-sentinel/7507/sentinel-7507.conf
還有一種啟動指令
redis-server /usr/local/redis-sentinel/7505/sentinel-7505.conf --sentinel
- 此時再去檢視程序,發現sentinel已經啟動成功
root 6390 1 0 15:48 ? 00:00:29 redis-sentinel *:7505 [sentinel]
root 6426 1 0 15:49 ? 00:00:28 redis-sentinel *:7506 [sentinel]
root 6434 1 0 15:49 ? 00:00:29 redis-sentinel *:7507 [sentinel]
root 7795 1 0 16:34 ? 00:00:17 redis-server 127.0.0.1:7501
root 16257 29348 0 21:28 pts/1 00:00:00 grep --color=auto redis
root 31756 1 0 12:09 ? 00:00:25 ./redis-server 127.0.0.1:7502
root 31766 1 0 12:09 ? 00:00:29 ./redis-server 127.0.0.1:7503
root 31777 1 0 12:09 ? 00:00:25 ./redis-server 127.0.0.1:7504
- 啟動成功後的變化
-
自動發現了其他的sentinel節點
1> sentinel 啟動日志檢視
tail -200f /usr/local/redis-sentinel/7505/sentinel-7505.log
2> 在sentinel的配置檔案最下面會多出如下配置
-
Sentinel一些指令介紹
要想使用Sentinel,必須使用redis-cli指令進入到Sentinel
redis-cli -h 127.0.0.1 -p 7505
如果有密碼 後面再加上 -a 密碼
- info : sentinel的基本狀态資訊 (例如監控的redis主節點的資訊)
- sentinel masters : 監控的主節點的資訊
1) "name"
2) "mymaster"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "7501" (這裡就是主節點的端口資訊)
7) "runid"
8) "06fce2f40c76e0a984d304d519fe6e437ff88aa6"
9) "flags"
10) "master"
.........
- sentinel slaves mymaster : 監控的從節點的資訊(下面會依次列出3個從節點的詳細資訊)
故障轉移試驗
- 我們将master節點-7501 強制kill掉
ps -ef|grep redis
kill -9 pid
- 檢視一下Sentinel節點監控的主節點資訊
- 當将Redis主節點kill掉以後,Redis Sentinel對主節點進行客觀下線(Objectively Down, 簡稱 ODOWN)的判斷,确認主節點不可達,則通知從節點中止複制主節點的操作。
127.0.0.1:7505> sentinel masters
1) 1) "name"
2) "mymaster"
3) "ip"
4) "127.0.0.1"
5) "port"
6) "7503"
7) "runid"
8) "06fce2f40c76e0a984d304d519fe6e437ff88aa6"
9) "flags"
10) "master"
11) "link-pending-commands"
........
此時發現 7503已經更新為master
sentinel日志也可以看得出來,這個時候Sentinel的配置檔案也修改了。
- 繼續啟動7501節點後,變為7503的子節點,跟正常一樣。
部署過程中遇到的坑
- bind含義:代表該redis執行個體能被其他伺服器通路的ip位址。比如這台機器有外網ip(114.15.54.55)和内網ip,我隻想把内網ip(172.16.130.52)暴露出去,那這裡就配置内網ip(172.16.130.52),别人通路這台redis示例隻能通過這個ip,外網的那個就不行了。預設是不限制的。
-
如果redis需要配置密碼的話,主從Redis示例需要增加以下配置
masterauth “123456”
requirepass “123456”
注意,這兩個的值一定要一樣!!
requirepass 表示 我給這個redis設定的登入密碼,你要通過redis-cli登入到這台redis上面就要輸入密碼了
AUTH password
masterauth : 這個又代表什麼意思呢,主節點redis設定了密碼,你的從節點想要同步主節點的資料,肯定也要輸入密碼了,是以就把這個變量配置上去就行了,是以它的值肯定跟requirepass保持一緻了。
因為每個節點都有可能是主節點,是以主從節點關于這個的配置要保持一緻,不然就亂套了。
- protected-mode : 在Redis的配置中,有這個配置,什麼意思呢?就是要不要開啟保護模式,預設是yes的。開啟的時候,隻有本地能連接配接成功,其他的機器想要連接配接你這個redis會報錯的。如果關閉了,就不安全了,但是可以通過其他的措施進行保護,是以官方文檔也說了有以下幾種方案:
-
使用 設定CONFIG SET protected-mode no
步驟:
在redis本機上打開redis-cli工具,并連接配接
在其中輸入CONFIG SET protected-mode no即可
缺點:
該種方式隻是短暫性有效,如果redisServer重新啟動後還是不能正常連結
- 保護模式關閉,重新開機(不安全,不推薦)
- 如果隻是測試的話,啟動的時候加上
--protected-mode no
- bind ip或者加上密碼認證(一般線上這兩個都配置才安全)
-
- sentinel 的 protected-mode也要改為no,原來的配置檔案沒有的,要手動加上去。
代碼實踐(Java版本)
需要引用的jar
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
package com.sunny.redis.sentinel;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;
/**
* @author JiaChang
* @date 2018/12/18
*/
public class SentinelUtil {
private static final Set SENTINELS = new HashSet();
private static String IP = "";
static {
//服務IP
IP = "172.16.150.**";
// Sentine端口
SENTINELS.add(new HostAndPort(IP, 7505).toString());
SENTINELS.add(new HostAndPort(IP, 7506).toString());
SENTINELS.add(new HostAndPort(IP, 7507).toString());
}
public static void main(String[] args) {
JedisSentinelPool sentinelPool = new JedisSentinelPool("mymaster", SENTINELS);
System.out.println("Current master: " + sentinelPool.getCurrentHostMaster().toString());
Jedis master = sentinelPool.getResource();
master.auth("***");
master.set("username","張三");
sentinelPool.returnResource(master);
Jedis master2 = sentinelPool.getResource();
master2.auth("***");
String value = master2.get("username");
System.out.println("username: " + value);
master2.close();
sentinelPool.destroy();
}
}
運作結果:
Current master: 172.16.150.**:7501
username: 張三