1. Pipeline:“管道”,和很多设计模式中的“管道”具有同样的概念,pipleline的操作,将明确client与server端的交互,都是“单向的”:你可以将多个command,依次发给server,但在此期间,你将无法获得单个command的响应数据,此后你可以关闭“请求”,然后依次获取每个command的响应结果。

    从简单来说,在IO操作层面,对于client而言,就是一次批量的连续的“write”请求,然后是批量的连续的“read”操作。其实对于底层Socket-IO而言,对于client而言,只不过是多次write,然后一次read的操作;对于server端,input通道上read到数据之后,就会立即被实施,也会和非pipeline一样在output通道上输出执行的结果,只不过此时数据会被阻塞在网络缓冲区上,直到client端开始read或者关闭链接。神秘的面纱已被解开,或许你也能创造一个pipeline的实现。

    非pipleline模式:

    Request---->执行

    ---->Response

    Request---->执行

    ---->Response
Pipeline模式下: Request---->执行,Server将响应结果队列化 Request---->执行,Server将响应结果队列化 ---->Response ---->Response Client端根据Redis的数据协议,将响应结果进行解析,并将结果做类似于“队列化”的操作。   不过需要明确一下,pipeline和“事务”是两个完全不同的概念,pipeline只是表达“交互”中操作的传递的方向性,pipeline也可以在事务中运行,也可以不在。无论如何,pipeline中发送的每个command都会被server立即执行,如果执行失败,将会在此后的相应中得到信息;也就是pipeline并不是表达“所有command都一起成功”的语义;但是如果pipeline的操作被封装在事务中,那么将有事务来确保操作的成功与失败(事实上,Redis的事务,仍然不像严格意义上的事务,稍后介绍)。 Pipeline在某些场景下非常有用,比如有多个command需要被“及时的”提交,而且他们对相应结果没有互相依赖,而且对结果响应也无需立即获得,那么pipeline就可以充当这种“批处理”的工具;而且在一定程度上,可以较大的提升性能,性能提升的原因主要是TCP链接中较少了“交互往返”的时间。

不过在编码时请注意,pipeline期间将“独占”链接,此期间将不能进行非“管道”类型的其他操作,直到pipeline关闭;比如在上述代码中间,使用jedis.set(key,value)等操作都将抛出异常。


如果你的pipeline的指令集很庞大,为了不干扰链接中的其他操作,你可以为pipeline操作新建Client链接,让pipeline和其他正常操作分离在2个client中。不过pipeline事实上所能容忍的操作个数,和socket-output缓冲区大小/返回结果的数据尺寸都有很大的关系;同时也意味着每个redis-server同时所能支撑的pipeline链接的个数,也是有限的,这将受限于server的物理内存或网络接口的缓冲能力。



使用场景举例:因为业务需要,我们需要把用户的操作过程记录在日志中以方便以后的统计,每隔3个小时生成一个新的日志文件,那么后台处理线程,将会扫描日志文件并将每条日志输出为“operation”:1,即表示操作次数为1;如果每个operation都发送一个command,事实上性能是很差的,而且是没有必要的;那么我们就可以使用pipeline批量提交即可。

2.Transaction(事务):

    Redis提供了简单的“事务”能力,MULTI,EXEC,DISCARD,WATCH/UNWATCH指令用来操作事务。

    1) MUTIL:开启事务,此后所有的操作将会添加到当前链接的事务“操作队列”中。

    2) EXEC:提交事务

    3) DISCARD:取消事务,记住,此指令不是严格意义上的“事务回滚”,只是表达了“事务操作被取消”的语义,将会导致事务的操作队列中的操作不会被执行,且事务关闭。

    4) WATCH/UNWATCH:“观察”,这个操作也可以说是Redis的特殊功能,但是也可说是Redis不能提供“绝对意义上”的事务能力而增加的一个“补充特性”(比如事务隔离,多事务中操作冲突解决等);在事务开启前,可以对某个KEY注册“WATCH”,如果在事务提交后,将会首先检测“WATCH”列表中的KEY集合是否被其他客户端修改,如果任意一个KEY 被修改,都将会导致事务直接被“DISCARD”;即使事务中没有操作某个WATCH KEY,如果此KEY被外部修改,仍然会导致事务取消。事务执行成功或者被DISCARD,都将会导致WATCH KEY被“UNWATCH”,因此事务之后,你需要重新WATCH。WATCH需要在事务开启之前执行。

    WATCH所注册的KEY,事实上无论是被其他Client修改还是当前Client修改,如果不重新WATCH,都将无法在事务中正确执行。WATCH指令本身就是为事务而生,你或许不会在其他场景下使用WATCH;

   Redis中,如果一个事务被提交,那么事务中的所有操作将会被顺序执行,且在事务执行期间,其他client的操作将会被阻塞;Redis采取了这种简单而“粗鲁”的方式来确保事务的执行更加的快速和更少的外部干扰因素。


EXEC指令将会触发事务中所有的操作被写入AOF文件(如果开启了AOF),然后开始在内存中实施这些数据变更操作;Redis将会尽力确保事务中所有的操作都能够执行,如果redis环境故障,有可能导致事务未能成功执行,那么需要在redis重启后增加额外的校验工作。


如果在EXEC指令被提交之前,Redis-server即检测到提交的某个指令存在语法错误,那么此事务将会被提前标记为DISCARD,此后事务提交也将直接被驳回;但是如果在EXEC提交后,在实施数据变更时(Redis将不会预检测数据类型,比如你对一个“非数字”类型的key执行INCR操作),某个操作导致了ERROR,那么redis仍然不会回滚此前已经执行成功的操作,而且也不会中断ERROR之后的其他操作继续执行。对于开发者而言,你务必关注事务执行后返回的结果(结果将是一个集合,按照操作提交的顺序排列,对于执行失败的操作,结果将是一个ERROR)。


Redis的事务之所以如此设计,它为了确保本身的性能,同时不引入“关系型数据库”的设计复杂度;你不能完全希望Redis能为你交付完美的事务操作,只能说,你选择了错误的工具。

 

参考:https://shift-alt-ctrl.iteye.com/blog/1863790

redis pipline 和 事务的更多相关文章

  1. Redis系列之key操作命令与Redis中的事务详解(六)

    序言 本篇主要目的有二: 1.展示所有数据类型中key的所有操作命令,以供大家学习,查阅,更深入的挖掘redis潜力. 2.掌握redis中的事务,让你的数据完整性一致性拥有更优的保障. redis命 ...

  2. Redis 中的事务

    Redis支持简单的事务 Redis与mysql事务的对比 Mysql Redis 开启 start transaction muitl 语句 普通sql 普通命令 失败 rollback 回滚 di ...

  3. redis中的事务

    首先明白在java中线程和进程的区别: 1.什么是多线程? 是指一个应用程序同时执行多个任务,一般来说一个任务就是一个线程 ,而一个应用程序有一个以上的线程我们称之为多线程. 2.什么是进程? 进程是 ...

  4. Redis 学习(三) —— 事务、消息发布订阅

    一.Redis事务 Redis 提供的事务机制与传统的数据库事务有些不同,传统数据库事务必须维护以下特性:原子性(Atomicity), 一致性(Consistency),隔离性(Isolation) ...

  5. Redis数据库 02事务| 持久化| 主从复制| 集群

    1. Redis事务 Redis不支持事务,此事务不是关系型数据库中的事务: Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化.按顺序地执行.事务在执行的过程中,不会被其他客户端发送来的 ...

  6. 三、redis系列之事务

    1. 绪言 Redis也提供了事务机制,可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许加塞.但Redis对事务的支持是部分支持 ...

  7. redis的简单事务

    Redis对事务的支持目前还比较简单.Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令.当一个client在一个连接中发出multi命令时,这个 ...

  8. 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存

    原文:http://blog.csdn.net/heyewu4107/article/details/71009712 高并发场景系列(一) 利用redis实现分布式事务锁,解决高并发环境下减库存 问 ...

  9. redis中的事务(版本2.6.16)

    一.命令支持 1.multi 开始事务 2.exec事务提交 3.取消事务discard 二.事务示例 1.示例 redis>set key1 20OKredis>mutilOKredis ...

随机推荐

  1. POSTGRESQL中ERROR: recursive query "t" column 2 has type character varying(150) in non-recursive term but type character varying overall

    最近在做项目的时候有个需求是需要查到当前登录的用户下辖所有区域的数据,并将查询出来的部门信息以如下格式展示 最高人民法院>江苏省高级人民法院>南通市中级人民法院最高人民法院>江苏省高 ...

  2. JVM(一):方法区

    方法区(Method Area) 在JVM中,类型信息和类静态变量都保存在方法区中,需要注意的一点是,常量池也存放于方法区中. 类型信息包括: 1.类型的全名(The fully qualified ...

  3. Failed to load driver class com.mysql.jdbc.Driver from HikariConfig class classloader sun.misc.Launcher$AppClassLoader@18b4aac2

    1.错误日志 Failed to load driver class com.mysql.jdbc.Driver from HikariConfig class classloader sun.mis ...

  4. [LeetCode] 236. Lowest Common Ancestor of a Binary Tree_ Medium tag: DFS, Divide and conquer

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  5. PHP----------php-fpm进程数的一些相关配置

    1.其中pm.max_children如何配置:pm.max_children 数量的多少根据机器内存确定,基本上一个进程需要30M的内存,假设起100个进程,那么就是3000M,3G内存. 2.pm ...

  6. phpcms网页替换验证码功能 及 搜索功能

    在使用phpcms替换网页的时候,除了正常的替换栏目.内容页等,其他的什么验证码啦,提交表单了,搜索功能了,这些在替换的时候可能会对一些默认文件有一些小小 的改变 下面就是自己在失败中成功的过程,最后 ...

  7. linux下git服务器安装

    git服务器配置http://www.cnblogs.com/dee0912/p/5815267.html git教程https://www.liaoxuefeng.com/wiki/00137395 ...

  8. scrapy流程图

    refer:https://blog.yongli1992.com/2015/02/08/python-scrapy-module/ 这里是一张Scrapy架构图的展示.Scrapy Engine负责 ...

  9. JavaScript 原型链学习(四)原型链的基本概念、原型链实现继承

    简单回顾一下构造函数.原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针.那么,假如我们让原型对象等于另一个类型的实例,结果会 ...

  10. IP通信基础学习第一周

    在IP方向上,IP通信基础是学习其他诸如:数字程教控交换技术与应用.IPV6技术与应用.SDH传输技术与应用等课程的基础. 学习IP通信基础,对学生而言至少可以拿学分,不仅有利于以后的学习,还有机会从 ...