Docker 演示 Redis Sentinel 高可用方案

歡迎訪問陳同學博客原文

介紹

Redis 目前被廣泛應用,緩存、限流、PubSub、分佈式鎖、分佈式數據結構等等許多場景都十分實用,Redis 的高可用(High Available) 自然是必不可少。

Redis 單機有單點故障,Master-Slave 無法做自動故障轉移,可以使用官方推薦的 Sentinel 實現Redis高可用方案。

Sentinel 負責監控 Redis Master,同時 Sentinel 集羣之間通過 Master 進行通訊。Sentinel 以集羣保障自身的可靠性,官方建議 Sentinel 至少保持3個節點。

Sentinel 提供以下特性(來自官網):

  • 監控(Monitoring):持續檢查 master、slave 健康狀況
  • 提醒(Notification):當Redis實例出問題時,可以通過系統管理員或以API形式通知其他應用。
  • 自動故障轉移(Automatic failover):當master發生故障時,Sentinel 會開啓故障處理流程,將一個slave晉升爲master,並將其他slave重新配置到新的master。當應用進行連接時,Sentinel會將新的master告知應用。
  • 配置提供者(Configuration provider):Sentinel 爲客戶端提供master節點的地址,當發生故障時,負責報告新的master節點給客戶端。

Sentinel HA 搭建

實驗環境:CentOS 7、Docker 1.13.1

搭建Redis Master-Slave

運行3個redis實例,設置一主兩從。

docker run -it --name redis-master -d redis redis-server
docker run -it --name redis-slave1 -d redis redis-server
docker run -it --name redis-slave2 -d redis redis-server

使用下面命令拿到 redis-master 的IP: 172.17.0.4

docker inspect --format='{{.NetworkSettings.IPAddress}}' redis-master

爲兩個slave節點分別執行下面命令,將自己設置爲slave.

docker exec -it redis-slave1 redis-cli -p 6379
127.0.0.1:6379> slaveof 172.17.0.4 6379

服從複製已搭建好,可以在master看看主從複製的狀態,此時已經檢測到兩個連接上來的slave.

docker exec -it redis-master redis-cli -p 6379
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.17.0.5,port=6379,state=online,offset=546,lag=1
slave1:ip=172.17.0.6,port=6379,state=online,offset=546,lag=0
...

在master做增刪改操作後數據會立即同步到2個slave,主從結構可以做讀寫分離,緩解主庫壓力。

搭建Sentinel集羣

準備配置文件

先從官網下載 Sentinel 的demo配置文件。

redis 配置文件改成 redis.conf 即可。

wget http://download.redis.io/redis-stable/sentinel.conf

做如下修改:

  • 設置需要監控的master節點信息,格式:sentinel monitor <master-name> <master-redis-ip> <master-redis-port> <quorum>
sentinel monitor mymaster 172.17.0.4 6379 2

如果要監控多個master集羣,這裏可以寫多行,各個集羣的自定義集羣名要修改一下。

quorum 是最小投票數,準備使用3個sentinel節點,設置爲2後選擇新master時需要2個節點同意。

  • 設置 daemonize yes 表示以後臺守護程序運行

運行集羣

sentinel.conf 複製三個,分別爲 sentinel1.conf、sentinel2.conf、sentinel3.conf,在啓動時這幾個文件會被自動寫入一些其他配置信息。

先啓動三個redis實例:redis-sentinel1、2、3,由於sentinel會修改sentinel.conf,我的配置文件位於 /root/redis 目錄。

docker run -it --name redis-sentinel1 --privileged -v /root/redis/sentinel1.conf:/data/sentinel.conf -d redis
docker run -it --name redis-sentinel2 --privileged -v /root/redis/sentinel2.conf:/data/sentinel.conf -d redis
docker run -it --name redis-sentinel3 --privileged -v /root/redis/sentinel3.conf:/data/sentinel.conf -d redis

接着使用 /data/sentinel.conf配置啓動 redis-sentinel,sentinel其實是一個運行在特殊模式下的 Redis實例。

docker exec -it redis-sentinel1 redis-sentinel /data/sentinel.conf
docker exec -it redis-sentinel2 redis-sentinel /data/sentinel.conf
docker exec -it redis-sentinel3 redis-sentinel /data/sentinel.conf

此時任意一臺sentinel節點可以看到的信息:

docker exec -it redis-sentinel3 redis-cli -p 26379
127.0.0.1:26379> info Sentinel
# Sentinel
sentinel_masters:1
master0:name=mymaster,status=ok,address=172.17.0.4:6379,slaves=2,sentinels=3

可以看到:master節點是 172.17.0.4,有2個slave、3個sentinel節點。

自動故障切換測試

停止 master節點,再看看sentinel信息。

docker stop redis-master

很快sentinel會重新選舉一個master,新的節點是:172.17.0.6,不再是172.17.0.4

master0:name=mymaster,status=ok,address=172.17.0.6:6379,slaves=2,sentinels=3

此時再啓動 redis-master,查看其狀態,切換成了slave節點。

docker exec -it redis-master redis-cli -p 6379
127.0.0.1:6379> info Replication
# Replication
role:slave
master_host:172.17.0.6
master_port:6379
master_link_status:up

Spring Boot 使用演示

以一個Spring Boot 2.0.6.RELEASE 程序演示配置及使用,先引入 redis 操作組件依賴(也可以使用Redisson):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置 sentinel 節點:

這裏使用的是容器的IP:Port,需要將本機網絡和容器網絡打通,可參考 Mac 如何訪問容器網絡.

spring:
  redis:
    sentinel:
      master: mymaster
      nodes: 172.17.0.2:26379, 172.17.0.3:26379, 172.17.0.7:26379

提供一個簡單的讀寫接口:

@RestController
public class DemoController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @GetMapping("sentinel")
    public String sentinel() {
        stringRedisTemplate.opsForValue().set("hello", "sentinel");
        return stringRedisTemplate.opsForValue().get("hello");
    }
}

訪問 http://localhost:8080/sentinel,此時去redis任意節點查看,都能看到 hello:sentinel

以容器來演示非常方便,實際使用時,使用內部域名將IP全部換掉即可。


歡迎關注公衆號 [陳一樂],一起學習,一起成長

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章