异常信息
org.springframework.data.redis.RedisConnectionFailureException: ERR Protocol error: invalid multibulk length; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: ERR Protocol error: invalid multibulk lengthCaused by: redis.clients.jedis.exceptions.JedisConnectionException: ERR Protocol error: invalid multibulk lengthat 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<String> 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<String> keys = redisTemplate.keys(prex);if (CollectionUtils.isNotEmpty(keys)) {List<String> list = new ArrayList<>(keys);// 为防止查出的数据过大分批删除 一次10wList<List<String>> splitList = CommonUtil.splitList(list, 100000);for (List<String> list2 : splitList) {redisTemplate.delete(list2);}}}