请教大佬一个高并发下操作 Reids 出现 read: connection reset by peer 的问题

2019-06-24 08:15:06 +08:00
 wewin

我的程序如下,目的就是为了测试,高并发下读取 redis 会出现什么问题:

package main

import (
	"fmt"
	"time"

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

var pool *redis.Pool

type User struct {
	ID       int    `json:"id"`
	Name     string `json:"name"`
	Password string `json:"password"`
}

func init() {
	pool = &redis.Pool{
		// 初始化链接数量
		MaxIdle:     16,
		MaxActive:   0,
		IdleTimeout: 300 * time.Second,
		Dial: func() (redis.Conn, error) {
			return redis.Dial("tcp", "127.0.0.1:6379")
		},
	}
}

func idIncr(conn redis.Conn) (id int, err error) {
	res, err := conn.Do("incr", "users_id_for_test")
	if err != nil {
		fmt.Printf("id incr error: %v\n", err)
		return
	}
	id = int(res.(int64))
	fmt.Printf("id: %v\n", id)
	return
}

func Register() (err error) {
	conn := pool.Get()
	defer conn.Close()

	// id 自增 1,作为下个用户 id
	id, err := idIncr(conn)
	if err != nil {
		return
	}

	_, err = conn.Do("rpush", "usersList", id)
	if err != nil {
		fmt.Printf("set user to reids error: %v", err)
		return
	}
	return
}

// 测试高并发下操作 redis
func main() {
	for i := 0; i < 1000; i++ {
		go Register()
	}
	time.Sleep(10 * time.Second)
}

这种情况下会有大量的报错

id incr error: read tcp 127.0.0.1:54156->127.0.0.1:6379: read: connection reset by peer

减少 goroutine 的数量不会有问题

应该是在高并发下 redis 的可用连接数不够了导致的问题,有理解的比较深入的大佬给个仔细的讲解吗?最好能给上解决方案,谢谢!

10274 次点击
所在节点    Go 编程语言
25 条回复
onepunch
2019-06-24 21:10:55 +08:00
redis 管道技术了解一下,最近面试都在问这个 -,- 目前没碰到一个会的
freestyle
2019-06-24 22:12:03 +08:00
redigo: connection pool exhaustet 是 redigo 包返回的错误,和初始化 pool 的选项有关,你设置 maxActive 的同时把 wait=true 再试试效果
wewin
2019-06-25 07:34:26 +08:00
@freestyle redigo: connection pool exhaustet 是和 maxActive 有关的,maxActive 需要设置和操作 redis 的 goroutine 数量差不多,或者多余 goroutine 的数量就不会出现 redigo: connection pool exhaustet 的错误
freestyle
2019-06-25 09:40:58 +08:00
@wewin 你得的结论不太严谨 不知道你没有有看 redigo 的 pool 的详细注释 wait 是表示当 pool 中没有可用的连接时是报错还是等待 .
SmartKeyerror
2019-06-25 11:08:31 +08:00
Redis 内部使用 epoll 事件驱动模型, 只要 redis-server 所在的服务器能够打开的文件描述符以及内存足够, 一般是不会出现连接数不够用的。 在我的机子上跑你这个代码,goroutine 的数量开到 10000 也不会有任何报错, 但是当同时运行的 goroutine 数量超过了 redis-server 默认的 maxClients(10000)数量之后, 会抛出 id incr error: ERR max number of clients reached, 但是这也是意料之中的问题。 所以我建议你看一下是不是 redigo 的版本或者是服务器的问题, 检查下服务器 TCP 最大连接数, 能够打开的最大文件数这些。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/576766

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX