redis资源未释放引发的问题
一、redis资源未释放的起因:
N年前,在修改一个古老程序时,不小心把redis释放的这块给干掉了,
|
程序调用了一会之后,就获取不到redis连接了,异常如下:
|
对比代码,定位到问题之后,修复上线。
二、事后分析出错的原因:
1、对于redis的认知不足.
2、java从集成redis角度上,我的认知:
2.1、选择spring-data-redis集成,目前我们的osp框架支持我们用这种方式,我目前的项目在用(po服务化).
集成后用RedisTemplate即可来操作。
好处:spring来帮你管理redis的连接获取和释放,我们只需要关注自己的业务就好.
坏处:限制于spring框架,其他暂未感觉...
2.2、用jedis来操作吧,
自己写好一个类,来获取JedisPool,对于redis的操作,记住操作完成后,释放连接回连接池,否则就会发生,我这次发生的这种问题。
好处:操作上更加灵活,不限于spring。
坏处:容易出错。
三、改进:
对于资源未释放,想到了在io操作,db操作等情况,最好封装统一的方法,保证最后资源一定是释放的。
redis方面,我参考spring的redisTemplate,
封装一个redis工具类,对每种类型的redis操作,封装一个方法,操作完后将资源释放回连接池,可避免再忘记释放redis。
代码示例:
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import redis.clients.jedis.Jedis;
- import redis.clients.jedis.JedisPool;
- import redis.clients.jedis.JedisPoolConfig;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- /**
- * 描 述:JedisUtil
- * 作 者:潇邦
- */
- public class JedisUtil {
- private static final Log logger = LogFactory.getLog(JedisUtil.class);
- //Redis服务器IP
- private static String IP = "127.0.0.1";
- //Redis的端口号
- private static int PORT = 6379;
- //可用连接实例的最大数目,默认值为8;
- //如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
- private static int MAX_ACTIVE = 64;
- //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
- private static int MAX_IDLE = 20;
- //等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException;
- private static int MAX_WAIT = 3000;
- private static int TIMEOUT = 3000;
- //在borrow一个jedis实例时,是否提前进行validate操作;如果为true,则得到的jedis实例均是可用的;
- private static boolean TEST_ON_BORROW = true;
- //在return给pool时,是否提前进行validate操作;
- private static boolean TEST_ON_RETURN = true;
- private static Map<String, JedisPool> maps = new ConcurrentHashMap<String, JedisPool>();
- private JedisUtil() {
- }
- /**
- * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
- */
- private static class RedisUtilHolder {
- private static JedisUtil instance = new JedisUtil();
- }
- /**
- * 当getInstance方法第一次被调用的时候,它第一次读取 RedisUtilHolder.instance,导致RedisUtilHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静
- * 态域,从而创建RedisUtil的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。 这个模式的优势在于,getInstance方法并没有被同步,
- * 并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本。
- */
- public static JedisUtil getInstance() {
- return RedisUtilHolder.instance;
- }
- /**
- * 获取连接池.
- */
- private JedisPool getPool(String ip, int port) {
- String key = ip + ":" + port;
- JedisPool pool = null;
- if (!maps.containsKey(key)) {//根据ip和端口判断连接池是否存在.
- JedisPoolConfig config = new JedisPoolConfig();
- config.setMaxTotal(MAX_ACTIVE);
- config.setMaxIdle(MAX_IDLE);
- config.setMaxWaitMillis(MAX_WAIT);
- config.setTestOnBorrow(TEST_ON_BORROW);
- config.setTestOnReturn(TEST_ON_RETURN);
- try {
- pool = new JedisPool(config, ip, port, TIMEOUT);
- maps.put(key, pool);
- } catch (Exception e) {
- logger.error("初始化Redis连接池异常:", e);
- }
- } else {
- pool = maps.get(key);
- }
- return pool;
- }
- /**
- * 获取Jedis实例
- */
- public Jedis getJedis() {
- Jedis jedis = null;
- try {
- jedis = getPool(IP, PORT).getResource();
- } catch (Exception e) {
- logger.error("获取Jedis实例异常:", e);
- // 销毁对象
- getPool(IP, PORT).returnBrokenResource(jedis);
- }
- return jedis;
- }
- /**
- * 释放jedis资源到连接池
- */
- public void returnResource(final Jedis jedis) {
- if (jedis != null) {
- getPool(IP, PORT).returnResource(jedis);
- }
- }
- /**
- * 获取数据
- */
- public Object get(String key) {
- Object value = null;
- Jedis jedis = null;
- try {
- jedis = getJedis();
- value = jedis.get(key);
- } catch (Exception e) {
- logger.warn("获取数据异常:", e);
- } finally {
- //返还到连接池
- returnResource(jedis);
- }
- return value;
- }
- public static void main(String[] args) {
- Object val = JedisUtil.getInstance().get("redisKey");
- System.out.println(val);
- }
- }
四、redis的概念:
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
五、数据库连接池的概念:
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
六、参考的资料:
http://www.cnblogs.com/linjiqin/archive/2013/06/14/3135248.html
http://www.sjsjw.com/kf_www/article/70_11941_26800.asp
http://www.cnblogs.com/tankaixiong/p/3660075.html
http://blog.csdn.net/truong/article/details/46711045
http://my.oschina.net/ydsakyclguozi/blog/465859
http://blog.csdn.net/aacm1992/article/details/21977237
http://www.cnblogs.com/jifeng/p/4676863.html
redis资源未释放引发的问题的更多相关文章
- 解决切换场景时NGUI图集资源未释放的问题
使用unity3d编辑器,在切换场景的时候.NGUI的图集没有释放造成内存不足游戏闪退的问题. 默认情况下,unity3d切换场景之后会释放不用的内存,即内部会调用Resources.UnloadUn ...
- 使用HttpURLConnection时遇到的资源未释放的问题
http://blog.sina.com.cn/s/blog_56beadc60100j9zu.html 今天自己写了一个压力测试的小程序,同时启100个线程,每个线程都串行地访问应用服务器上的一个j ...
- 图层损坏 E/ArcGIS﹕ The map or layer has been destroyed or recycled. 资源未释放
看到论坛上有个网友和我一样的问题: The map or layer has been destroyed or recyled t Hello, I have a problem when the ...
- 一次 Redis 事务使用不当引发的生产事故
这是悟空的第 170 篇原创文章 官网:http://www.passjava.cn 你好,我是悟空. 本文主要内容如下: 一.前言 最近项目的生产环境遇到一个奇怪的问题: 现象:每天早上客服人员在后 ...
- mysql优化, 删除数据后物理空间未释放(转载)
mysql优化, 删除数据后物理空间未释放(转载) OPTIMIZE TABLE 当您的库中删除了大量的数据后,您可能会发现数据文件尺寸并没有减小.这是因为删除操作后在数据文件中留下碎片所致.OPTI ...
- 关于mysql 删除数据后物理空间未释放(转载)
转自 关于mysql 删除数据后物理空间未释放(转载) - NETDATA - 博客园http://www.cnblogs.com/shawnloong/archive/2013/02/07/2908 ...
- jsch连接sftp后连接未释放掉问题排查
项目中通过jsch中的sftp实现上传下载文件.在压测过程中,由于调用到sftp,下载文件不存在时,系统不断抛出异常,内存飙升,逐渐把swap区也占满,通过top监控未发现占用内存的进程,通过查找ss ...
- java输入输出流操作同一资源实现覆盖引发冲突的解析
一.问题发生的场景 题目:把s.txt中大写转成小写,小写转成大写,空格转成下划线,在输入到文件中覆盖之前的 前面的没有问题,问题出现在后面的覆盖文件上,输入流.输出流要操作同一个文件的问题 二.小白 ...
- linux删除文件未释放空间问题处理
linux删除文件未释放空间问题处理 或者 /根分区满了 (我的根分区是/dev/sda1,/dev/sda1满了) http://blog.csdn.net/donghustone/article/ ...
随机推荐
- Dynamics CRM2013 sub grid中数据翻页问题
CRM2013中一个很低级很令人无语的BUG,见下图subgrid中的明细条目超过当前页设置的条目后会有翻页,在底下有个paging bar会显示条数.页数.当前所处页数 但sp1版本的CRM打上ur ...
- PA模块报错-实际返回的行数超出请求的行数(分析标准FORM报错解决思路)
录入预算报错时报错: 分析:这个错误是select into 语句返回多行的结果,但具体在哪? 两种方法查找,trace 或者debug 1.trace 启用调试 获取trace文件 -bash-3. ...
- PHP解决中文乱码问题
初学PHP,在汉字页面间传输和转换的时候,遇到了中文乱码问题. 究其原因乱码无外乎以下几种情况: 1.html页本身的乱码问题, 解决方法:纯html页使用<meta http-equiv=&q ...
- Uva - 11853 - Paintball
先判断是否有解,从上到下dfs判断连通性,如果有从顶部到底部连通图,则无解.再判断最北的进出位置,从上边界开始遍历,沿途检查与边界相交的圆.这些圆的左边界的交点中最靠南边的一个就是所有的最北进入位置, ...
- DB 查询分析器 6.04 发布 ,本人为之撰写的相关技术文章达78篇
DB查询分析器 6.04 发布,本人为之撰写的相关技术文章达78篇 中国本土程序员马根峰(CSDN专访马根峰:海量数据处理与分析大师的中国本土程序员 http://www.csdn.net/artic ...
- web多语言url的设计
因为项目要支持国际化,最近跟一个同事在讨论多语言版本下面url如何设计,假如我们需要支持en和cn的版本. 他倾向于支持如下的url格式,后续以格式1指代: /en/group/abc.html /c ...
- MinerConfig.java 爬取配置类
MinerConfig.java 爬取配置类 package com.iteye.injavawetrust.miner; import java.util.List; /** * 爬取配置类 * @ ...
- C++ Primer 有感(顺序容器)
1.顺序容器的元素排列次序与元素的值无关,而是由元素添加到容器里的次序决定. 2. 顺序容器 vector 支持快速随机访问 list ...
- Linux 学习笔记_12_文件共享服务_2_FTP应用--vsftpd
Wu-FTP:古老,配置复杂 Proftp:功能强大 vsftp: 安全,高速,稳定[系统默认的FTP软件] VSFTP服务器配置 启动:/etc/rc.d/init.d/vsftpd start [ ...
- Android群英传笔记——第八章:Activity与Activity调用栈分析
Android群英传笔记--第八章:Activity与Activity调用栈分析 开篇,我们陈述一下Activity,Activity是整个应用用户交互的核心组件,了解Activity的工作模式,生命 ...