GO连接redis数据库时,redis的TCP出现大量ESTABLISHED或者TIME_WAIT

1、Go  连接redis的方法:

package que

import (
	"fmt"
	"time"

	"github.com/gomodule/redigo/redis"
)

var (
	pool      *redis.Pool
	localhost = "" // 127.0.0.1
	port      = "6379"
	addr      = localhost + ":" + port
	Password  = ""
)

func init() {
	initRides()
	// InitReceiver()
}

func initRides() {
	pool = &redis.Pool{
		IdleTimeout: 180 * time.Second,
		Dial: func() (redis.Conn, error) {
			conn, err := redis.Dial("tcp", addr, redis.DialPassword(Password))
			if err != nil {
				return nil, err
			}
			return conn, nil
		},
	}
}

其中如果没有 redis.DialPassword(Password),则连接redis时可能会报错:NOAUTH Authentication required.

或者可以使用下面这种设置方式解决认证问题:

func initRides() {
	pool = &redis.Pool{
		IdleTimeout: 180 * time.Second,
		Dial: func() (redis.Conn, error) {
			conn, err := redis.Dial("tcp", addr)
			if err != nil {
				return nil, err
			}
			if _, err := conn.Do("AUTH", Password); err != nil {
				conn.Close()
				return nil, err
			}
			return conn, nil
		},
	}
}

2、根据业务需求,在main的init里面调用InitReceiver方法,当需要处理大量数据的时候,接口不能做出及时反馈,这时就需要类似的模型来解决该问题了:


func init() {
	initRides()
	InitReceiver()
}

func InitReceiver() {
	go func() {
		for {
			var conn = pool.Get()
			defer conn.Close()

			// Do some thing
			conn.Do("set", "test", "test1111")
			line, _ := redis.String(conn.Do("get", "test"))

			fmt.Println(line)
		}
	}()
}

3、代码跑起来之后,使用命令:

netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'

查看TCP的状态信息,其中ESTABLISHED状态的存在1万多个:

CLOSE_WAIT       1
ESTABLISHED      10015
SYN_SENT         1
TIME_WAIT        15

下面是 TCP正常连接建立和终止所对应的状态图:

相关TCP状态解释:

LISTEN:       侦听来自远方的TCP端口的连接请求;

SYN_SENT:     在发送连接请求后等待匹配的连接请求;

SYN_RECV: 在收到和发送一个连接请求后等待对方对连接请求的确认;

ESTABLISHED:  代表一个打开的连接;

FIN_WAIT1:   等待远程TCP连接中断请求, 或先前的连接中断请求的确认;

FIN_WAIT2:   从远程TCP等待连接中断请求;

CLOSE_WAIT:   等待从本地用户发来的连接中断请求;

CLOSING:      等待远程TCP对连接中断的确认;

LAST_ACK:     等待原来的发向远程TCP的连接中断请求的确认;

TIME_WAIT:    等待足够的时间以确保远程TCP接收到连接中断请求的确认;

CLOSE:        没有任何连接状态;

注(参考出处:https://blog.csdn.net/dujianxiong/article/details/83180633)

4、当我们推出程序之后:

[root ~]# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
CLOSE_WAIT       1
ESTABLISHED      15
SYN_SENT         1
TIME_WAIT        10013

ESTABLISHED状态的连接被中断了,会通过TIME_WAIT的状态保留一段时间,这段时间过了才会释放这个端口,但是如果再这段时间内还有大量的请求的时候,就会产生大量的TIME_WAIT状态的连接,这些连接占着端口,也会占用大量的资源。

5、解决方法,增加 MaxIdle 和 MaxActive :

func initRides() {
	pool = &redis.Pool{
        MaxIdle:     30,
		MaxActive:   30,
		IdleTimeout: 180 * time.Second,
		Dial: func() (redis.Conn, error) {
			conn, err := redis.Dial("tcp", addr, redis.DialPassword(Password))
			if err != nil {
				return nil, err
			}
			return conn, nil
		},
	}
}

maxIdle,最大空闲数,数据库连接的最大空闲时间。超过空闲时间,数据库连
接将被标记为不可用,然后被释放。设为0表示无限制。
MaxActive,连接池的最大数据库连接数。设为0表示无限制。

maxActive是最大激活连接数,这里取值为30,表示同时最多有30个数据库连接。

maxIdle是最大的空闲连接数,这里取值为30,表示即使没有数据库连接时依然可以保持30空闲的

连接,而不被清除,随时处于待命状态。

 

设置了之后效果显著:

[root ~]# netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
CLOSE_WAIT       2
ESTABLISHED      25
TIME_WAIT        67

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在 IntelliJ IDEA 中连接 Redis 数据库,需要进行以下步骤: 1. 在 pom.xml 文件中添加 Redis 相关的依赖: ```xml <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.6.0</version> </dependency> ``` 2. 在 Redis 数据库中创建一个数据库(例如:test),并启动 Redis 服务。 3. 在 IDEA 中创建一个 Java 项目,并创建一个 RedisUtil 工具类,用于连接 Redis 数据库。示例代码如下: ```java import redis.clients.jedis.Jedis; public class RedisUtil { private static final String HOST = "localhost"; // Redis 服务器地址 private static final int PORT = 6379; // Redis 服务器端口号 private static final int TIMEOUT = 10000; // 连接间 private static Jedis jedis = null; /** * 获取 Jedis 实例 */ public static Jedis getJedis() { if (jedis == null) { jedis = new Jedis(HOST, PORT, TIMEOUT); } return jedis; } /** * 关闭 Jedis 实例 */ public static void closeJedis() { if (jedis != null) { jedis.close(); } } } ``` 4. 在代码中调用 RedisUtil 工具类的 getJedis() 方法,获取 Jedis 实例,即可操作 Redis 数据库。示例代码如下: ```java Jedis jedis = RedisUtil.getJedis(); jedis.set("key", "value"); String value = jedis.get("key"); System.out.println(value); RedisUtil.closeJedis(); ``` 上述代码中,先使用 set 方法将 key-value 数据存储到 Redis 数据库中,然后使用 get 方法从 Redis 数据库中获取 key 对应的 value 值,并输出到控制台中。最后使用 closeJedis 方法关闭 Jedis 实例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值