天天看點

Redis Sentinel叢集搭建(哨兵模式,采用Docker Compose搭建)與SpringBoot內建(從0開始搭建)

一、Redisr Sentinel叢集搭建

在linux環境下,使用docker compose安裝redis sentinel叢集的搭建,需要準備的工作:

1.1安裝docker

•下載下傳安裝docker:yum -y install docker

•啟動docker服務:service docker start

•檢查docker是否安裝成功:docker version

1.2安裝docker compose

•安裝指令:sudo pip install -U docker-compose

如果在安裝的過程中,出現連接配接逾時的報錯提示,可以使用如下指令解決:

•pip --default-timeout=100 install -U Pillow,如果未出現報錯,則無需使用該指令

1.3安裝redis鏡像

•安裝指令:docker pull redis

•檢視安裝是否成功指令:docker images

Redis Sentinel叢集搭建(哨兵模式,采用Docker Compose搭建)與SpringBoot內建(從0開始搭建)

1.4在/usr/local/目錄下建立redis-docker檔案夾

•指令:mkdir redis-docker

在redis-docker目錄下建立redis目錄

•指令:mkdir redis

在redis檔案夾下建立docker-compose.yml檔案,實作redis一主二從,編寫内容:

redis不加密的配置方式:

version: '3'
services:
  master:
    image: redis
    container_name: redis-sentinel-master
    ports:
      - 6379:6379
    volumes:
      - ./data:/redisdata
   
  slave1:
    image: redis
    container_name: redis-sentinel-slave-1
    ports:
      - 6380:6379
    command: redis-server --slaveof redis-sentinel-master 6379
    volumes:
      - ./data:/redisdata

  slave2:
    image: redis
    container_name: redis-sentinel-slave-2
    ports:
      - 6381:6379
    command: redis-server --slaveof redis-sentinel-master 6379
    volumes:
      - ./data:/redisdata
           

redis加密的配置方式:

version: '3'
services:
  master:
    image: redis
    container_name: redis-sentinel-master
    command: redis-server --requirepass 123456
    ports:
      - 6379:6379
    volumes:
      - ./data:/redisdata

  slave1:
    image: redis
    container_name: redis-sentinel-slave-1
    ports:
      - 6380:6379
    command: redis-server --slaveof redis-sentinel-master 6379 --requirepass 123456 --masterauth 123456
    volumes:
      - ./data:/redisdata

  slave2:
    image: redis
    container_name: redis-sentinel-slave-2
    ports:
      - 6381:6379
    command: redis-server --slaveof redis-sentinel-master 6379 --requirepass 123456 --masterauth 123456
    volumes:
      - ./data:/redisdata
           

主節點的端口,最好和redis的預設端口,即6379保持一緻

•啟動redis,使用如下指令 挂在背景:docker-compose up -d

•如果使用失敗了,可以使用如下指令檢視日志,觀察是什麼原因造成的:

docker logs -f 容器Id

•停止redis:docker-compose down

或者

docker stop 容器Id

docker rm 容器Id

•進入主redis容器中,使用如下指令:docker exec -it 容器Id bash

•重新開機docker:systemctl restart docker

•檢視docker叢集狀态:docker ps -a

如果修改過redis節點的端口和ip,一定要重新開機docker鏡像

1.5在redis-docker檔案夾下建立sentinel檔案

•指令:mkdir redis-docker

在redis-docker目錄下,編寫docker-compose.yml,編寫内容:

version: '3'
services:
  sentinel1:
    image: redis
    container_name: redis-sentinel-sentinel1
    ports:
      - 26379:26379
    command: redis-sentinel /usr/local/redis-docker/sentinel/sentinel.conf
    volumes:
      - ./sentinel1.conf:/usr/local/redis-docker/sentinel/sentinel.conf

  sentinel2:
    image: redis
    container_name: redis-sentinel-sentinel2
    ports:
      - 26380:26379
    command: redis-sentinel /usr/local/redis-docker/sentinel/sentinel.conf
    volumes:
      - ./sentinel2.conf:/usr/local/redis-docker/sentinel/sentinel.conf

  sentinel3:
    image: redis
    container_name: redis-sentinel-sentinel3
    ports:
      - 26381:26379
    command: redis-sentinel /usr/local/redis-docker/sentinel/sentinel.conf
    volumes:
      - ./sentinel3.conf:/usr/local/redis-docker/sentinel/sentinel.conf
           

1.6在redis-docker檔案夾下編寫sentinel.conf檔案

sentinel.conf内容如下:

port 26379
dir /tmp
# 自定義叢集名,其中 192.168.1.110 為 redis-master 的 ip,6379 為 redis-master 的端口,2 為最小投票數(因為有 3 台 Sentinel 是以可以設定成 2),我自己設定的主節點的ip為所在伺服器的ip
sentinel monitor mymaster 192.168.1.110 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
           

執行如下指令,複制3份redis-sentinel配置檔案

cp sentinel.conf sentinel1.conf
cp sentinel.conf sentinel2.conf
cp sentinel.conf sentinel3.conf
           

•啟動redis-sentinel:docker-compose up -d

•檢視redis-sentinel是否啟動狀态:docker-compose ps

•執行如下指令,檢視從redis資訊是否正常:sentinel slaves mymaster

•執行如下指令,檢視redis主節點資訊:sentinel master mymaster

名詞 描述
version docker檔案的版本
image 指定容器鏡像就是之前拉取的redis鏡像
container_name 給這個鏡像起一個别名
restart always:表名開機自啟動
command 相當于執行一些指令 (–requirepass 指定redis密碼 --appendonly yes 這個指令是用于開啟redis資料持久化)
ports 端口映射,将容器的端口映射到對應主控端的端口
volumes 資料卷的映射.因為一旦容器停止了那麼裡面的資料也沒有.是以我們需要把這個資料檔案放在外面,然後映射到容器中

二、後端代碼中application.yml檔案中的配置

#Redis叢集哨兵模式
redisSentinel:
   sentinelMaster: 192.168.1.110
   masterName: mymaster
   sentinelNodes: 192.168.1.110:26379,192.168.1.110:26380,192.168.1.110:26381
   sentinelPort: 6379
   maxIdle: 300
   maxTotal: 1000
   maxWaitMills: 1000
   minEvictableIdleTimeMillis: 300000
   numTestPerEvictionRun: 1024
   timeBetweenEvictionRunMillis: 30000
   testOnBorrow: true
   testWhileIdle: true
           

哨兵模式下,redis叢集相對來說特殊點,這種配置下,後端代碼直接監控并連接配接哨兵節點資訊,并不直接連接配接主節點;是以masterName和sentinel.conf配置檔案中mymaster保持一緻,否則後端會報錯,這是我的了解,如果有不對的地方;sentinelMaster這個參數,可以不配置。

三、後端代碼demo示例

3.1.pom檔案添加依賴,我使用的是jedis1.8.6版本:

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

3.2建立redis叢集連接配接池配置RedisSentinelPoolConfig.java

/**
 * @Description:redis叢集哨兵模式下,用于初始化連接配接池
 * @Date: 2019/8/10 15:44
 */
@Configuration
public class RedisSentinelPoolConfig {

    @Value("${redisSentinel.maxIdle}")
    private Integer maxIdle;

    @Value("${redisSentinel.maxTotal}")
    private Integer maxTotal;

    @Value("${redisSentinel.maxWaitMills}")
    private Integer maxWaitMills;

    @Value("${redisSentinel.minEvictableIdleTimeMillis}")
    private Integer minEvictableIdleTimeMillis;

    @Value("${redisSentinel.numTestPerEvictionRun}")
    private Integer numTestPerEvictionRun;

    @Value("${redisSentinel.timeBetweenEvictionRunMillis}")
    private long timeBetweenEvictionRunMillis;

    @Value("${redisSentinel.testOnBorrow}")
    private boolean testOnBorrow;

    @Value("${redisSentinel.testWhileIdle}")
    private boolean testWhileIdle;

    @Value("${redisSentinel.sentinelMaster}")
    private String sentinelMaster;

    @Value("${redisSentinel.masterName}")
    private String masterName;

    @Value("${redisSentinel.sentinelNodes}")
    private String sentinelNodes;

    @Value("${redisSentinel.sentinelPort}")
    private String sentinelPort;

    /*
    * 初始化JedisPoolConfig連接配接池到spring容器内
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
        //最大空閑數
        jedisPoolConfig.setMaxIdle(maxIdle*10);
        //連接配接池的最大資料庫連接配接數
        jedisPoolConfig.setMaxTotal(maxTotal*10);
        //最大建立連接配接等待時間
        jedisPoolConfig.setMaxWaitMillis(maxWaitMills*10);
        //逐出連接配接的最小空閑時間預設1800000毫秒(30分鐘)
        jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        //每次逐出檢查時,逐出的最大數目,如果為負數就是1/abs(n),預設為3
        jedisPoolConfig.setNumTestsPerEvictionRun(numTestPerEvictionRun);
        //逐出掃描的時間間隔(毫秒),如果為負數,則不運作逐出線程,預設為-1
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunMillis);
        //是否從連接配接池中取出連接配接前進行檢驗,如果檢驗失敗,則嘗試從池中取出另一個
        jedisPoolConfig.setTestOnBorrow(testOnBorrow);
        //在空閑時檢查有效性,預設為false
        jedisPoolConfig.setTestWhileIdle(testWhileIdle);
        return jedisPoolConfig;
    }

    /*
    * 初始化叢集節點到spring容器内
     */
    @Bean
    public RedisSentinelConfiguration redisSentinelConfiguration(){
        RedisSentinelConfiguration configuration=new RedisSentinelConfiguration();
        String[] host=sentinelNodes.split(Constants.COMMA);
        for(String redisHost:host){
            String[] item=redisHost.split(Constants.COLON);
            String ip=item[0];
            String port=item[1];
            configuration.addSentinel(new RedisNode(ip,Integer.parseInt(port)));
        }
        configuration.setMaster(masterName);
        return configuration;

    }


}
           

3.3建立redis配置RedisConfiguration.java

/**
 * redis配置
 *
 * @create 2018/8/10 17:25
 */
@Configuration
@EnableCaching
public class RedisConfiguration extends CachingConfigurerSupport {

    @Autowired
    private JedisPoolConfig jedisPoolConfig;

    @Autowired
    private RedisSentinelConfiguration redisSentinelConfiguration;

    @Bean
    public JedisConnectionFactory jedisConnectionFactory(){
        JedisConnectionFactory jedisConnectionFactory=new JedisConnectionFactory(redisSentinelConfiguration,jedisPoolConfig);
        //如果redis沒設定密碼,就不要傳參數,否則會報錯
        // jedisConnectionFactory.setPassword(redisPassword);
        return jedisConnectionFactory;
    }


    @Bean
    public RedisTemplate<String,Object> redisTemplate(){
        RedisTemplate<String,Object>  template = new RedisTemplate<String,Object> ();
        //設定開啟事務
        template.setEnableTransactionSupport(true);
        //設定key序列化
        StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setConnectionFactory(jedisConnectionFactory());
        template.afterPropertiesSet();
        return template;

    }

    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        //rcm.setDefaultExpiration(60);
        return rcm;
    }

}
           

3.4建立RedisSentinelTemplate.java,用于後端代碼操作redis庫

/**
 * @Description:redis叢集哨兵模式下,用于操作redis庫
 * @Date: 2019/8/10 15:44
 */
@Component
public class RedisSentinelTemplate {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    public void set(String key ,Object value){
        redisTemplate.opsForValue().set(key,value);
    }

    public void set(String key, Object obj, Long expiration) {
        redisTemplate.opsForValue().set(key, obj, expiration, TimeUnit.SECONDS);
    }

    public Object get(String key) {
        return  redisTemplate.opsForValue().get(key);
    }

}

           

然後在業務子產品注入RedisSentinelTemplate對象,即可進行資料的增删改查

在這裡有一篇文章,寫的也是這種搭建方式,寫的也很不錯,大家可以參考下

1: https://www.cnblogs.com/hckblogs/p/11186311.html

以上内容純屬原創,有些地方也是參考了網上不少教程;這篇文章純屬技術分享,不以任何盈利為目的,如果有侵權的地方,請私信我,我将會進行調整,謝謝!

繼續閱讀