redis sentinel高可用性方案

參考:redis官方文檔,Redis 復(fù)制、Sentinel的搭建和原理說(shuō)明

Redis Sentinel(哨兵) 是redis自帶的集群管理工具。目前官方推薦使用redis2.8或3.0及以上版本,一個(gè)穩(wěn)定的Sentinel 2已經(jīng)包括在這些版本中,redis2.6不建議使用。

主要功能

  • 監(jiān)控(Monitoring)
        Sentinel會(huì)不斷檢查redis主服務(wù)(master)與從服務(wù)(slave)是否正常工作
  • 提醒(Notification)
          當(dāng)被監(jiān)控的某一個(gè)redis服務(wù)出現(xiàn)故障時(shí),Sentinel會(huì)通過(guò)api通知管理員或應(yīng)用程序
    
  • 災(zāi)難自動(dòng)恢復(fù)(Automatic failOver)
          當(dāng)主服務(wù)出現(xiàn)故障,Sentinel會(huì)開(kāi)始災(zāi)難恢復(fù),選出一個(gè)從服務(wù)升級(jí)為主服務(wù)繼續(xù)向提供服務(wù)
          同時(shí)其他的從服務(wù)改為監(jiān)聽(tīng)最新的主服務(wù),當(dāng)之前的主服務(wù)故障恢復(fù)后,Sentinel會(huì)自動(dòng)把恢復(fù)的服務(wù)改成從服務(wù)
    
  • 主redis配置提供(Configuration provider)
          客戶端通過(guò)連接Sentinel來(lái)獲取當(dāng)前主redis服務(wù)的地址,如果主redis服務(wù)掛了,Sentinel會(huì)自動(dòng)報(bào)告最新的主redis服務(wù)地址
    

簡(jiǎn)介

Sentinel是一個(gè)分布式系統(tǒng):

多個(gè)Sentinel進(jìn)程相互協(xié)作,每一個(gè)Sentinel都在自己的配置中運(yùn)行,Sentinel必須通過(guò)配置文件啟動(dòng),這樣做的優(yōu)勢(shì):

  1. 當(dāng)已知的主redis不可用時(shí),多個(gè)Sentinel會(huì)對(duì)主redis進(jìn)行故障檢測(cè),減少誤判
  2. 即使個(gè)別Sentinel不可用,整個(gè)分布式系統(tǒng)還是可以使用
  3. 通過(guò)配置文件保存當(dāng)前的服務(wù)狀態(tài),Sentinel重啟的時(shí)候可以重新加載這些狀態(tài)
名詞解釋:
  • 主觀下線(Subjectively Down, 簡(jiǎn)稱(chēng) SDOWN)
    單個(gè) Sentinel 實(shí)例對(duì)服務(wù)器做出的下線判斷
  • 客觀下線(Objectively Down, 簡(jiǎn)稱(chēng) ODOWN)
    多個(gè)Sentinel對(duì)同一個(gè)服務(wù)器做出SDOWN判斷,并且互相交流之后, 得出的服務(wù)器下線判斷。
工作原理:
  1. Sentinel集群通過(guò)給定的配置文件發(fā)現(xiàn)的master,啟動(dòng)時(shí)監(jiān)控master,同時(shí)通過(guò)向master發(fā)送info來(lái)獲得所有的slave
  2. sentinel通過(guò)命令連接向被監(jiān)視的主從服務(wù)器發(fā)送hello信息(每秒一次),以此來(lái)向其他sentinel宣告自己的存在
  3. sentinel通過(guò)訂閱接收其他sentinel發(fā)送的hello信息,以此來(lái)發(fā)現(xiàn)監(jiān)視同一個(gè)master的其他sentinel
  4. sentinel使用ping命令來(lái)檢測(cè)服務(wù)的狀態(tài),如果在指定的時(shí)間內(nèi)(down-after-milliseconds)沒(méi)有正確回復(fù),判定SDOWN,觸發(fā)failover
  5. failover被觸發(fā)后,不會(huì)馬上進(jìn)行,還需要集群中大多數(shù)sentinel授權(quán)后才可以進(jìn)行,即進(jìn)行failover的sentinel會(huì)去獲得指定個(gè)數(shù)的sentinel的授權(quán),成功后進(jìn)入ODOWN。如在5個(gè)sentinel中配置了2,等到2個(gè)sentinel認(rèn)為master死了就執(zhí)行failover。
  6. sentinel向選為master的slave發(fā)送SLAVEOF NO ONE命令,選擇slave的條件是sentinel首先會(huì)根據(jù)slaves的優(yōu)先級(jí)來(lái)進(jìn)行排序,優(yōu)先級(jí)越小排名越靠前。
  7. sentinel被授權(quán)后,它將會(huì)獲得宕掉的master的一份最新配置版本號(hào)(config-epoch),當(dāng)failover執(zhí)行結(jié)束以后,這個(gè)版本號(hào)將會(huì)被用于最新的配置,通過(guò)廣播形式通知其它sentinel,其它的sentinel則更新對(duì)應(yīng)master的配置。


    image.png

配置

目錄結(jié)構(gòu)
directoryStructure.png
master redis
#編輯/masterRedisPath/redis_master.conf文件 
bind 10.0.2.190 #默認(rèn)為127.0.0.1,通過(guò)Sentinel獲得redis主服務(wù)器地址時(shí)會(huì)映射成此地址,外部鏈接將無(wú)法連接到redis服務(wù)
protected-mode no #默認(rèn)為yes,即只有本機(jī)可以訪問(wèn),關(guān)掉保護(hù)模式,可以使外部應(yīng)用訪問(wèn)該redis, 設(shè)置為no后一定要設(shè)置redis連接密碼
port 6379 #默認(rèn)端口號(hào),當(dāng)部署主從redis時(shí),需要設(shè)置不同的端口
daemonize yes #守護(hù)進(jìn)程
pidfile "/var/run/redis_6379.pid" #pid文件,redis主從服務(wù)器需設(shè)置不同pid文件路徑
logfile "/home/log/redis_6379.log" #redis日志文件
masterauth utry1234 #主服務(wù)器驗(yàn)證密碼
requirepass utry1234 #redis連接密碼
slave redis
#基本與主redis配置相同,只解釋不同部分
#slaveof <master-ip> <master-port> 這個(gè)是slave的關(guān)鍵,配置后即可成為master的slave
#即redis會(huì)采用異步復(fù)制的方式將數(shù)據(jù)從master熱備到slave
#默認(rèn)下slave是只讀的,可以通過(guò)配置關(guān)閉
#編輯/slaveRedispath/redis_slave.conf
bind 10.0.2.190 
protected-mode no 
port 6380 #從redis服務(wù)器端口
daemonize yes 
pidfile "/var/run/redis_6380.pid" 
logfile "/home/log/redis_6380.log" 
masterauth utry1234
slaveof 10.0.2.190 6379 #設(shè)置從屬的主redis服務(wù)器訪問(wèn)地址,即以這個(gè)配置文件啟動(dòng)的redis為slave
requirepass utry1234
Sentinel
#根據(jù)官方推薦配置至少3個(gè)Sentinel以保證系統(tǒng)穩(wěn)定工作
#redis安裝目錄下提供了sentinel.conf的配置示例,在主redis目錄下復(fù)制該示例3份,分別命名sentinel63791.conf,sentinel63792.conf,sentinel63793.conf
port 63791 #sentinel端口
protected-mode no #sentinel.conf默認(rèn)是沒(méi)有這個(gè)配置的,需要手動(dòng)添加
daemonize yes #守護(hù)進(jìn)程
logfile "/home/log/sentinel_63791.log" #運(yùn)行日志,可以在此查看主從狀態(tài)
sentinel monitor mymaster 10.0.2.190 6379 2 #配置監(jiān)控主服務(wù)器,mymaster:定義主服務(wù)器名, 10.0.2.190:主服務(wù)ip 6379:主服務(wù)端口 2:設(shè)置當(dāng)有2個(gè)sentinel判斷master故障后才真正認(rèn)為master無(wú)法繼續(xù)提供服務(wù),即開(kāi)始容災(zāi)措施
sentinel down-after-milliseconds mymaster 60000 #指定sentinel認(rèn)定一個(gè)服務(wù)器斷線的毫秒數(shù),即一個(gè)sentinel認(rèn)定服務(wù)SDOWN,在這個(gè)配置時(shí)間內(nèi)需要獲得指定個(gè)數(shù)的Sentinel判定ODWON,才開(kāi)始failover
sentinel failover-timeout mymaster 180000 #在觸發(fā)failover多少秒后任未執(zhí)行任何failover,則被認(rèn)為failover失敗
sentinel parallel-syncs mymaster 1 #選項(xiàng)指定了在執(zhí)行故障轉(zhuǎn)移時(shí), 最多可以有多少個(gè)從服務(wù)器同時(shí)對(duì)新的主服務(wù)器進(jìn)行同步,這個(gè)數(shù)字越小, 完成故障轉(zhuǎn)移所需的時(shí)間就越長(zhǎng)
sentinel auth-pass mymaster utry1234 #主redis服務(wù)器驗(yàn)證密碼

啟動(dòng)服務(wù)

主redis: redis-server /masterRedisPath/to/redis.conf
從redis: redis-server /slaveRedisPath/to/redis.conf
訪問(wèn)redis: redis-cli -h 10.0.2.190 -p 6379 -a utry1234 #-h:ip地址,-p:訪問(wèn)端口,-a:連接密碼
進(jìn)入redis客戶端之后,通過(guò)info命令查看redis主從狀態(tài): info replication
sentinel: redis-sentinel /path/to/sentinel.conf 
          或 redis-server  /path/to/sentinel.conf  --sentinel
訪問(wèn)sentinel:與訪問(wèn)redis一樣,可以用info命令查看集群狀態(tài): info

測(cè)試

啟動(dòng)master與slave之后
查看master的狀態(tài):role:master,同時(shí)顯示了slave的信息

master_redis.png

查看slave狀態(tài):role:slave,同時(shí)顯示了所屬的master redis信息

slave_redis.png

查看Sentenel狀態(tài):status =ok,同時(shí)顯示了當(dāng)前的master訪問(wèn)地址,以及slave和sentinel數(shù)量

sentinel_63791_conf.png

down掉master redis 進(jìn)程,查看sentinel日志,sentinel自動(dòng)把slave選舉為新的master,同時(shí)slave的狀態(tài)信息role:master

sentinel_63791_log.png
過(guò)程解釋?zhuān)?/h6>
  1. Sentinel發(fā)現(xiàn)master不可用判定主觀下線(SDOWN)
  2. 與集群中其他的Sentinel交流后判定為客觀下線(ODWON)
  3. Sentinel投票選舉出一個(gè)領(lǐng)頭羊Sentienl,由這個(gè)領(lǐng)頭羊來(lái)進(jìn)行failover
  4. 領(lǐng)頭羊?qū)⑦x出一個(gè)slave升級(jí)為master,同時(shí)修改這個(gè)被升級(jí)的slave的配置使其成為master的配置
  5. 將其他的slave配置改成最新master的slave,同時(shí)通知其他Sentinel進(jìn)行修改
  6. 當(dāng)之前的master從故障中恢復(fù)后,sentinel會(huì)自動(dòng)發(fā)現(xiàn),并采用最新的配置,將這個(gè)恢復(fù)的redis改成最新master的slave
new_slave.png

與Jedis集成

jedis支持Sentinel+redis形式的高可用redis方案
gradle
compile 'redis.clients:jedis:2.6.3'
compile 'org.springframework.data:spring-data-redis:1.6.0.RELEASE' 
spring XML configuration
<bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">
    <property name="master"><!-- 配置master的名字,和Sentinel中配置的master名字一致 -->
      <bean class="org.springframework.data.redis.connection.RedisNode">
        <property name="name" value="mymaster"></property>
      </bean>
    </property>
    <property name="sentinels"><!-- 配置可用的Sentinel -->
         <set>
            <bean class="org.springframework.data.redis.connection.RedisNode">                   
                <constructor-arg name="host" value="10.0.2.190"/>
                <constructor-arg name="port" value="63791"/>               
            </bean>
            <bean class="org.springframework.data.redis.connection.RedisNode">                   
                <constructor-arg name="host" value="10.0.2.190"/>
                <constructor-arg name="port" value="63792"/>               
            </bean>
            <bean class="org.springframework.data.redis.connection.RedisNode">                   
                <constructor-arg name="host" value="10.0.2.190"/>
                <constructor-arg name="port" value="63793"/>               
            </bean>
        </set>
    </property>
</bean>
<!-- 配置redis連接工廠 -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <constructor-arg ref="sentinelConfig" /><!--  sentinel配置-->
    <property name="password" value="utry1234"/><!-- redis連接密碼 -->
</bean>
<!-- redis操作模板,在代碼中注入這個(gè)模板,就可以進(jìn)行redis的相關(guān)操作了  -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容