错误原因
transaction错误使用
pipeline错误使用
具体分析
transaction错误使用
- Redis事务的执行结果是在exec之后才统一返回,所以Jedis会用一个Response对象最为事务对象transaction的执行放回值。如果我们在transaction执行exec方法之前调用response对象的get方法会出现异常:
- Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: Please close pipeline or multi block before calling this method.
- 更多Redis事务操作,请移步:Redis事务:用法,常见错误和API_琦彦-CSDN博客
pipeline错误使用
1.异常堆栈
redis.clients.jedis.exceptions.JedisDataException: Please close pipeline or multi block before calling this method.
2.异常描述:
在pipeline.sync()执行之前,通过response.get()获取值,在pipeline.sync()执行前,命令没有执行(可以通过monitor做验证),下面代码就会引起上述异常
Jedis jedis = new Jedis("127.0.0.1", 6379); Pipeline pipeline = jedis.pipelined(); pipeline.set("hello", "world"); pipeline.set("java", "jedis"); Response<String> pipeString = pipeline.get("java"); //这个get必须在sync之后,如果是批量获取值建议直接用List<Object> objectList = pipeline.syncAndReturnAll(); System.out.println(pipeString.get()); //命令此时真正执行 pipeline.sync();
Jedis中Reponse中get()方法,有个判断:如果set=false就会报错,而response中的set初始化为false.
public T get() { // if response has dependency response and dependency is not built, // build it first and no more!! if (dependency != null && dependency.set && !dependency.built) { dependency.build(); } if (!set) { throw new JedisDataException( "Please close pipeline or multi block before calling this method."); } if (!built) { build(); } if (exception != null) { throw exception; } return response; }
pipeline.sync()会每个结果设置set=true。
public void sync() { if (getPipelinedResponseLength() > 0) { List<Object> unformatted = client.getAll(); for (Object o : unformatted) { generateResponse(o); } } }
其中generateResponse(o):
protected Response<?> generateResponse(Object data) { Response<?> response = pipelinedResponses.poll(); if (response != null) { response.set(data); } return response; }
其中response.set(data);
public void set(Object data) { this.data = data; set = true; }
3.解决方法:
实际上对于批量结果的解析,建议使用pipeline.syncAndReturnAll()来实现,下面操作模拟了批量hgetAll
/** * pipeline模拟批量hgetAll * @param keyList * @return */ public Map<String, Map<String, String>> mHgetAll(List<String> keyList) { // 1.生成pipeline对象 Pipeline pipeline = jedis.pipelined(); // 2.pipeline执行命令,注意此时命令并未真正执行 for (String key : keyList) { pipeline.hgetAll(key); } // 3.执行命令 syncAndReturnAll()返回结果 List<Object> objectList = pipeline.syncAndReturnAll(); if (objectList == null || objectList.isEmpty()) { return Collections.emptyMap(); } // 4.解析结果 Map<String,Map<String, String>> resultMap = new HashMap<String, Map<String,String>>(); for (int i = 0; i < objectList.size(); i++) { Object object = objectList.get(i); Map<String, String> map = (Map<String, String>) object; String key = keyList.get(i); resultMap.put(key, map); } return resultMap; }
4.处理人:
修改业务代码。