Docker下redis与springboot三部曲之三:springboot下访问redis哨兵

2022-05-06 13:36:29 浏览数 (1)

在《 Docker下redis与springboot三部曲之二:安装redis主从和哨兵》一文中,我们在docker下搭建了redis主从和哨兵,本章我们开发一个基于springboot的web工程,体验springboot下如何使用redis高可用服务;

原文地址:http://blog.csdn.net/boling_cavalry/article/details/79041129

实战环境

  1. 本次实战的环境是Ubuntu16,安装的Docker版本是17.03.2-ce;
  2. 本次开发web工程的ide推荐使用IntelliJ IDEA;
  3. 本次实战用到的redis服务,在上一次实战中已经搭建完成,详情请参照在《 Docker下redis与springboot三部曲之二:安装redis主从和哨兵》;
  4. 哨兵的数量为三个,由于之前已经配置了QUORUM=2,如果哨兵只有一个,在master出了问题重新选举master的时候,会因为投票数不够一半导致选举失败,无法将slave切换为master;
  5. 容器运行情况如下:
代码语言:javascript复制
root@rabbitmq:/usr/local/work/blog# docker ps
CONTAINER ID        IMAGE                                COMMAND                  CREATED              STATUS              PORTS                    NAMES
39369dd41b45        bolingcavalry/redis3sentinel:0.0.1   "sentinel-entrypoi..."   About a minute ago   Up About a minute   6379/tcp, 26379/tcp      blog_sentinel_2
2c319d8cd473        bolingcavalry/redis3sentinel:0.0.1   "sentinel-entrypoi..."   About a minute ago   Up About a minute   6379/tcp, 26379/tcp      blog_sentinel_3
9c2ddac0d1fb        redis:3                              "docker-entrypoint..."   About a minute ago   Up About a minute   6379/tcp                 blog_slave_2
d6fbcf0db3fd        bolingcavalry/springbootrun:0.0.1    "/bin/bash"              2 minutes ago        Up 2 minutes        0.0.0.0:8080->8080/tcp   blog_java_1
5f889da820a1        bolingcavalry/redis3sentinel:0.0.1   "sentinel-entrypoi..."   2 minutes ago        Up 2 minutes        6379/tcp, 26379/tcp      blog_sentinel_1
b54d6373a65e        redis:3                              "docker-entrypoint..."   2 minutes ago        Up 2 minutes        6379/tcp                 blog_slave_1
2b7b3b80af56        redis:3                              "docker-entrypoint..."   2 minutes ago        Up 2 minutes        6379/tcp                 blog_master_1
73b4044c420d        redis:3                              "docker-entrypoint..."   2 minutes ago        Up 2 minutes        6379/tcp                 blog_client_1

redis环境

我们先回顾一下docker-compose.yml的内容,看看已经准备好哪些服务了:

代码语言:javascript复制
master:
  image: redis:3
  ports:
    - "6379:6379"
slave:
  image: redis:3
  command: redis-server --slaveof redis-master 6379
  links:
    - master:redis-master
sentinel:
  image: bolingcavalry/redis3sentinel:0.0.1
  environment:
    - SENTINEL_DOWN_AFTER=5000
    - SENTINEL_FAILOVER=5000    
  links:
    - master:redis-master
    - slave
  ports:
    - "26379:26379"
java:
  image: bolingcavalry/springbootrun:0.0.1
  links:
    - sentinel:redis-sentinel
    - master:redis-master
  volumes:
     - /usr/local/work/share:/usr/Downloads
  ports:
    - "8080:8080"
  tty:true
client:
  image: redis:3

上面的java服务有以下几点请注意:

  1. 这个服务已经配置了两个link参数,由此在这个容器中redis-sentinel就代表了哨兵的地址,redis-master就代表了master的地址(/etc/hosts的配置效果);
  2. 使用的镜像是bolingcavalry/springbootrun:0.0.1,这是我做的镜像,功能非常简单:装了JDK,暴露了8080端口,详情请看《Docker下运行springboot》;
  3. 容器的/usr/local/work/share与当前电脑的/usr/Downloads目录已建立映射关系,把文件放到/usr/Downloads目录,就相当于把文件放入了容器的/usr/local/work/share目录;
  4. 容器的8080端口与当前电脑的8080端口绑定;
  5. 使用tty参数分配终端,否则容器启动后会立即退出;

web工程源码

web工程源码我已上传到github,地址是:git@github.com:zq2599/blog_demos.git,或者用浏览器访问:https://github.com/zq2599/blog_demos,这里面有多个工程,本次实战的工程是redissentineldemo,如下图红框所示:

pom.xml

本次实战的web工程是基于maven构建的,pom.xml的内容与通常的spring boot工程一样,只有依赖库新增以下内容:

代码语言:javascript复制
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>

如上所示,增加了spring-boot-starter-data-redis;

application.properties(连接master)

配置文件application.properties的内容如下:

代码语言:javascript复制
spring.redis.database=0
spring.redis.host=redis-master
spring.redis.port=6379
spring.redis.pool.max-active=2500
spring.redis.pool.max-wait=6000
spring.redis.pool.max-idle=500
spring.redis.pool.min-idle=100
spring.redis.pool.testOnBorrow=true
spring.redis.pool.blockWhenExhausted=true
spring.redis.pool.numTestsPerEvictionRun=3
spring.redis.pool.timeBetweenEvictionRunsMillis=-1
spring.redis.timeout=100

spring.redis.host和spring.redis.port表明这个配置文件是直接连接master库的;

源码

在springboot下操作redis的步骤很简单,这里做了一个controller来验证写redis,代码如下:

代码语言:javascript复制
@RestController
public class MockController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping(value = "/testredis/{key}/{value}", method = RequestMethod.GET)
    @ResponseBody
    public String testRedis(@PathVariable("key") final String key, @PathVariable("value") final String value) {
        try{
            stringRedisTemplate.opsForValue().set(key, value);
        }catch(Exception e){
            e.printStackTrace();
        }
        return "1. success";
    }
}

如上所示,spring环境会根据配置信息来初始化StringRedisTemplate对象,我们只要通过@Autowire注解配置就能直接使用了;

验证

  • 将上述工程打包成jar,放入blog_java_1容器(之前提到过文件夹映射的),再执行命令java -jar redissentineldemo-0.0.1-SNAPSHOT.jar启动服务;
  • 我当前电脑的IP是192.168.119.155,所以在浏览器访问:http://192.168.119.155:8080/testredis/name/tom111112333666777,浏览器会显示"“1. success”,此时controller会在redis中写入key为"name",value为"tom111112333666777"的一条记录;
  • 执行命令docker exec -it blog_slave_1 /bin/bash进入slave的容器,查看"name"对应的值,如下所示:
代码语言:javascript复制
root@362d09f7fee9:/data# redis-cli
127.0.0.1:6379> get name
"tom111112333666777"
127.0.0.1:6379>

可见从库已经同步到了主库写入的数据;

web工程连接到哨兵

前面的实战我们是直接连接到redis的master,并未体验到哨兵带来的高可用能力,现在我们来试试连接到哨兵,这样当master有问题时,如果slave成了新的master,应用程序不需要任何改动,通过哨兵就能自动连接到新的master;

application.properties(连接哨兵)

从连接到master改为连接到哨兵的改动很简单,只需要修改配置文件即可,修改后的application.properties的内容如下:

代码语言:javascript复制
spring.redis.database=0
#spring.redis.host=redis-master
#spring.redis.port=6379
spring.redis.pool.max-active=2500
spring.redis.pool.max-wait=6000
spring.redis.pool.max-idle=500
spring.redis.pool.min-idle=100
spring.redis.pool.testOnBorrow=true
spring.redis.pool.blockWhenExhausted=true
spring.redis.pool.numTestsPerEvictionRun=3
spring.redis.pool.timeBetweenEvictionRunsMillis=-1
spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=redis-sentinel:26379
spring.redis.timeout=1000

可见spring.redis.host和spring.redis.port这两个配置被注释掉,然后新增了spring.redis.sentinel.master和spring.redis.sentinel.nodes,“redis-sentinel”是link参数,可以连接到哨兵的机器;

以上就是所有改动,重新打包复制到blog_java_1容器,启动后在浏览器发起一次请求,然后去redis服务器上检查,发现数据成功更新;

验证高可用

  • 执行命令令docker stop blog_master_1停止master容器,再docker logs -f blog_sentinel_1命令查看哨兵日志,可以发现slave已经切换成了master,如下:
代码语言:javascript复制
root@rabbitmq:~# docker stop blog_master_1
blog_master_1
root@rabbitmq:/usr/local/work/blog# docker logs -f blog_sentinel_1
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 3.2.11 (00000000/0) 64 bit
  .-`` .-```.  ```/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in sentinel mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
 |    `-._   `._    /     _.-'    |     PID: 1
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

1:X 12 Jan 12:31:46.811 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
1:X 12 Jan 12:31:46.812 # Sentinel ID is 43a5934ce2c884b268e40cfbb3d3e14bb3d7bac3
1:X 12 Jan 12:31:46.812 #  monitor master mymaster 172.17.0.3 6379 quorum 2
1:X 12 Jan 12:31:46.812 *  slave slave 172.17.0.4:6379 172.17.0.4 6379 @ mymaster 172.17.0.3 6379
1:X 12 Jan 12:31:56.923 *  fix-slave-config slave 172.17.0.4:6379 172.17.0.4 6379 @ mymaster 172.17.0.3 6379
1:X 12 Jan 12:32:13.463 *  sentinel sentinel 6f85d8262413edc32ce2a996cbbaf6d8bfc27563 172.17.0.8 26379 @ mymaster 172.17.0.3 6379
1:X 12 Jan 12:32:13.469 *  sentinel sentinel ba786641ce23a03f0d6cff8885d6315edf025d43 172.17.0.7 26379 @ mymaster 172.17.0.3 6379
1:X 12 Jan 12:32:16.886 *  slave slave 172.17.0.9:6379 172.17.0.9 6379 @ mymaster 172.17.0.3 6379
1:X 12 Jan 12:32:26.997 *  fix-slave-config slave 172.17.0.9:6379 172.17.0.9 6379 @ mymaster 172.17.0.3 6379
1:X 12 Jan 12:35:28.735 #  sdown master mymaster 172.17.0.3 6379
1:X 12 Jan 12:35:28.805 #  new-epoch 1
1:X 12 Jan 12:35:28.805 #  vote-for-leader 6f85d8262413edc32ce2a996cbbaf6d8bfc27563 1
1:X 12 Jan 12:35:29.812 #  odown master mymaster 172.17.0.3 6379 #quorum 3/2
1:X 12 Jan 12:35:29.812 # Next failover delay: I will not start a failover before Fri Jan 12 12:35:39 2018
1:X 12 Jan 12:35:30.004 #  config-update-from sentinel 6f85d8262413edc32ce2a996cbbaf6d8bfc27563 172.17.0.8 26379 @ mymaster 172.17.0.3 6379
1:X 12 Jan 12:35:30.004 #  switch-master mymaster 172.17.0.3 6379 172.17.0.4 6379
1:X 12 Jan 12:35:30.004 *  slave slave 172.17.0.9:6379 172.17.0.9 6379 @ mymaster 172.17.0.4 6379
1:X 12 Jan 12:35:30.004 *  slave slave 172.17.0.3:6379 172.17.0.3 6379 @ mymaster 172.17.0.4 6379
1:X 12 Jan 12:35:35.025 #  sdown slave 172.17.0.3:6379 172.17.0.3 6379 @ mymaster 172.17.0.4 6379

如上日志所示,“ new-epoch 1”表示发起了新的选举,“ odown master mymaster 172.17.0.3 6379 #quorum 3/2”表示投票超过了一半,选举成功,slave被选为master;

这里要注意的是,quorum参数在conf中被我们配置成了2,所以这里要有三个哨兵才能投票通过,如果您没有执行命令docker-compose scale sentinel=3将哨兵数量扩展为3,slave是不会切换成master的!

  • 像前面的验证方式一样,在浏览器发起一次请求(http://192.168.119.155:8080/testredis/name/aaabbbccc),然后去slave服务器上执行redis-cli进入控制台检查key为"name"的值,发现数据成功更新为"aaabbbccc";

至此,《Docker下redis与springboot三部曲》系列实战就全部完成了,希望能帮助你熟悉和了解redis的一些特性,以及基本的java调用redis服务的操作。

0 人点赞