生产-已解决-Redis连接数占满 报错 (error) ERR max number of clients reached

记一次线上Redis 报错 ERR max number of clients reached ,Redis 宕机生产事故

一、前提交代:

新需求,参与商城品牌首单价促销价格,需要在指定时间内,已购买过指定门槛品牌。
商城内关于商品价格展示接口都需校验改商品关联的促销活动是否参加 品牌首单价门槛促销,商品详情页、订单结算页、商品列表页、购物车预览页。

线上Redis 手动搭建在阿里云linux服务器内,单机版本。且此服务器部署了一台商城服务
注意这里

由于促销活动属于高并发,高流量业务,选择把门槛品牌,门槛购买时间等信息用String 数据结构存储Redis中 数据结构如下

Redis中 BD=2 
String类型  Key:promotion:brand:firstPrice:purchasedBrand:促销活动id

Value:{
    "purchasedBrandList": [
        {
            "brandId": 9710,
            "brandName": "咿儿润"
        }
    ],
    "purchasedEndTime": 1678247960000,
    "purchasedStartTime": 1677643160000,
    "buyStartTime": 1678247960000,
    "buyEndTime": 1678247960000,
    "status": 0
}

二、开发需求

开发需求期间发现前同事写的Redis 操作工具类无法选择指定DB进行存储,默认在db=0

    public <T> T get(String key, String modulePrefix, Class<T> t) {
        checkJedisPool(); // 检测JedisPool 是否为空 
        key = generateKey(key, modulePrefix);// 组装key前缀
        try (Jedis jedis = jedisPool.getResource()) {
            String valueStr = jedis.get(key);
            return parse(valueStr, t);
        }
    }
   private void checkJedisPool() {
        if (jedisPool == null) {
            throw new CacheException("jedisPool can not be null.");
        }
    }

 /**
     * 生成 key .
     *
     * @param key
     * @param modulePrefix
     * @return
     */
    private String generateKey(String key, String modulePrefix) {
        if (StringUtils.isBlank(key)) {
            throw new CacheException("key can not be null.");
        }
        if (StringUtils.isBlank(modulePrefix)) {
            return CacheInfo.MODULE_DEFAULT + ":" + key;
        }
        return modulePrefix + ":" + key;
    }

我写的工具类方法:

   public static String getString(String key, int db) {
        JedisPool pool = getPool();
        Jedis jds = null;
        boolean broken = false;
        String t = null;
        try {
            jds = pool.getResource();
            jds.select(db);
            t = jds.get(key);
        } catch (Exception e) {
            broken = true;
            logger.error("getString:", e);
            throw new RuntimeException(e);
        } finally {
            if (broken) {
                pool.returnBrokenResource(jds);
            } else if (jds != null) {
                pool.returnResource(jds);
            }
        }
        return t;
    }

需求开发完 测试环境,测试验证没问题,开始发版本。

三、发布新版本

我们的集群服务物理机中有一台部署的包专门提供后台管理人员使用,也就是内部人员用。一台专门跑xxl-job 定时任务。
发版平时的流程都为 先发后台机器、与定时任务机器,验证包启动无误再发 商城集群 另外两台。

发完后台机器、定时任务机器,没问题,我一如既往开始发布商城的服务器。
当发完后,半小时后,陆续有运营同学反馈管理后台某些页面加载报错,无法使用。

马上看机器日志,大量的Redis 无法连接错误报出,定时任务机器,商城机器组也开始报错。

我意识到是自己新写的业务代码有问题,马上回滚,但情急之中还是在思考,自己的写的Redis工具类是没问题的,经过了百万生产流量使用的。

把jar包构建好,准备发后台、定时任务机器,后台机器jar无法启动,提示redis 无法连接报错

 (error) ERR max number of clients reached

着急的我,还没等后台机器发完,我那时候就已经把 定时任务机器停止服务。这时候定时任务jar也无法启动,这下可急坏了,因为如果不在晚上12点把定时任务恢复的话就会导致大量定时任务无法运行,后续补任务,补数据可能出现数据重复。

这时,已经开始意识到是由于商品详情页、商品列表页、订单计算页计算价格大量请求Redis 判断是否符合门槛,导致redis过载的原因。

我想把商城机器组代码回滚到上一个版本。我停了一台商城机器,还剩一台机器对外提供商品购买,下单服务。

准备回滚代码,重新发布商城机器1,也无法启动,现在就只有一条机器在扛着流量,说实话,我自己肩膀被压得松软。

四、解决方案

自己的连接Redis查询工具类是肯定没问题,连接用完了也有归还连接词操作。
这时我仔细审查了一下前同事写的Redis工具类,发现连接用完,全都没有归还连接。。。。 这个工具类在 整个工程代码内大量使用。。。。无语死了

    public <T> T get(String key, String modulePrefix, Class<T> t) {
        checkJedisPool();
        key = generateKey(key, modulePrefix);
        try (Jedis jedis = jedisPool.getResource()) {
            String valueStr = jedis.get(key);
            return parse(valueStr, t);
        }
    }

我开始查资料,看Redis启动时的设置的最大连接是多少
我登入redis-cli 客户端,输入命令
在这里插入图片描述
收到的是 连接已经爆满

 (error) ERR max number of clients reached

后面临时修改,将最大连接数调大,查到资料Redis 连接数是取决于物理机最大文件可打开数

在linux 终端直接输入

 ps -ef |grep redis 
cat /proc/5129/limits
// 最大可用连接数
Max open files            10032                10032                files
redis 某时刻已经用了连接数
[root@iZwz9fp1ljg8ksssoyuo0eZ redis-5.0.5]# ll /proc/5129/fd | wc -l 
10008
[root@iZwz9fp1ljg8ksssoyuo0eZ redis-5.0.5]# 

就是说Redis 已经达到现有物理机配置的最大连接数。

1、修改物理机最大连接数后,需要重启机器。
2、商城只有这台redis宿主机在提供对外服务了,重启了就宕机了。

当时情况图:
在这里插入图片描述

晚上八点左右,流量有下降,我重启了N此终于把定时任务机器恢复了。

解决方案

现在已经确定是Redis 物理单机连接数小。
唯一办法就是重启Redis ,重置连接数。此时需要先把最后一台商城服务 停机,要不然Redis再次重启,又会被流量占满连接数。

为了尽量减低商城下单,浏览商品影响范围,选择了十一点后 停止商城服务。
1、停止所有与Redis 交互的服务。
2、重启Redis。
3、版本回退到上一个逻辑代码,重启服务。

后续优化

1、将Redis 迁移为阿里云 TariDB(企业版redis) 集群。可用连接数多,数据有保障
2、优化原有Redis 交互工具类,关闭连接。

参考资料

redis报-ERR max number of clients reached错误

解决Redis 连接池报错:ERR max number of clients reached

解决Redis 连接池报错:ERR max number of clients reached

<think>好的,我现在需要回答用户关于如何强制断开Redis客户端连接的问题。首先,我得回忆一下Redis的相关命令和机制。用户提到的CLIENT KILL命令应该是关键,但需要详细说明如何使用它。 我记得RedisCLIENT KILL命令可以终止指定的客户端连接。需要确认命令的语法和参数,比如IP地址、端口,或者使用其他过滤条件如ID、类型等。另外,用户可能还需要知道如何列出当前连接的客户端,这样才能找到需要断开的目标。所以应该先介绍CLIENT LIST命令,再讲解CLIENT KILL的不同用法。 还要注意权限问题,执行这些命令可能需要管理员权限。此外,Redis是单线程的,如果客户端正在执行命令,断开连接的操作会在命令执行完成后生效,这一点需要明确说明,可能引用到提供的资料中的引用[1]的内容。 用户的问题可能还涉及如何处理连接数达到上限的情况,比如引用[3]中的情况,这时候可能需要先断开一些连接才能进行其他操作。可能需要提到修改最大连接数配置,但用户主要问的是断开连接的命令,所以重点放在CLIENT KILL上。 另外,是否还有其他方法,比如修改配置自动断开空闲连接?比如timeout参数,或者使用CLIENT PAUSE命令,但这些可能超出当前问题的范围,不过可以简要提及作为补充。 需要确保回答结构清晰,分步骤说明,给出具体示例,并引用相关资料中的信息来支持回答的正确性。同时,生成的相关问题要围绕断开连接的方法、查看客户端、处理连接数过载等方向,帮助用户进一步了解。</think>要强制断开Redis的客户端连接,可以通过以下步骤实现: ### 一、使用CLIENT KILL命令 Redis提供了$CLIENT\ KILL$命令来强制断开指定客户端连接,其完整语法为: $$CLIENT KILL [ip:port] [ID client-id] [TYPE type] [USER username] [ADDR ip:port] [SKIPME yes/no]$$ **常用操作示例**: 1. 断开特定IP和端口的连接: ```redis CLIENT KILL 192.168.1.100:63542 ``` 2. 通过客户端ID断开连接(需配合CLIENT LIST使用): ```redis CLIENT KILL ID 12345 ``` 3. 断开所有普通客户端连接(保留副本节点/pubsub等特殊连接): ```redis CLIENT KILL TYPE normal ``` ### 二、查看客户端连接 执行$CLIENT\ LIST$可获取所有连接详情: ```redis 127.0.0.1:6379> CLIENT LIST id=12345 addr=192.168.1.100:63542 fd=6 name= age=1800 idle=5 flags=N db=0 sub=0 ... ``` ### 三、特殊场景处理 1. **连接数爆满时**(出现$ERR\ max\ number\ of\ clients\ reached$错误): - 先临时扩大最大连接数: ```redis CONFIG SET maxclients 10000 ``` - 再断开不需要的连接[^3] 2. **批量断开空闲连接**: ```redis CLIENT KILL TYPE normal SKIPME yes ``` ### 四、注意事项 1. 需要管理员权限执行 2. 正在执行命令的客户端会在当前命令完成后断开[^1] 3. 默认最大连接数由$maxclients$配置控制(默认10000)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

真香号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值