Redis ERR Protocol error: invalid multibulk length

异常信息 

org.springframework.data.redis.RedisConnectionFailureException: ERR Protocol error: invalid multibulk length; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: ERR Protocol error: invalid multibulk length


Caused by: redis.clients.jedis.exceptions.JedisConnectionException: ERR Protocol error: invalid multibulk length
	at redis.clients.jedis.Connection.sendCommand(Connection.java:138) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.jedis.BinaryClient.del(BinaryClient.java:132) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.jedis.BinaryJedis.del(BinaryJedis.java:291) ~[jedis-2.9.0.jar!/:?]
	at org.springframework.data.redis.connection.jedis.JedisKeyCommands.del(JedisKeyCommands.java:121) ~[spring-data-redis-2.1.9.RELEASE.jar!/:2.1.9.RELEASE]
	... 38 more
Caused by: java.net.SocketException: Broken pipe (Write failed)
	at java.net.SocketOutputStream.socketWrite0(Native Method) ~[?:1.8.0_111]
	at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109) ~[?:1.8.0_111]
	at java.net.SocketOutputStream.write(SocketOutputStream.java:153) ~[?:1.8.0_111]
	at redis.clients.util.RedisOutputStream.flushBuffer(RedisOutputStream.java:52) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.util.RedisOutputStream.write(RedisOutputStream.java:76) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.util.RedisOutputStream.write(RedisOutputStream.java:66) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.jedis.Protocol.sendCommand(Protocol.java:100) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.jedis.Protocol.sendCommand(Protocol.java:84) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.jedis.Connection.sendCommand(Connection.java:127) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.jedis.BinaryClient.del(BinaryClient.java:132) ~[jedis-2.9.0.jar!/:?]
	at redis.clients.jedis.BinaryJedis.del(BinaryJedis.java:291) ~[jedis-2.9.0.jar!/:?]
	at org.springframework.data.redis.connection.jedis.JedisKeyCommands.del(JedisKeyCommands.java:121) ~[spring-data-redis-2.1.9.RELEASE.jar!/:2.1.9.RELEASE]
	... 38 more

报错原因: redis 执行条件过长 

错误代码: 


    /**
     * 批量删除
     * @param   prex为迷糊匹配的key,如cache:user:* 
     */
    public void redisDeleteByPrex(String prex) {
        Set keys = redisTemplate.keys(prex);
        if (CollectionUtils.isNotEmpty(keys)) { 
        		redisTemplate.delete(keys); 
        }
    }

这里采用前匹配查询,获取到需要删除的数据超过 1M 所以报错

1M 这个结果来自  redis源码:

/* We know for sure there is a whole line since newline != NULL,
         * so go ahead and find out the multi bulk length. */
        redisAssertWithInfo(c,NULL,c->querybuf[0] == '*');
        ok = string2ll(c->querybuf+1,newline-(c->querybuf+1),&ll);
        if (!ok || ll > 1024*1024) {
            addReplyError(c,"Protocol error: invalid multibulk length");
            setProtocolError(c,pos);
            return REDIS_ERR;
        }

参考: https://blog.csdn.net/sinat_29843547/article/details/77512585

解决方案:

将查询结果分批处理 控制大小在1M内

修改代码如下:

    /**
     * 批量删除
     * @param   prex为迷糊匹配的key,如cache:user:* 
     */
    public void redisDeleteByPrex(String prex) {
        Set keys = redisTemplate.keys(prex);
        if (CollectionUtils.isNotEmpty(keys)) {
        	List list = new ArrayList<>(keys);
        	// 为防止查出的数据过大分批删除  一次10w
        	List> splitList = CommonUtil.splitList(list, 100000);
        	for (List list2 : splitList) {
        		redisTemplate.delete(list2);
			}
        }
    }

你可能感兴趣的:(java,mybatis,开发语言)