使用Redis中遇到错误:
[ERROR] (DimUtil.java:446) 根据业务时间获取Codis中保存的spIp列表出错,原因:ERR handle response, backend conn failure, bad array len, too long 2019-10-18 14:25:36,422
redis.clients.jedis.exceptions.JedisDataException: ERR handle response, backend conn failure, bad array len, too long
at redis.clients.jedis.Protocol.processError(Protocol.java:117)
at redis.clients.jedis.Protocol.process(Protocol.java:151)
at redis.clients.jedis.Protocol.read(Protocol.java:205)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:297)
at redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:233)
at redis.clients.jedis.Jedis.hgetAll(Jedis.java:796)
at Commons.DimUtil.getSpIp(DimUtil.java:436)
at LocalJob.MigrateJob.execute(MigrateJob.java:188)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
查看代码发现报错的代码块为
Map<String, String> result = jedis.hgetAll(Constant.SPIPTIMEKEY+ servTime);
判断是HgetAll返回的键值对数量过多超过了限制值导致的。
查询Redis 协议里面 BulkBytesArray 数量,发现限制为1024*1024,接近一百万条。
这种情况可以将hgetAll改为扫描方式,对于哈希值,可使用 HSCAN 来迭代哈希键中的键值对。
修改代码:
public List<String> getSpIp(String servTime){
Jedis jedis=null;
......
// Map<String, String> result = jedis.hgetAll(Constant.SPIPTIMEKEY+ servTime);
ScanParams scanParams = new ScanParams();
scanParams.count(500);
Map<String, String> result = scanKeyInJedis(jedis,Constant.SPIPTIMEKEY + servTime,scanParams);
......
}
/**
* 共用扫描节点数据方法
* @param jedis
* @param key
* @param scanParams
* @return
*/
public Map<String, String> scanKeyInJedis(Jedis jedis, String key, ScanParams scanParams) {
long count = 0l ;
Map<String, String> map=new HashMap<>();
try {
String cursor = ScanParams.SCAN_POINTER_START ;
int size = 0 ;
while (true) {
ScanResult<Map.Entry<String, String>> scanResult = jedis.hscan(key, cursor, scanParams);
size = scanResult.getResult().size() ;
count += size ;
cursor = scanResult.getStringCursor() ;
List<Map.Entry<String, String>> results = scanResult.getResult();
for (Map.Entry<String, String> result: results) {
map.put(result.getKey(),result.getValue());
}
if ("0".equals(cursor)) {
break;
}
}
logger.info("======扫描Codis中的Key: "+key+" 成功,总数:" + count);
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
修改后重新部署运行,错误消失,问题解决。