项目接入redis

首先通俗的介绍下redis:可以把redis当做一个数据库,像mysql这样,只是存放的方式和地方不一样。

                                       redis将数据存放在内存中,所有读取的速度肯定比mysql快。

                                       同时redis的数据类型是key-value型。和Map<String,Object>相似。所以对于java项目来说,很方便对redis                                         的数据操作。redis的value值可以支持 String,List,Set,ZSet(有序),Hash.

项目需求:项目需要统计每个使用者(大概每天1w人登录操作)的操作内容,操作了多少次(总共400个接口)。每天最多400w条数据。

方案:1.采用HashMap来存数据,数据内存太大。系统吃不消

        2.接入监控平台,添加埋点即可。但是花费太大,每年11w

        3.接入redis。费用大减

具体操作: 1.引入jar 由于项目比较老,用的jdk6,并且内网限制。采用了jedis 2.1.0 和commons-pool 1.5.6

                   jedis用于操作redis,常见的set,get,expire,其他对象的操作等。

                  现在基本使用jedis 2.9.0+ 和commons2-pool 2.4.2+ 并且会接入Spring(封装了一层)

                2.具体代码逻辑,2.1 写好redis工具类,这个可以百度。然后注意连接池的配置。  JedisPoolConfig的配置。

                                            2.2 写个拦截器。对所有的请求,获取用户编码 a,请求url b,当天时间 c. 以 a_b_c为key,value放次                                                       数。第一次为1,然后 2. 可以用到redis的incrby方法。因为有了当前日期,并且我们打算存两天                                                      的数据,所有得设 置有效期,不然以后垃圾数据就爆了。设置有效期为两天。

                                            2.3 写个定时任务,每天凌晨将缓存的数据读取出来,批量插入到oracle中,然后定期进行归档(将次                                                    数进行汇总,相同的key的数据累加,只保留前7天的数据和月份数据,后期归档到年数据中)

                             至此就完成了:          后面再根据oracle中的数据查询即可。

 

出现的问题:

1.JedisPoolConfig 的问题,很多参数只是百度然后没有认真思考。

   1.1 whenExhaustedAction(当取不到jedis链接时的操作):默认是 阻塞等待。千万不要这样,这样会导致线上大量线程阻塞。                                                          最好是设置为0.即超过等待时间还没获取到就抛异常。这个问题导致线上紧张的一批。

                                                    同时设置下max_wait的值。比如 3000,单位 毫秒

  1.2. testOnBorrow 和testOnReturn 即 测试 取链接和还链接 是测试 链接时ok的,但是我出现了问题,并设置了后并没有起作                                        用。

 

2. 异常  JedisConnectionException

    正常测试开发环境都没有问题,一旦并发,就出现问题了。。。。

  后来经过不断的找问题,终于发现是对于异常处理的问题:

   之前 的代码:

      long result=0;

    Jedis jedis=getJedis();

 try{

    result=jedis.incrBy(key,count)// key 为a_b_c 字符串,count 为1,累加1

    if(result==1) jedis.expire(key,expire_time)//只在第一次设置过期时间

}catch(Exception e){

log.error(......)

}finally{

   jedisPool.returnResource(jedis);//释放资源,将连接放回连接池

}

上述代码好像没有问题,可以一旦并发起来,jedis.incrBy 这个代码会有异常,

由于异常后没有将异常链接销毁掉,导致异常链接一直被用,从而一直报有错误信息。

所以在Catch那里需要有针对性的catch异常。

catch(JedisConnectionException e){

      jedisPool.returnBrokenResource(jedis);//销毁异常链接

}

 

 

异常二:

   是由于自己不小心造成的,后果非常严重。我在取链接的方法中的finally中添加了returnResource方法,在实际操作链接的地方,比如incrby(),get(),set()方法的finally也添加了returnResource方法。导致连接池中的一个参数 numActive为负数。应为每拿了一个链接,我返回的两次,导致现存的链接时负数。而 whenExhaustedAction 这参数的判断条件是当前链接大于最大链接时才会起作用,所以whenExhaustedAction 这个参数不起作用。可想而知。最后都阻塞了。

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值