redis的事务与管道
redis的事务与管道
一、redis的管道##
1. 使用管道技术的原因
redis是一个客户端-服务器(CS)模型和请求/响应协议的TCP服务器,使用和http类似的请求响应协议。一个client可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完请求命令后会将结果通过响应报文返回给client。所以,如果一个业务逻辑中需要多次发送redis操作时,每一条命令在网络传输中的往返时延(计算机网络了解一下)会远远大于执行时间,这也是为什么说影响redis性能的最大难题是网络时延。
而管道(pipeline)可以一次性发送多条命令并在执行完后一次性将结果返回,pipeline通过减少客户端与redis的通信次数来实现降低往返延时时间,而且Pipeline 实现的原理是队列,而队列的原理是时先进先出,这样就保证数据的顺序性。
单个执行与管道执行对比图
Redis管道的特点
redis自带的命令行是没有管道技术的,只存在于各个客户端语音中,因为管道作用主要是,客户端在远程操作redis时,减少发送多个命令造成的网络时延TTL。
通过pipeline方式当有大批量的操作时候。我们可以节省很多原来浪费在网络延迟的时间。但是,需要注意到用pipeline方式打包命令发送,redis必须在处理完所有命令前先缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并是不是打包的命令越多越好。此外,pipeline期间将“独占”当前redis连接,此期间将不能进行非“管道”类型的其他操作,直到该pipeline关闭。
pipeline不是原子性的,中间可能会存在部分失败的情况,也就是说不能保证每条命令都能执行成功,如果中间有命令出现错误,redis不会中断执行,而是直接执行下一条命令,然后将所有命令的执行结果(执行成果或者执行失败)放到列表中统一返回,如果需要每条命令都执行成功,我们在批量执行过程中需要监控执行数量和返回的成功数量是否一致。
pipeline管道使用场景
Pipeline在某些场景下非常有用,比如有多个command需要被及时提交,而且他们对相应结果没有互相依赖,对结果响应也无需立即获得,那么pipeline就可以充当这种批处理的工具;
jedis实现demo如下
Pipeline pipeline = conn.pipelined();
for (User user : users){
String age= "age:" + user.getId();
pipeline.incry(age);
}
List<Object> response = pipeline.syncAndReturnAll();
二、redis的简单事务##
如果在EXEC指令被提交之前,Redis-server即检测到提交的某个指令存在语法错误,那么此事务将会被提前标记为DISCARD,此后事务提交也将直接被驳回;但是如果在EXEC提交后,在实施数据变更时(Redis将不会预检测数据类型,比如你对一个“非数字”类型的key执行INCR操作),某个操作导致了ERROR,那么redis仍然不会回滚此前已经执行成功的操作,而且也不会中断ERROR之后的其他操作继续执行。对于开发者而言,你务必关注事务执行后返回的结果(结果将是一个集合,按照操作提交的顺序排列,对于执行失败的操作,结果将是一个ERROR)。