总体概述
jedis-lettuce-RedisTemplate三者的联系
本地Java连接Redis常见问题
● bind配置请注释掉
● 保护模式设置为no
● Linux系统的防火墙设置
● Redis服务器的IP地址和密码是否正确
● 忘记写Redis的服务端口号和auth密码
1、集成Jedis
是什么
Jedis Client是Redis官网推荐的一个面向Java客户端,库文件实现了对各类API进行封装调用
改POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.atguigu</groupId>
<artifactId>redis7</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version>
</dependency>
</dependencies>
</project>
案例
public class jedisDemo {
public static void main(String[] args) {
//获取连接
Jedis jedis = new Jedis("192.168.10.101", 6379);
//指定服务器密码
jedis.auth("111111");
//获取redis客户端,可以向jdbc一样访问redis
System.out.println(jedis.ping()); //PONG
//keys
System.out.println(jedis.keys("*"));
jedis.set("k5", "hello-jedis");
System.out.println("jedis.get(\"k5\") = " + jedis.get("k5"));
jedis.lpush("list", "l1,l2,l3");
System.out.println("jedis.lrange(\"list\",0,-1) = " + jedis.lrange("list", 0, -1));
Map<String, String> map = new HashMap<>();
map.put("id", "1");
map.put("name", "zhangsan");
map.put("age", "25");
jedis.hset("user:001", map);
System.out.println("jedis.hgetAll(\"user:001\") = " + jedis.hgetAll("user:001"));
jedis.sadd("set", "1,2,3,4,5");
System.out.println("jedis.smembers(\"set\") = " + jedis.smembers("set"));
jedis.zadd("zset",100,"zhangsan");
System.out.println("jedis.zrange(\"zet\",0,-1) = " + jedis.zrange("zset", 0, -1));
}
}
/**
* PONG
* [zset, user:001, set, k5, list]
* jedis.get("k5") = hello-jedis
* jedis.lrange("list",0,-1) = [l1,l2,l3, l1,l2,l3]
* jedis.hgetAll("user:001") = {name=zhangsan, age=25, id=1}
* jedis.smembers("set") = [1,2,3,4,5]
* jedis.zrange("zet",0,-1) = [zhangsan]
*/
2、集成lettuce
是什么
Redis的Java驱动包
lettuce vs jedis
● 都可以链接Redis服务器,但是在SpringBoot2.0之后默认使用的是Lettuce这个客户端连接Redis服务器
● Lettuce底层使用的是Netty
案例
改POM
POM依赖
<!--lettuce-->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.2.1.RELEASE</version>
</dependency>
案例
public class LettuceDemo {
public static void main(String[] args) {
//使用构建器链式编程builder我们的RedisURI
RedisURI uri = RedisURI.builder()
.redis("192.168.10.101")
.withPort(6379)
.withAuthentication("default", "111111")
.build();
//创建连接客户端
RedisClient redisClient = RedisClient.create(uri);
StatefulRedisConnection<String, String> conn = redisClient.connect();
//通过conn创建操作的command
RedisCommands<String, String> commands = conn.sync();
//业务逻辑
//#######################
System.out.println("commands.keys(\"*\") = " + commands.keys("*")); //commands.keys("*") = [k5, user:001, list, zset, set]
commands.set("k7", "hello-lettuce");
System.out.println("commands.get(\"k7\") = " + commands.get("k7")); //commands.get("k7") = hello-lettuce
//#######################
//各种关闭释放资源
conn.close();
redisClient.shutdown();
}
}
3、集成RedisTemplate—推荐使用
连接单机
改POM
<!--SpringBoot与Redis整合依赖-->
<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
server:
port: 7777
spring:
application:
name: redis7_study
redis:
database: 0
host: 192.168.10.101
port: 6379
password: 111111
lettuce:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
案例
@Service
@Slf4j
public class OrderService {
public static final String ORDER_KEY = "ord:";
@Autowired
private RedisTemplate redisTemplate;
public void addOrder() {
int keyId = ThreadLocalRandom.current().nextInt(1000) + 1;
String serialNo = UUID.randomUUID().toString();
String key = ORDER_KEY + keyId;
String value = "京东订单" + serialNo;
redisTemplate.opsForValue().set(key, value);
log.info("***key:{}", key);
log.info("***value:{}", value);
}
public String getOrderById(Integer keyId) {
return redisTemplate.opsForValue().get(ORDER_KEY + keyId).toString();
}
}
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();
template.setConnectionFactory(connectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
连接集群
改写YML
server:
port: 7777
spring:
application:
name: redis7_study
redis:
password: 111111
lettuce:
pool:
max-active: 8
max-wait: -1ms
max-idle: 8
min-idle: 0
cluster:
max-redirects: 3
nodes: 192.168.10.101:6381,192.168.10.101:6382,192.168.10.102:6383,192.168.10.102:6384,192.168.10.103:6385,192.168.10.103:6386
直接通过微服务访问Redis集群
问题来了
- 认为模拟,master-6381及其意外宕机,手动shutdown
- 先对redis集群命令方式,手动验证各种读写命令,看看6384是否上位
3.Redis Cluster集群能自动感知并自动完成主备切换,对应的slave6384会被选举为master节点
4. 微服务客户端再次读写访问试试
a. 故障现象:SpringBoot客户端没有感知到RedisCluster的最新集群信息
b. 原因:SpringBoot2.X版本,Redis默认的连接池采用Lettuce,当Redis集群节点发生变化后,Lettuce默认是不会刷新节点拓扑。
c. 解决方案:
ⅰ. 排除lettuce采用jedis(不推荐)
ⅱ. 重写连接工厂实例(极度不推荐)
ⅲ. 刷新节点集群拓扑动态感应
1. 在YML配置文件新增两个设置: spring.redis.lettuce.cluster.refresh.adaptive=true支持集群拓扑动态感应刷新,自适应拓扑刷新是否适用所有可用的更新,默认false关闭 和 spring.redis.lettuce.cluster.refresh.period=2000 定时刷新