写点什么

redis 中报 too many connections 错误的解决

作者:杨彦星
  • 2022 年 4 月 12 日
  • 本文字数:1910 字

    阅读完需:约 6 分钟

redis中报too many connections错误的解决

最近在对系统中某个接口进行压力测试的时候发现,有个 redis 的查询接口大量的报错,于是查看后台日志,发现是 aioredis 报了Too many connections, 起初我认为是由于在进行压力测试,由于这个接口需要访问 redis 数据,同一时间来了大量的请求,所以会对 redis 服务器造成大量的请求,redis 服务器抗不住返回了Too many connections 错误,但是经过排查不是这样的。


查看详细的报错信息


Traceback (most recent call last):  File "handle_request", line 83, in handle_request    FutureStatic,  File "/app/handlers/test_handler.py", line 67, in get    n = await userdao.getTaskNum()  File "/app/dao/user_dao.py", line 33, in getTaskNum    resutl = await self.request.app.ctx.redis.get("task_num")  File "/usr/local/lib/python3.8/site-packages/aioredis/client.py", line 1082, in execute_command    conn = self.connection or await pool.get_connection(command_name, **options)  File "/usr/local/lib/python3.8/site-packages/aioredis/connection.py", line 1411, in get_connection    connection = self.make_connection()  File "/usr/local/lib/python3.8/site-packages/aioredis/connection.py", line 1449, in make_connection    raise ConnectionError("Too many connections")aioredis.exceptions.ConnectionError: Too many connections
复制代码


查看 aioredis 源代码,


def make_connection(self):    """Create a new connection"""    if self._created_connections >= self.max_connections:        raise ConnectionError("Too many connections")    self._created_connections += 1    return self.connection_class(**self.connection_kwargs)
复制代码


这里报错是由于_created_connections 大于max_connections,这个 max_connections 又是在哪里初始化的呢?


我的代码在初始化 redis 连接池时设置了 max_connections 参数我这里设置成了 50,


def make_redis(redisConf):    '''    redis://[[username]:[password]]@localhost:6379/0            rediss://[[username]:[password]]@localhost:6379/0            unix://[[username]:[password]]@/path/to/socket.sock?db=0    :param redisConf:    :return:    '''    password = redisConf.get("password")    host = redisConf.get("host")    port = redisConf.get("port")    db = redisConf.get("db")    address = f'redis://:{password}@{host}:{port}/{db}'    try:        pool = aioredis.ConnectionPool.from_url(address, max_connections=50)        redis = aioredis.Redis(connection_pool=pool, encoding='utf-8')        return redis    except:        logger.error("连接redis失败")        raise Exception("连接redis失败")
复制代码


于是就有了最大的连接数为 50,也就是我这个系统与 redis 服务器最多会有 50 个连接,redis 的 ConnectionPool 的实例中, 有两个 list,一个是_available_connections, _in_use_connections, 在获取连接的时候从_available_connections 中弹出一个连接放到_in_use_connections


async with self._lock:    try:      connection = self._available_connections.pop()    except IndexError:      connection = self.make_connection()    self._in_use_connections.add(connection)
复制代码


也就是说,当报 Too many connections 时,后台想要去连接 redis 时,如果此时由于访问量太大,前一个请求还没有处理完,这时就要创建一个新的连接,但是如果此时连接数超过了 max_connections 则就会报 Too many connections 错误了!


解决方法也很简单,就是不要设置 max_connections 参数,当不设置该参数的时候,aioreids 将设置为 2 ** 31, 也就是 2 个 31 次方,该值已经非常大。


但是 redis 服务器也不能无限的连接,可以登录到 redis 服务器上,查看 redis 服务器自身可以连接的数量。该值默认为 10000.


在我取消了 aioredis 连接池最大连接数限制以后,再次进行压测


10 threads and 2000 connections  Thread Stats   Avg      Stdev     Max   +/- Stdev    Latency   318.38ms  115.42ms   1.09s    70.99%    Req/Sec   622.78    241.92     1.58k    68.12%  Latency Distribution     50%  309.36ms     75%  377.44ms     90%  453.45ms     99%  711.74ms  60149 requests in 10.02s, 6.48MB readRequests/sec:   6003.59Transfer/sec:    662.51KB
复制代码


这时请求量上去了,可以达到 6K,在查看服务端以后发现上面的 6W 个请求,在服务端只需要大概 500 多个 redis 连接即可。

发布于: 刚刚阅读数: 3
用户头像

杨彦星

关注

还未添加个人签名 2018.08.08 加入

还未添加个人简介

评论

发布
暂无评论
redis中报too many connections错误的解决_redis_杨彦星_InfoQ写作平台