目录
3.2.3.1 人为模拟master-6383宕机,手动shutdown。此时在集群内部可以正常添加数据,而且从机6384slave成功上位编辑
3.2.3.2 用微服务测试,出现 Command timed out after 1 minute(s)的错误
1. 集成Jedis(单机版)
1.1 是什么
Jedis Client 是Redis官网推荐的一个面向Java客户端,库文件实现了对各类API进行封装调用。
1.2 步骤
- 建Module
略~ - 改POM
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>${jedis.version}</version> </dependency>
- 写YML
spring.application.name=springBoot_Redis server.port=8080
- 主启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootRedisApplication { public static void main(String[] args) { SpringApplication.run(SpringBootRedisApplication.class, args); } }
- 业务类
import redis.clients.jedis.Jedis; public class JedisDemo { public static void main(String[] args) { Jedis jedis = new Jedis("192.168.217.146", 6379); jedis.auth("Beijing@123"); System.out.println(jedis.ping()); } }
2. 集成lettuce(单机版)
2.1 lettuce 和 Jedis 的区别
他们都是redis的客户端,都可以连接redis,但是在SpingBoot2.0之后默认都是使用Lettuce这个客户端链接redis服务器。因为当使用Jedis客户端连接redis服务器的时候,每个线程都要拿自己创建的Jedis实例去连接Redis客户端,当有多个线程的时候,不仅开销大需要反复的创建关闭一个Jedis连接,而且也是线程不安全的,一个线程通过Jedis实例更改Redis服务器中的数据之后会影响另一个线程;但是如果使用Lettuce这个客户端连接Redis服务器的时候,就不会出现上面的情况,Lettuce底层使用的是Netty,当有多个线程都需要连接Redis服务器的时候,可以保证只创建一个Lettuce连接,使所有的线程共享一个Lettuce连接,这样可以减少创建关闭一个Lettuce连接时候的开销;而且这种方式也是线程安全的,不会出现一个线程通过Lettuce更改Redis服务器中的数据之后而影响另一个线程的情况;
2.2步骤
- 改POM
<dependency> <groupId>io.lettuce</groupId> <artifactId>lettuce-core</artifactId> <version>6.2.1.RELEASE</version> </dependency>
- 业务类
import io.lettuce.core.RedisClient; import io.lettuce.core.RedisURI; import io.lettuce.core.api.StatefulRedisConnection; import io.lettuce.core.api.sync.RedisCommands; import java.util.List; public class lettuceDemo { public static void main(String[] args) { //1 使用构建器 链式编程来来builder我们的RedisURI RedisURI uri = RedisURI.Builder.redis("192.168.217.146") .withPort(6379) .withAuthentication("default","Beijing@123") .build(); //2 创建连接客户端 RedisClient redisClient = RedisClient.create(uri); StatefulRedisConnection connect = redisClient.connect(); //3 通过connect创建操作的command RedisCommands commands = connect.sync(); //==================================== // commands.set("k11","v11"); List keys = commands.keys("*"); System.out.println(keys); //==================================== //4 各种关闭,释放资源 connect.close(); redisClient.shutdown(); } }
3. 集成RedisTemplate
3.1 连接单机
- 建Module
略 - 改POM
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency>
- 写YML
spring.application.name=springBoot_Redis server.port=8080 #=====================redis单机================= spring.redis.database=0 spring.redis.host=192.168.217.151 spring.redis.port=6379 spring.redis.password=Beijing@123 spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=1ms spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.min-idle=0
- 主启动类
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootRedisApplication { public static void main(String[] args) { SpringApplication.run(SpringBootRedisApplication.class, args); } }
- 业务类
import com.dylan.springBoot_Redis.service.OrderService; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @RestController public class OrderConntroller { @Resource private OrderService orderService; @GetMapping(value = "/order/add") public void addOrder(){ orderService.addOrder(); } @GetMapping(value = "/order/{keyId}") public void getOrderById(@PathVariable String keyId){ orderService.getOrder(keyId); } }
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; @Service public class OrderService { @Resource public StringRedisTemplate stringRedisTemplate; public static final String ORDER_KEY = "ord:"; public void addOrder(){ int keyId = ThreadLocalRandom.current().nextInt(1000)+1; String seriaNo = UUID.randomUUID().toString(); String key = ORDER_KEY+keyId; String value = "京东订单"+seriaNo; stringRedisTemplate.opsForValue().set(key,value); System.out.println("key:"+key); System.out.println("value:"+value); } public String getOrder(String key){ return stringRedisTemplate.opsForValue().get(key); } }
- 测试
插入中文有乱码问题,其他正常。
连接Redis,如果有中文的话要在登录客户端命令的时候加 --raw命令
redis-cli -a password -p 6379 --raw
3.1.1 序列化问题
由上面 6.测试 可知会存在乱码的序列化问题。
查看源码得知:
3.2 连接集群 (微服务代码不做任何改变)
3.2.1 改YML
#=====================redis集群=================
spring.redis.password=Beijing@123
#获取失败,最大重定向次数
spring.redis.cluster.max-redirects=3
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=1ms
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0
spring.redis.cluster.nodes=192.168.217.135:6381,192.168.217.134:6382,192.168.217.140:6383,192.168.217.136:6384,192.168.217.138:6385,192.168.217.137:6386
3.2.2 正常测试
可以正常添加和查询。
3.2.3 测试其中一个台master宕机
3.2.3.1 人为模拟master-6383宕机,手动shutdown。
此时在集群内部可以正常添加数据,而且从机6384slave成功上位

3.2.3.2 用微服务测试,出现 Command timed out after 1 minute(s)的错误
原因是:springBoot 客户端没有动态感知RedisCluster的最新集群状态。springBoot2.X版本,Redis默认使用Lettuce。当Redis集群节点发生变化后,Lettuce默认是不会刷新节点拓扑。
需要修改YML文件,增加下面2条配置:
#支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用有可能的更新,默认false关闭 spring.redis.lettuce.cluster.refresh.adaptive=true
#定时刷新
spring.redis.lettuce.cluster.refresh.period=2000