欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實(shí)現(xiàn)Redis哨兵的示例代碼

 更新時(shí)間:2022年07月04日 10:34:51   作者:我的架構(gòu)師之路  
這篇文章主要介紹了Java實(shí)現(xiàn)Redis哨兵的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言:

本文將采用文字+代碼的方式,講解redis版哨兵的實(shí)現(xiàn),所有代碼都將寫在一個(gè)類中,每個(gè)屬性和方法都會(huì)結(jié)合文字加以說明。

1. 哨兵(Sentinel)主要功能如下:

1、不時(shí)的監(jiān)控redis節(jié)點(diǎn)是否良好運(yùn)行,如果節(jié)點(diǎn)不可達(dá)就會(huì)對(duì)節(jié)點(diǎn)進(jìn)行下線標(biāo)識(shí)

2、如果被標(biāo)識(shí)的是主節(jié)點(diǎn),哨兵就會(huì)選舉一個(gè)redis從(slave)節(jié)點(diǎn)成為新的主節(jié)點(diǎn)繼續(xù)對(duì)外提供讀寫服務(wù), 進(jìn)而實(shí)現(xiàn)自動(dòng)故障轉(zhuǎn)移,保證系統(tǒng)的高可用。

3、在redis主節(jié)點(diǎn) 和 從節(jié)點(diǎn) 進(jìn)行切換后,主節(jié)點(diǎn)配置文件master_redis.conf、從節(jié)點(diǎn)配置文件slave_redis.conf都要發(fā)生改變。

2. 準(zhǔn)備工作:

  • Redis集群推薦一主兩從,共三個(gè)節(jié)點(diǎn)。
  • jedis-2.9.0.jar 客戶端框架

3. 代碼實(shí)現(xiàn)

JavaSentinel.java

package com.middleware.redis.sentinels;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.*;

/**
?* java版哨兵
?*?
?* @author 93733
?*
?*/
public class JavaSentinel {

?? ?// 主節(jié)點(diǎn)ip:端口 ? ?127.0.0.1:6379
?? ?static String masterAddress = "127.0.0.1:6379";
?? ?// 所有 slave
?? ?static final Vector<String> slaveRedisServers = new Vector<String>();
?? ?// 壞掉的實(shí)例
?? ?static final Vector<String> badRedisServers = new Vector<String>();

?? ?// 連接池對(duì)象
?? ?static JedisPool jedisPool ;

?? ?// 連接池配置信息對(duì)象
? ? private static JedisPoolConfig config = new JedisPoolConfig();

?? ?/**
?? ? * 配置連接池信息
?? ? * @return
?? ? */
?? ?static {

?? ??? ?// 最大連接數(shù)10
?? ??? ?config.setMaxTotal(10);
?? ??? ?//最大空閑連接數(shù)5
?? ??? ?config.setMaxIdle(5);

?? ?}

?? ?/**
?? ? * 獲取jedis 實(shí)例
?? ? * @param
?? ? * @return
?? ? */
?? ?public Jedis newJedisInstance() {
?? ??? ?return jedisPool.getResource() ;
?? ?}

?? ?volatile static JavaSentinel javaSentinel;

?? ?/**
?? ? * 創(chuàng)建JavaSentinel對(duì)象
?? ? * @param isOpenSentinel 是否開啟哨兵 true 開啟, false 不開啟
?? ? * @return
?? ? *
?? ? * 1) 如果開啟哨兵, 我們創(chuàng)建一個(gè)定時(shí)任務(wù), 延遲1秒,間隔3秒執(zhí)行一次
?? ? * 2)每次執(zhí)行時(shí), 任務(wù)如下:
?? ? * ? ? ? ? ? ? ?// 檢測(cè) master是否可以
?? ? * ?? ??? ??? ??? ?checkMaster();
?? ? * ?? ??? ??? ??? ?// 更新slave列表
?? ? * ?? ??? ??? ??? ?updateSlaves();
?? ? * ?? ??? ??? ??? ?// 檢測(cè)壞掉的實(shí)例是否恢復(fù)正常
?? ? * ?? ??? ??? ??? ?checkBadServer();
?? ? *
?? ? * 3)初始化 jedisPool 對(duì)象 和 javaSentinel對(duì)象
?? ? *
?? ? */

?? ?public static synchronized JavaSentinel getInstance(boolean isOpenSentinel){

?? ??? ?// 是否開啟java哨兵
?? ??? ?if(isOpenSentinel){

?? ??? ??? ?// 定時(shí)任務(wù)
?? ??? ??? ?new Timer().schedule(new TimerTask() {
?? ??? ??? ??? ?@Override
?? ??? ??? ??? ?public void run() {
?? ??? ??? ??? ??? ?// 檢測(cè) master是否可以
?? ??? ??? ??? ??? ?checkMaster();
?? ??? ??? ??? ??? ?// 更新slave列表
?? ??? ??? ??? ??? ?updateSlaves();
?? ??? ??? ??? ??? ?// 檢測(cè)壞掉的實(shí)例是否恢復(fù)正常
?? ??? ??? ??? ??? ?checkBadServer();

?? ??? ??? ??? ?}
?? ??? ??? ?}, 1000, 3000);
?? ??? ?}

?? ??? ?if(null == javaSentinel){

?? ??? ??? ?/**
?? ??? ??? ? * 初始化redis連接池對(duì)象
?? ??? ??? ? */
?? ??? ??? ?String[] serverInfo = masterAddress.split(":");
?? ??? ??? ?String masterHost = serverInfo[0] ;
?? ??? ??? ?int masterPort = Integer.parseInt(serverInfo[1]) ;
?? ??? ??? ?jedisPool = new JedisPool(config, masterHost, masterPort, 100000);

?? ??? ??? ?//初始化當(dāng)前類對(duì)象
?? ??? ??? ?javaSentinel = new JavaSentinel();
?? ??? ?}

?? ??? ?return javaSentinel;

?? ?}


?? ?/**
?? ? * 該方法通過ping 方式, 檢驗(yàn)當(dāng)前redis主節(jié)點(diǎn)是否在線
?? ? *
?? ? * 如若發(fā)生異常, 則主節(jié)點(diǎn)掛掉, 需要做如下兩步:
?? ? * 1)如果捕獲到了異常證明: ?redis節(jié)點(diǎn)掛掉, 我們需要將當(dāng)前主節(jié)點(diǎn)address保存到badRedisServers集合中
?? ? * 2)調(diào)用changeMaster() 方法,選舉從節(jié)點(diǎn)作為新的主
?? ? */
?? ?private static void checkMaster() {
?? ??? ?// 主從切換
?? ??? ?// 檢查狀態(tài)
?? ??? ?System.out.println("檢查master狀態(tài):" + masterAddress);
?? ??? ?String masterHost = masterAddress.split(":")[0];
?? ??? ?int masterPort = Integer.parseInt(masterAddress.split(":")[1]);
?? ??? ?try {
?? ??? ??? ?Jedis jedis = new Jedis(masterHost, masterPort);
?? ??? ??? ?jedis.ping();
?? ??? ??? ?jedis.close();
?? ??? ?} catch (Exception e) {
?? ??? ??? ?// master掛掉啦
?? ??? ??? ?badRedisServers.add(masterAddress);
?? ??? ??? ?// 切換master
?? ??? ??? ?changeMaster();
?? ??? ?}
?? ?}

?? ?/**
?? ? * 切換master
?? ? *
?? ? * 1) 從slaveRedisServers集合中, 獲取一個(gè)從節(jié)點(diǎn)地址
?? ? * 2)通過地址創(chuàng)建jedis對(duì)象嘗試ping動(dòng)作,驗(yàn)證器是否在線
?? ? * 3)沒發(fā)生異常,證明在線,我們需要禁用它從死掉master繼續(xù)同步數(shù)據(jù)
?? ? * 4)修改屬性masterAddress 為新選舉出來的slave地址
?? ? * 5)如果發(fā)生異常,則將當(dāng)前slave存放在badRedisServers集合中, 進(jìn)入下一次循環(huán)重試1-4 動(dòng)作
?? ? * 6)選舉成功后,將當(dāng)前slave從 slaveRedisServers集合中移除掉
?? ? *
?? ? * 7)遍歷slaveRedisServers集合,將其他從節(jié)點(diǎn) 主從復(fù)制配置更新到剛剛選舉出來的新主節(jié)點(diǎn)身上
?? ? */
?? ?private static void changeMaster() {
?? ??? ?Iterator<String> iterator = slaveRedisServers.iterator();
?? ??? ?while (iterator.hasNext()) {
?? ??? ??? ?String slaveAddress = iterator.next();
?? ??? ??? ?try {
?? ??? ??? ??? ?String slaveHost = slaveAddress.split(":")[0];
?? ??? ??? ??? ?int slavePort = Integer.parseInt(slaveAddress.split(":")[1]);
?? ??? ??? ??? ?Jedis jedis = new Jedis(slaveHost, slavePort);

?? ??? ??? ??? ?/*確保當(dāng)前從節(jié)點(diǎn)在線*/
?? ??? ??? ??? ?jedis.ping();

? ? ? ? ? ? ? ? /*禁用當(dāng)前從節(jié)點(diǎn)同步復(fù)制*/
?? ??? ??? ??? ?jedis.slaveofNoOne();
?? ??? ??? ??? ?jedis.close();
?? ??? ??? ??? ?masterAddress = slaveAddress;
?? ??? ??? ??? ?System.out.println("產(chǎn)生新的master:" + masterAddress);
?? ??? ??? ??? ?break;
?? ??? ??? ?} catch (Exception e) {
?? ??? ??? ??? ?badRedisServers.add(slaveAddress);
?? ??? ??? ?} finally {
?? ??? ??? ??? ?iterator.remove();
?? ??? ??? ?}
?? ??? ?}

?? ??? ?// 所有slave切到新的master
?? ??? ?for (String slave : slaveRedisServers) {
?? ??? ??? ?String slaveHost = slave.split(":")[0];
?? ??? ??? ?int slavePort = Integer.parseInt(slave.split(":")[1]);
?? ??? ??? ?Jedis jedis = new Jedis(slaveHost, slavePort);
?? ??? ??? ?jedis.slaveof(masterAddress.split(":")[0], Integer.parseInt(masterAddress.split(":")[1]));
?? ??? ??? ?jedis.close();
?? ??? ?}
?? ?}

?? ?/**
?? ? * 更新當(dāng)前所有從節(jié)點(diǎn)到 slaveRedisServers中
?? ? *
?? ? * 1)根據(jù)masterAddress 創(chuàng)建主節(jié)點(diǎn)Jedis對(duì)象
?? ? * 2)獲取主節(jié)點(diǎn)replication配置信息jedis.info("replication");
?? ? * 3)根據(jù)配置信息, 獲取到當(dāng)前主節(jié)點(diǎn)從節(jié)點(diǎn)個(gè)數(shù)
?? ? * 4)循環(huán)遍歷從節(jié)點(diǎn)個(gè)數(shù), 如果個(gè)數(shù)大于0, 則清空當(dāng)前 slaveRedisServers集合
?? ? * 5)從配置信息中截取出所有從節(jié)點(diǎn)的ip:端口后,放入到 slaveRedisServers集合中
?? ? *
?? ? */
?? ?private static void updateSlaves() {
?? ??? ?// 獲取所有slave
?? ??? ?try {
?? ??? ??? ?String masterHost = masterAddress.split(":")[0];
?? ??? ??? ?int masterPort = Integer.parseInt(masterAddress.split(":")[1]);
?? ??? ??? ?Jedis jedis = new Jedis(masterHost, masterPort);
?? ??? ??? ?String info_replication = jedis.info("replication");
?? ??? ??? ?// 解析info replication
?? ??? ??? ?String[] lines = info_replication.split("\r\n");
?? ??? ??? ?int slaveCount = Integer.parseInt(lines[2].split(":")[1]);
?? ??? ??? ?if (slaveCount > 0) {
?? ??? ??? ??? ?slaveRedisServers.clear();
?? ??? ??? ??? ?for (int i = 0; i < slaveCount; i++) {
?? ??? ??? ??? ??? ?String host = lines[3 + i].split(",")[0].split("=")[1];
?? ??? ??? ??? ??? ?String port = lines[3 + i].split(",")[1].split("=")[1];
?? ??? ??? ??? ??? ?slaveRedisServers.add(host + ":" + port);
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ??? ?System.out.println("更新slave列表:" + Arrays.toString(slaveRedisServers.toArray(new String[] {})));
?? ??? ??? ?jedis.close();
?? ??? ?} catch (Exception e) {
?? ??? ??? ?e.printStackTrace();
?? ??? ??? ?System.out.println("更新slave失敗:" + e.getMessage());
?? ??? ?}
?? ?}


?? ?/**
?? ? * 檢測(cè)壞掉的實(shí)例是否恢復(fù)正常
?? ? * 1)如果調(diào)用 pint() 沒有發(fā)生異常, 證明恢復(fù)正常
?? ? * 2)恢復(fù)正常后,先將當(dāng)前節(jié)點(diǎn)主從復(fù)制的配置通過slaveof() 掛載當(dāng)前節(jié)點(diǎn)上
?? ? * 3)將當(dāng)前節(jié)點(diǎn)地址從 badRedisServers集合中remove()掉, 并添加到 slaveRedisServers集合中。
?? ? *?
?? ? */
?? ?private static void checkBadServer() {
?? ??? ?// 獲取所有slave
?? ??? ?Iterator<String> iterator = badRedisServers.iterator();
?? ??? ?while (iterator.hasNext()) {
?? ??? ??? ?String bad = iterator.next();
?? ??? ??? ?try {
?? ??? ??? ??? ?String badHost = bad.split(":")[0];
?? ??? ??? ??? ?int badPort = Integer.parseInt(bad.split(":")[1]);
?? ??? ??? ??? ?Jedis badServer = new Jedis(badHost, badPort);
?? ??? ??? ??? ?badServer.ping();

?? ??? ??? ??? ?// 如果ping沒有問題,則掛在當(dāng)前的master
?? ??? ??? ??? ?badServer.slaveof(masterAddress.split(":")[0], Integer.parseInt(masterAddress.split(":")[1]));
?? ??? ??? ??? ?badServer.close();

?? ??? ??? ??? ?slaveRedisServers.add(bad);
?? ??? ??? ??? ?iterator.remove();
?? ??? ??? ??? ?System.out.println(bad + " 恢復(fù)正常,當(dāng)前master:" + masterAddress);
?? ??? ??? ?} catch (Exception e) {
?? ??? ??? ?}
?? ??? ?}
?? ?}
}

到此這篇關(guān)于Java實(shí)現(xiàn)Redis哨兵的示例代碼的文章就介紹到這了,更多相關(guān)Java Redis哨兵內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Hadoop運(yùn)行時(shí)遇到j(luò)ava.io.FileNotFoundException錯(cuò)誤的解決方法

    Hadoop運(yùn)行時(shí)遇到j(luò)ava.io.FileNotFoundException錯(cuò)誤的解決方法

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識(shí),文章圍繞著Hadoop運(yùn)行時(shí)遇到j(luò)ava.io.FileNotFoundException錯(cuò)誤展開,文中有非常詳細(xì)的解決方法,需要的朋友可以參考下
    2021-06-06
  • Java日期轉(zhuǎn)換注解配置date?format時(shí)間失效

    Java日期轉(zhuǎn)換注解配置date?format時(shí)間失效

    這篇文章主要為大家介紹了Java日期轉(zhuǎn)換注解配置date?format時(shí)間失效,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Java中HashMap與String字符串互轉(zhuǎn)的問題解決

    Java中HashMap與String字符串互轉(zhuǎn)的問題解決

    本文介紹了Java中HashMap與String字符串互轉(zhuǎn)的問題解決,當(dāng)我們有需求將HashMap轉(zhuǎn)為Json格式的String時(shí),需要使用FastJson/Gson將HashMap轉(zhuǎn)為String,感興趣的可以了解一下
    2022-03-03
  • Java實(shí)現(xiàn)替換Word中文本和圖片功能

    Java實(shí)現(xiàn)替換Word中文本和圖片功能

    Word中的替換功能以查找指定文本然后替換為新的文本,可單個(gè)替換或全部替換。本文將用Java語言實(shí)現(xiàn)Word中的文本、圖片替換功能,需要的可以參考一下
    2022-06-06
  • 手把手教你如何在Idea中下載jar包

    手把手教你如何在Idea中下載jar包

    maven依賴的jar包,很多時(shí)候同一個(gè)jar包會(huì)存在多個(gè)版本,刪除其中一個(gè)后,重新編譯,會(huì)把舊jar由加載回來了,下面這篇文章主要給大家介紹了關(guān)于如何在Idea中下載jar包的相關(guān)資料,需要的朋友可以參考下
    2023-06-06
  • Java 找不到或無法加載主類的修復(fù)方法

    Java 找不到或無法加載主類的修復(fù)方法

    這篇文章主要介紹了Java 找不到或無法加載主類的修復(fù)方法,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2021-02-02
  • JAVA時(shí)間存儲(chǔ)類Period和Duration使用詳解

    JAVA時(shí)間存儲(chǔ)類Period和Duration使用詳解

    這篇文章主要為大家介紹了JAVA時(shí)間存儲(chǔ)類Period和Duration使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • java理論基礎(chǔ)Stream元素的匹配與查找

    java理論基礎(chǔ)Stream元素的匹配與查找

    這篇文章主要為大家介紹了java理論基礎(chǔ)Stream元素的匹配與查找方法的示例說明解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • SpringBoot如何通過@Profile注解配置多環(huán)境

    SpringBoot如何通過@Profile注解配置多環(huán)境

    在Spring中,可以使用配置文件的方式來指定不同環(huán)境下所需要的配置信息,本文給大家介紹SpringBoot如何通過@Profile注解配置多環(huán)境,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • SpringBoot 緩存 Caffeine使用解析

    SpringBoot 緩存 Caffeine使用解析

    這篇文章主要介紹了SpringBoot 緩存 Caffeine使用解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09

最新評(píng)論