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
在这里插入图片描述

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版本:

        
            org.springframework.boot
            spring-boot-starter-data-redis
        

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 redisTemplate(){
        RedisTemplate  template = new RedisTemplate ();
        //设置开启事务
        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 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

以上内容纯属原创,有些地方也是参考了网上不少教程;这篇文章纯属技术分享,不以任何盈利为目的,如果有侵权的地方,请私信我,我将会进行调整,谢谢!

你可能感兴趣的:(Redis)