java原生程序redis连接(连接池/长连接和短连接)选择问题
2019-01-15 21:35
471 查看
版权声明:虽然坑有点多,不过转载请声明原作者 https://blog.csdn.net/jyj1100/article/details/86499547
最近遇到的连接问题我准备从重构的几个程序(redis和mysql)长连接和短连接,以及连接池和单连接等问题用几篇博客来总结下。
这个问题的具体发生在java原生程序和redis的交互中。这个问题对我最深刻的教训就是说明获取连接不能迷信连接池和原封不动的搬运以前代码的utils。在连接的建立的一开始就应该思考连接的稳定性和是否应该关闭连接。否则这些问题在线上运行十几个小时可能才会暴露,即使知道了问题反过来的排查和修改也会很困难。甚至在重构之前用一种勉强凑合的方式掩盖问题(给自己挖坑)
应用场景
java原生程序,内部写多个线程,定时循环监测(一小时一次),使用了redis连接。
最开始是采用长连接的方式,在main方法中用连接池获取连接后分配到各线程,这种方式虽然只创建一次连接,但在长时间的程序休眠中,仍然会产生对连接的占用,也会导致掉连接的问题,以下是从连接池获取连接的代码(也可拆分成获取连接池和通过连接池单独获取连接):
[code]public Jedis createJedisCluterInstance(Map<String, Object> props){ String[] hostPortStr = String.valueOf(this.config.getOrDefault(REDIS_CLUSTER_NODE_PORT,props.get(REDIS_CLUSTER_NODE_PORT))).split(":"); GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(Integer.valueOf(String.valueOf(this.config.getOrDefault(REDIS_MAX_TOTAL,props.get(REDIS_MAX_TOTAL))))); config.setMaxIdle(Integer.valueOf(String.valueOf(this.config.getOrDefault(REDIS_MAX_IDLE,props.get(REDIS_MAX_IDLE))))); config.setMaxWaitMillis(Integer.valueOf(String.valueOf(this.config.getOrDefault(REDIS_MAX_WAIT_MILLIS,props.get(REDIS_MAX_WAIT_MILLIS))))); JedisPool jedisPool = new JedisPool(config,hostPortStr[0],Integer.valueOf(hostPortStr[1])); final Jedis[] jedis= {null}; Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder() .retryIfException() .withWaitStrategy(WaitStrategies.fixedWait(1000, TimeUnit.MILLISECONDS)) .withStopStrategy(StopStrategies.stopAfterAttempt(10)) .build(); try { retryer.call(() -> { jedis[0] = jedisPool.getResource(); jedis[0].auth("123"); String value = jedis[0].ping(); return StringUtils.isNotBlank(value); }); } catch (Exception e) { LOGGER.error("多次获取Redis连接失败!"); } return jedis[0]; }
当时处理掉连接的方式是采用了定时任务按每分钟一次的频率监测,对异常trycatch后直接退出程序。
这种方法产生了很大的资源消耗,也对业务造成影响,主要原因是盲目使用连接池造成的。
修改后采用传入配置到线程中,在线程中启动连接,同时修改连接池连接为直接获取连接。减少了资源消耗,同时也处理了掉连接的问题。并在每次循环结束后关闭redis连接 :关闭方法redis.close(); 并在下次循环开始后重新初始化,直接获取redis对象代码:
[code]public Jedis getJedis(Map<String, Object> props){ String[] hostPortStr = String.valueOf(this.config.getOrDefault(REDIS_CLUSTER_NODE_PORT, props.get(REDIS_CLUSTER_NODE_PORT))).split(":"); Jedis jedis = new Jedis(hostPortStr[0],Integer.valueOf(hostPortStr[1]),Integer.valueOf(String.valueOf(this.config.getOrDefault(REDIS_MAX_WAIT_MILLIS, props.get(REDIS_MAX_WAIT_MILLIS))))); jedis.auth("123"); return jedis; }
相关文章推荐
- java redis client无法连接redis服务获取连接池问题处理记录
- java原生程序mysql连接(Durid连接池和普通连接)选择问题
- 使用JNI连接Cpp程序的问题--> java.lang.UnsatisfiedLinkError: HelloWorld
- Java连接虚拟机的redis报错问题解决办法
- Java/JSP程序连接不上Mysql驱动问题解决方法
- Java连接linux虚拟机的redis报错问题解决办法
- 首次用java连接redis出现的问题
- Linux后台启动程序以及打开XShell连接运行java -jar然后关闭连接程序不再运行问题
- Java连接虚拟机的redis报错问题解决办法
- Java连接redis小程序
- java Swing 程序连接SQLsever数据库方面的系列问题.
- Java ADF Template程序不能连接ArcGIS Server问题
- window 7 下用MyEclipse编写Java程序连接HBase时遇到的问题
- JAVA连接redis,解决权限问题(第一次连接不上)
- java连接redis 的问题
- java 连接redis 遇到的问题
- Java程序连接数据库(mysql,sql server)以及出现的问题解决
- 关于spring boot整合druid连接池在程序关闭后连接不释放问题解决
- Linux中4.0.1版本的redis和java连接出现的redis被保护的问题以及解决办法
- 虚拟机开启Redis,java代码连接失败问题