Redis用一段时间之后会报错,经过反复测试和百度、Google之后才发现是redis连接池在关闭项目的时候,需要收回连接池,不然redis在开发的过程中,所有开发人员本地项目连接redis服务器,经常重启项目会累积很多不能释放的连接,
代码如下:
[java] view plain
copy
- <bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig">
- <property name="testWhileIdle" value="true"/>
- </bean>
- <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="destroy">
- <constructor-arg ref="jedisConfig" />
- <constructor-arg value="localhost" />
- <constructor-arg type="int" value="6379" />
- </bean>
其中
destroy-method="destroy",是关闭web容器的时候,会调用连接池的destroy,关闭和redis的连接,就此隐藏两个月的问题终于解决了。
还有可能是(go
语言)
代码里面用到了redis的连接池,
[plain] view plain
copy
- var pool *redis.pool
- func main() {
- pool = newRedisPool(REDISHOST+":6379", "")
-
- go userLoginLog()
-
- ....
- }
-
- func userLoginLog() {
- for {
- redisConn := pool.Get()
- defer redisConn.Close()
- listLog, err := redis.String(redisConn.Do("LPOP", "list"))
- ........
- }
- }
-
- func newRedisPool(server, password string) *redis.Pool {
- return &redis.Pool{
- MaxIdle: 10,
- IdleTimeout: 240 * time.Second,
- Dial: func() (redis.Conn, error) {
- c, err := redis.Dial("tcp", server)
- if err != nil {
- return nil, err
- }
- if _, err := c.Do("AUTH", password); err != nil {
- c.Close()
- return nil, err
- }
-
- return c, err
- },
- TestOnBorrow: func(c redis.Conn, t time.Time) error {
- _, err := c.Do("PING")
- return err
- }
- }
- }
就是上面的这段代码,
执行一段时间后,频繁的报“ ERR max number of clients reached ”
错误。google后,发现是
可能是因为客户端接入太多,也是可能是因为系统最大文件描述符数过小。仔细查看代码,才发现原来下面的这段代码:
[plain] view plain
copy
- defer redisConn.Close()
实际上根本没有执行过。之前用mysql的连接池的时候,也遇到类似的错误了,可惜记性不好哈。在redis的机子上执行如下代码,发现redis的连接数已经10000多个了。
[plain] view plain
copy
- [root@Web-DB ~]# netstat -an|grep 6379|wc -l
- 10003
果然是redis的连接数过多导致的。应该在执行完一次循环后就调用 [plain] view plain
copy
- redisConn.Close()
因为之前是死循环,所以defer永远没有执行。