连接redis出错

本文记录了一次因Redis运行在保护模式下导致的任务调度错误,并给出了详细的堆栈跟踪信息及解决方案。通过配置文件启动Redis服务来禁用保护模式,确保外部连接正常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler] - Unexpected error occurred in scheduled task.
  org.springframework.dao.DataAccessResourceFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:101)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:148)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.getConnection(JedisConnectionFactory.java:41)
at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:81)
at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:53)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:150)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:133)
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:84)
at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:42)
at com.shores.utils.RedisUtil.get(RedisUtil.java:167)
at com.shores.task.MyTestTask.templateCode(MyTestTask.java:81)
at com.shores.task.MyTestTask.spiderSportByCanadaJob(MyTestTask.java:111)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
at redis.clients.util.Pool.getResource(Pool.java:22)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.fetchJedisConnector(JedisConnectionFactory.java:94)
... 25 more
Caused by: redis.clients.jedis.exceptions.JedisDataException: DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.
at redis.clients.jedis.Protocol.processError(Protocol.java:59)
at redis.clients.jedis.Protocol.process(Protocol.java:66)
at redis.clients.jedis.Protocol.read(Protocol.java:131)
at redis.clients.jedis.Connection.getStatusCodeReply(Connection.java:162)
at redis.clients.jedis.Jedis.auth(Jedis.java:1964)
at redis.clients.jedis.JedisPool$JedisFactory.makeObject(JedisPool.java:74)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1158)
at redis.clients.util.Pool.getResource(Pool.java:20)

... 26 more


解决:启动redis时使用带配置文件的方式开启:redis-server redis.conf


<think>我们正在处理用户关于如何连接和配置Redis集群的问题。用户可能遇到了Flink连接Redis集群的问题,并希望获得连接和配置Redis集群的指南或解决方案。根据引用内容,我们可以提取以下关键信息:1.引用[1]提到用户尝试使用Flink连接Redis集群时遇到问题,并决定重写Redis集群连接代码。这涉及到Flink与Redis集群的集成问题。2.引用[2]提供了一个配置Redis集群的整体流程,包括引入依赖、配置连接信息、集群节点信息、连接池、RedisTemplate等步骤。3.引用[3]展示了使用redis-cli创建Redis集群的命令示例,其中指定了节点地址和副本数量。结合用户问题“如何连接和配置Redis集群”,我们应提供通用连接和配置Redis集群的步骤,同时考虑到用户可能是在Flink环境中使用,我们可以适当提及Flink连接Redis集群的注意事项。由于用户问题没有明确指定是普通应用连接Redis集群还是Flink连接Redis集群,我们将重点放在通用连接配置上,并在最后简要提及Flink集成。###连接和配置Redis集群的通用步骤####1.引入Redis客户端依赖在Java项目中,通常使用Jedis或Lettuce作为Redis客户端。以下是Maven依赖示例:```xml<!--Jedis--><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.7.0</version></dependency><!--或者Lettuce--><dependency><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId><version>6.1.8.RELEASE</version></dependency>```####2.配置Redis集群节点创建一个包含所有Redis集群节点(至少包括主节点)的集合。```javaSet<HostAndPort>clusterNodes=newHashSet<>();clusterNodes.add(newHostAndPort("192.168.150.101",7001));clusterNodes.add(newHostAndPort("192.168.150.101",7002));clusterNodes.add(newHostAndPort("192.168.150.101",7003));//如果有从节点,也可以添加,但客户端通常只需要主节点即可自动发现集群拓扑```####3.创建并配置JedisCluster对象使用Jedis连接集群:```java//设置连接池配置(可选)JedisPoolConfigpoolConfig=newJedisPoolConfig();poolConfig.setMaxTotal(100);//最大连接数poolConfig.setMaxIdle(20);//最大空闲连接数//创建JedisCluster对象JedisClusterjedisCluster=newJedisCluster(clusterNodes,10000,//连接超时时间(毫秒)10000,//读写超时时间(毫秒)3,//最大重试次数"yourPassword",//密码(如果无密码则为null)poolConfig);//连接池配置//使用jedisCluster对象操作集群jedisCluster.set("key","value");Stringvalue=jedisCluster.get("key");```如果使用Lettuce:```javaRedisURIredisUri=RedisURI.Builder.redis("192.168.150.101",7001).withPassword("yourPassword").build();RedisClusterClientclusterClient=RedisClusterClient.create(Collections.singletonList(redisUri));StatefulRedisClusterConnection<String,String>connection=clusterClient.connect();RedisAdvancedClusterCommands<String,String>commands=connection.sync();commands.set("key","value");Stringvalue=commands.get("key");//关闭连接和客户端connection.close();clusterClient.shutdown();```####4.配置RedisTemplate(Spring项目)在SpringBoot项目中,通常使用RedisTemplate来操作Redis集群。在`application.properties`或`application.yml`中配置集群信息:```propertiesspring.redis.cluster.nodes=192.168.150.101:7001,192.168.150.101:7002,192.168.150.101:7003spring.redis.password=yourPasswordspring.redis.timeout=10000spring.redis.jedis.pool.max-active=100spring.redis.jedis.pool.max-idle=20spring.redis.jedis.pool.min-idle=5```然后配置RedisTemplateBean:```java@ConfigurationpublicclassRedisConfig{@BeanpublicRedisConnectionFactoryredisConnectionFactory(){RedisClusterConfigurationclusterConfig=newRedisClusterConfiguration();//解析节点配置String[]nodes=environment.getProperty("spring.redis.cluster.nodes").split(",");for(Stringnode:nodes){String[]hostPort=node.split(":");clusterConfig.addClusterNode(newRedisNode(hostPort[0],Integer.parseInt(hostPort[1])));}clusterConfig.setPassword(RedisPassword.of(environment.getProperty("spring.redis.password")));JedisConnectionFactoryfactory=newJedisConnectionFactory(clusterConfig);factory.setTimeout(Integer.parseInt(environment.getProperty("spring.redis.timeout")));factory.getPoolConfig().setMaxTotal(Integer.parseInt(environment.getProperty("spring.redis.jedis.pool.max-active")));factory.getPoolConfig().setMaxIdle(Integer.parseInt(environment.getProperty("spring.redis.jedis.pool.max-idle")));factory.getPoolConfig().setMinIdle(Integer.parseInt(environment.getProperty("spring.redis.jedis.pool.min-idle")));returnfactory;}@BeanpublicRedisTemplate<String,Object>redisTemplate(){RedisTemplate<String,Object>template=newRedisTemplate<>();template.setConnectionFactory(redisConnectionFactory());template.setKeySerializer(newStringRedisSerializer());template.setValueSerializer(newGenericJackson2JsonRedisSerializer());returntemplate;}}```####5.使用Redis集群在代码中注入RedisTemplate即可使用:```java@AutowiredprivateRedisTemplate<String,Object>redisTemplate;publicvoidsetKey(Stringkey,Objectvalue){redisTemplate.opsForValue().set(key,value);}publicObjectgetKey(Stringkey){returnredisTemplate.opsForValue().get(key);}```###关于Flink连接Redis集群如果用户需要在Flink中连接Redis集群,可以考虑使用第三方库(如bahir),但根据引用[1]所述,bahir可能存在问题。用户重写了连接代码,但具体代码未在引用中给出。建议用户参考可靠的Flink-Redis连接器实现,例如:-[FlinkRedisConnectorbyapache/bahir](https://bahir.apache.org/docs/flink/current/flink-streaming-redis/)(但用户已遇到问题)-或者社区中其他维护较好的实现,如[streaming/flink-connector-redis](https://github.com/apache/bahir/tree/master/flink-connector-redis)(注意检查版本兼容性)如果用户需要自定义连接器,可能需要实现`RichSinkFunction`,并在其中创建Redis集群连接(如上述JedisCluster或Lettuce连接),然后在`invoke`方法中处理数据写入。###注意事项-确保所有Redis节点配置了正确的绑定地址(bind)和密码(requirepass)。-集群模式需要至少3个主节点,每个主节点可以有多个副本。-防火墙设置需允许客户端访问所有Redis节点端口。§§相关问题§§1.如何创建Redis集群?2.如何配置Redis集群的密码认证?3.在SpringBoot项目中如何配置Redis集群?4.Flink如何连接Redis集群进行数据写入?5.Redis集群节点故障时客户端如何处理?</think>### 如何连接和配置 Redis 集群 #### 一、基础配置流程 1. **引入 Redis 依赖** 在 Maven 或 Gradle 项目中添加 Redis 客户端依赖(以 Jedis 为例): ```xml <!-- Maven 依赖 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.2.3</version> </dependency> ``` 2. **配置集群节点信息** 初始化 Redis 集群连接时需指定所有主节点地址(至少 3 个主节点): ```java Set<HostAndPort> nodes = new HashSet<>(); nodes.add(new HostAndPort("192.168.150.101", 7001)); // 主节点1 nodes.add(new HostAndPort("192.168.150.101", 7002)); // 主节点2 nodes.add(new HostAndPort("192.168.150.101", 7003)); // 主节点3 ``` 3. **创建集群连接对象** 通过 `JedisCluster` 建立连接(支持密码认证和连接池配置): ```java JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(100); // 最大连接数 poolConfig.setMaxIdle(20); // 最大空闲连接 JedisCluster jedisCluster = new JedisCluster( nodes, 10000, // 连接超时(ms) 10000, // 读写超时(ms) 3, // 最大重试次数 "your_password",// 集群密码 poolConfig // 连接池配置 ); ``` 4. **执行数据操作** 通过集群对象读写数据: ```java jedisCluster.set("key", "value"); // 写入数据 String value = jedisCluster.get("key"); // 读取数据 ``` #### 二、Flink 连接 Redis 集群的特殊处理 针对 Flink 无法直连 Redis 集群的问题(如 bahir 连接器的局限性),需重写连接逻辑[^1]: 1. **自定义 Redis Sink** 继承 `RichSinkFunction` 实现集群连接管理: ```java public class RedisClusterSink extends RichSinkFunction<String> { private transient JedisCluster jedisCluster; @Override public void open(Configuration parameters) { Set<HostAndPort> nodes = ... // 初始化节点 jedisCluster = new JedisCluster(nodes, 10000, 10000, 3, "password"); } @Override public void invoke(String value, Context context) { jedisCluster.set("flink_data", value); // 写入Redis } } ``` 2. **Flink Job 中调用** ```java DataStream<String> stream = ... // 从Kafka获取数据 stream.addSink(new RedisClusterSink()); ``` #### 三、Redis 集群创建命令 使用 `redis-cli` 创建集群(Redis 6.2.4+)[^3]: ```bash redis-cli --cluster create \ 192.168.150.101:7001 \ 192.168.150.101:7002 \ 192.168.150.101:7003 \ 192.168.150.101:8001 \ 192.168.150.101:8002 \ 192.168.150.101:8003 \ --cluster-replicas 1 # 每个主节点配1个副本 ``` #### 四、关键注意事项 1. **网络要求** - 所有节点需互通,开放 `6379`(服务端口)和 `16379`(集群总线端口) - 避免跨机房部署以减少延迟 2. **客户端兼容性** - 使用 Jedis 3.0+ 或 Lettuce 6.0+ 支持集群协议 - 旧版客户端需升级以避免 `MOVED` 重定向错误 3. **高可用配置** ```java // 设置故障转移检测 poolConfig.setTestOnBorrow(true); // 启用自动拓扑刷新 jedisCluster.refreshClusterInfo(); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值