目录
- 12.1 配置文件
- 12.2 防火墙
- 12.3 Jedis(一般不用了,了解即可)
- 1.介绍
- 2.步骤
- 3.写YML
- 4.主启动
- 5.业务类
- 12.4 Lettuce
- 1.介绍以及和Jedis的区别
- 2.步骤
- 1.改pom
- 2.业务类
- 12.5 Redis Template(推荐)
- 1.连接单机
- 1.改pom
- 2.写YML
- 3.业务类
- 3.1配置类
- 3.2 service
- 3.3 controller
- 测试
- 序列化问题
- 2.连接集群
- 1.正常启动
- 2.人为模拟down机
- 3.解决方案
- 1.排除Lettuce采用jedis(不推荐)
- 2.重写连接工厂(极度不推荐)
- 3.刷新节点集群拓扑动态感应
12.1 配置文件
redis.conf配置文件,改完后确保生效,记得重启,记得重启
- 默认daemonize no 改为 daemonize yes
- 默认protected-mode yes 改为 protected-mode no
- 默认bind 127.0.0.1 改为 直接注释掉(默认bind 127.0.0.1只能本机访问)或改成本机IP地址,否则影响远程IP连接
- 添加redis密码 改为 requirepass 你自己设置的密码
12.2 防火墙
启动: systemctl start firewalld
关闭: systemctl stop firewalld
查看状态: systemctl status firewalld
开机禁用 : systemctl disable firewalld
开机启用 : systemctl enable firewalld
添加 :firewall-cmd --zone=public --add-port=80/tcp --permanent (--permanent永久生效,没有此参数重启后失效)
重新载入: firewall-cmd --reload
查看: firewall-cmd --zone= public --query-port=80/tcp
删除: firewall-cmd --zone= public --remove-port=80/tcp --permanent
12.3 Jedis(一般不用了,了解即可)
1.介绍
Jedis Client 是Redis 官网推荐的一个面向 Java 客户端,库文件实现了对各类API进行封装调用
2.步骤
- 建Moudle redis_7_study
- 改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.redis7</groupId><artifactId>redis7_study</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.10</version><relativePath/></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><junit.version>4.12</junit.version><log4j.version>1.2.17</log4j.version><lombok.version>1.16.18</lombok.version></properties><dependencies><!--SpringBoot通用依赖模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--jedis--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version></dependency><!--通用基础配置--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version></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><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><optional>true</optional></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
3.写YML
server.port=7777spring.application.name=redis7_study
4.主启动
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Redis7Study01Application {public static void main(String[] args) {SpringApplication.run(Redis7Study01Application.class, args);}
}
5.业务类
import redis.clients.jedis.Jedis;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;public class JedisDemo {public static void main(String[] args) {// 1 connection 连接,通过指定ip和端口号Jedis jedis = new Jedis("192.168.238.111", 6379);// 2 指定访问服务器密码jedis.auth("111111");// 3 获得了Jedis客户端,可以像jdbc一样访问redisSystem.out.println(jedis.ping());// keysSet<String> keys = jedis.keys("*");System.out.println(keys);// stringjedis.set("k3","hello-jedis");System.out.println(jedis.get("k3"));System.out.println(jedis.ttl("k3"));// listjedis.lpush("list","11","22","33");List<String> list = jedis.lrange("list", 0, -1);for (String s : list) {System.out.println(s);}System.out.println(jedis.rpop("list"));System.out.println(jedis.lpop("list"));// hashjedis.hset("hset1","k1","v1");Map<String,String> hash = new HashMap<>();hash.put("k1","1");hash.put("k2","2");hash.put("k3","3");jedis.hmset("hset2",hash);System.out.println(jedis.hmget("hset2","k1","k3","k2"));System.out.println(jedis.hget("hset1", "k1"));System.out.println(jedis.hexists("hset2","k2"));System.out.println(jedis.hkeys("hset2"));// setjedis.sadd("set1","1","2","3");jedis.sadd("set2","4");System.out.println(jedis.smembers("set1"));System.out.println(jedis.scard("set1"));System.out.println(jedis.spop("set1"));jedis.smove("set1","set2","1");System.out.println(jedis.smembers("set1"));System.out.println(jedis.smembers("set2"));System.out.println(jedis.sinter("set1", "set2")); // 交集System.out.println(jedis.sunion("set1","set2")); // 并集// zsetjedis.zadd("zset1",100,"v1");jedis.zadd("zset1",80,"v2");jedis.zadd("zset1",60,"v3");List<String> zset1 = jedis.zrange("zset1", 0, -1);for (String s : zset1) {System.out.println(s);}List<String> zset11 = jedis.zrevrange("zset1", 0, -1);for (String s : zset11) {System.out.println(s);}}
}
12.4 Lettuce
1.介绍以及和Jedis的区别
Lettuce是一个Redis的Java驱动包,Lettuce翻译为生菜,没错,就是吃的那种生菜,所以它的Logo就是生菜
2.步骤
1.改pom
<!--lettuce--><dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>6.2.1.RELEASE</version></dependency>
2.业务类
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我们的RedisURIRedisURI uri = RedisURI.builder().withHost("192.168.238.111")//.redis("192.168.238.111").withPort(6379).withAuthentication("default", "123456").build();// 2 连接客户端RedisClient redisClient = RedisClient.create(uri);StatefulRedisConnection<String, String> conn = redisClient.connect();// 3 创建操作的command, 通过conn 创建RedisCommands<String, String> commands = conn.sync();// stringcommands.set("k1","v1");System.out.println("==========================="+commands.get("k1"));System.out.println("==========================="+commands.mget("k1","k2"));List<String> keys = commands.keys("*");for (String key : keys) {System.out.println("========================="+key);}// listcommands.lpush("list01","1","2","3");List<String> list01 = commands.lrange("list01", 0, -1);for (String s : list01) {System.out.println("================"+s);}System.out.println("===================="+ commands.rpop("list01", 2));// hashcommands.hset("hash","k1","v1");commands.hset("hash","k2","v2");commands.hset("hash","k3","v3");System.out.println("======================="+commands.hgetall("hash"));Boolean hexists = commands.hexists("hash", "v2");System.out.println("------"+hexists);// setcommands.sadd("s1","1","2");System.out.println("=================================" + commands.smembers("s1"));System.out.println(commands.sismember("s1", "1"));System.out.println(commands.scard("s1"));// zsetcommands.zadd("a1",100,"v1");commands.zadd("a1",80,"v2");System.out.println(commands.zrange("a1", 0, -1));System.out.println("======================"+commands.zcount("a1", "90", "100"));// 4 各种关闭释放资源 先开后关conn.close();redisClient.shutdown();}
}
12.5 Redis Template(推荐)
1.连接单机
1.改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><!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency>
2.写YML
server.port=7777spring.application.name=redis7_study# ========================logging=====================
logging.level.root=info
logging.level.com.atguigu.redis7=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n logging.file.name=D:/mylogs2023/redis7_study.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n# ========================swagger=====================
spring.swagger2.enabled=true
#在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常,
#原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser,
# 导致出错,解决办法是matching-strategy切换回之前ant_path_matcher
spring.mvc.pathmatch.matching-strategy=ant_path_matcher# ========================redis单机=====================
spring.redis.database=0
# 修改为自己真实IP
spring.redis.host=192.168.111.185
spring.redis.port=6379
spring.redis.password=111111
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
3.业务类
3.1配置类
- RedisConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisConfig
{/*** redis序列化的工具配置类,下面这个请一定开启配置* 127.0.0.1:6379> keys ** 1) "ord:102" 序列化过* 2) "\xac\xed\x00\x05t\x00\aord:102" 野生,没有序列化过* this.redisTemplate.opsForValue(); //提供了操作string类型的所有方法* this.redisTemplate.opsForList(); // 提供了操作list类型的所有方法* this.redisTemplate.opsForSet(); //提供了操作set的所有方法* this.redisTemplate.opsForHash(); //提供了操作hash表的所有方法* this.redisTemplate.opsForZSet(); //提供了操作zset的所有方法* @param lettuceConnectionFactory* @return*/@Beanpublic RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory){RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(lettuceConnectionFactory);//设置key序列化方式stringredisTemplate.setKeySerializer(new StringRedisSerializer());//设置value的序列化方式json,使用GenericJackson2JsonRedisSerializer替换默认序列化redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.afterPropertiesSet();return redisTemplate;}
}
- SwaggerConfig
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;@Configuration
@EnableSwagger2
public class SwaggerConfig
{@Value("${spring.swagger2.enabled}")private Boolean enabled;@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).enable(enabled).select().apis(RequestHandlerSelectors.basePackage("com.lv")) //你自己的package.paths(PathSelectors.any()).build();}public ApiInfo apiInfo() {return new ApiInfoBuilder().title("springboot利用swagger2构建api接口文档 "+"\t"+ DateTimeFormatter.ofPattern("yyyy-MM-dd").format(LocalDateTime.now())).description("springboot+redis整合,有问题给管理员发邮件:").version("1.0").termsOfServiceUrl("https://www.atguigu.com/").build();}
}
3.2 service
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;@Service
@Slf4j
public class OrderService {// RedisTemplate ===> StringRedisTemplate@Resourceprivate RedisTemplate redisTemplate;// private StringRedisTemplate redisTemplate;public static final String ORDER_KEY = "ord:";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 getOrderId(Integer keyId){return (String) redisTemplate.opsForValue().get(ORDER_KEY + keyId);}
}
3.3 controller
import com.lv.service.OrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@Slf4j
@Api(tags = "订单接口")
public class OrderController {@Resourceprivate OrderService orderService;@ApiOperation("新增订单")@RequestMapping(value = "/order/add", method = RequestMethod.POST)public void addOrder(){orderService.addOrder();}@ApiOperation("按照keyId 查询订单")@RequestMapping(value = "/order/{keyId}", method = RequestMethod.GET)public String getOrderId(@PathVariable Integer keyId){return orderService.getOrderId(keyId);}
}
测试
序列化问题
- 如果使用RedisTemplate,推荐序列化用StringRedisSerializer,默认使用的是JdkSerializationRedisSerializer,存入Redis会出现乱码问题,查询非常不方便
)
2.连接集群
1.正常启动
- 启动前面配的集群
- 改写YML(注意IP和端口)
server.port= 7070
spring.application.name=redis7_study01# ========================logging=====================
logging.level.root=info
logging.level.com.atguigu.redis7=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n logging.file.name=D:/mylogs2023/redis7_study.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n# ========================swagger=====================
spring.swagger2.enabled=true
#在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常,
#原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser,
# 导致出错,解决办法是matching-strategy切换回之前ant_path_matcher
spring.mvc.pathmatch.matching-strategy=ant_path_matcher# ========================redis单机=====================
#spring.redis.database=0
## 修改为自己真实IP
#spring.redis.host=192.168.238.111
#spring.redis.port=6379
#spring.redis.password=123456
#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=0spring.redis.password=123456
#获取失败,最大重定向次数
spring.redis.clusterspring.redis.cluster.nodes=192.1.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
68.238.111:6381,192.168.238.111:6382,192.168.238.112:6383,192.168.238.112:6384,192.168.238.113:6385,192.168.238.113:6386
- Swagger测试接口
2.人为模拟down机
-
让master-6381down机,shutdown
-
查看集群信息 ,看slave是否上位 Cluster nodes
-
我们客户端再次读写
-
直接报错Error
-
原因是因为SpringBoot客户端没有动态感知到RedisCluster的最新集群信息
-
导致这个的原因是
- Spring Boot 2,Redis默认的是 Lettuce(蕾缇斯)
- 当Redis集群节点发生变化后,Lettuce默认是不会刷新节点拓扑
-
3.解决方案
1.排除Lettuce采用jedis(不推荐)
2.重写连接工厂(极度不推荐)
// 很不推荐,不用了解
@Bean
public DefaultClientResources lettuceClientResources() {return DefaultClientResources.create();}@Bean
public LettuceConnectionFactory lettuceConnectionFactory(RedisProperties redisProperties, ClientResources clientResources) {ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder().enablePeriodicRefresh(Duration.ofSeconds(30)) //按照周期刷新拓扑.enableAllAdaptiveRefreshTriggers() //根据事件刷新拓扑.build();ClusterClientOptions clusterClientOptions = ClusterClientOptions.builder()//redis命令超时时间,超时后才会使用新的拓扑信息重新建立连接.timeoutOptions(TimeoutOptions.enabled(Duration.ofSeconds(10))).topologyRefreshOptions(topologyRefreshOptions).build();LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder().clientResources(clientResources).clientOptions(clusterClientOptions).build();RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration(redisProperties.getCluster().getNodes());clusterConfig.setMaxRedirects(redisProperties.getCluster().getMaxRedirects());clusterConfig.setPassword(RedisPassword.of(redisProperties.getPassword()));LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(clusterConfig, clientConfiguration);return lettuceConnectionFactory;}
3.刷新节点集群拓扑动态感应
改写YML
server.port= 7070
spring.application.name=redis7_study01
# ========================logging=====================
logging.level.root=info
logging.level.com.atguigu.redis7=info
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
logging.file.name=D:/mylogs2023/redis7_study.log
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger- %msg%n
# ========================swagger=====================
spring.swagger2.enabled=true
#在springboot2.6.X结合swagger2.9.X会提示documentationPluginsBootstrapper空指针异常,
#原因是在springboot2.6.X中将SpringMVC默认路径匹配策略从AntPathMatcher更改为PathPatternParser,
# 导致出错,解决办法是matching-strategy切换回之前ant_path_matcher
spring.mvc.pathmatch.matching-strategy=ant_path_matcher# ========================redis单机=====================
#spring.redis.database=0
## 修改为自己真实IP
#spring.redis.host=192.168.238.111
#spring.redis.port=6379
#spring.redis.password=123456
#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=0spring.redis.password=123456
#获取失败,最大重定向次数
spring.redis.clusterspring.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
redis.cluster.nodes=192.168.238.111:6381,192.168.238.111:6382,192.168.238.112:6383,192.168.238.112:6384,192.168.238.113:6385,192.168.238.113:6386
#支持集群拓扑动态感应刷新,自适应拓扑刷新是否使用所有可用的更新,默认false关闭
spring.redis.lettuce.cluster.refresh.adaptive=true
#定时刷新
spring.redis.lettuce.cluster.refresh.period=2000