在 《 Docker下redis与springboot三部曲之二:安装redis主从和哨兵》 一文中,我们在docker下搭建了redis主从和哨兵,本章我们开发一个基于springboot的web工程,体验springboot下如何使用redis高可用服务;
原文地址: http://blog.csdn.net/boling_cavalry/article/details/79041129
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
我们先回顾一下docker-compose.yml的内容,看看已经准备好哪些服务了:
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工程源码我已上传到github,地址是:git@github.com:zq2599/blog_demos.git,或者用浏览器访问: https://github.com/zq2599/blog_demos ,这里面有多个工程,本次实战的工程是redissentineldemo,如下图红框所示:
本次实战的web工程是基于maven构建的,pom.xml的内容与通常的spring boot工程一样,只有依赖库新增以下内容:
<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的内容如下:
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,代码如下:
@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”对应的值,如下所示:
root@362d09f7fee9:/data# redis-cli 127.0.0.1:6379> get name "tom111112333666777" 127.0.0.1:6379>
可见从库已经同步到了主库写入的数据;
前面的实战我们是直接连接到redis的master,并未体验到哨兵带来的高可用能力,现在我们来试试连接到哨兵,这样当master有问题时,如果slave成了新的master,应用程序不需要任何改动,通过哨兵就能自动连接到新的master;
从连接到master改为连接到哨兵的改动很简单,只需要修改配置文件即可,修改后的application.properties的内容如下:
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服务器上检查,发现数据成功更新;
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的!
至此,《Docker下redis与springboot三部曲》系列实战就全部完成了,希望能帮助你熟悉和了解redis的一些特性,以及基本的java调用redis服务的操作。