原文

Redis提供了5种数据结构,但除此之外,Redis还提供了注入慢查询分析,Redis Shell、Pipeline、事务、与Lua脚本、Bitmaps、HyperLogLog、PubSub、GEO等附加功能,这些功能可以在某些场景发挥很重要的作用.

Pipeline

1. Pipeline概念

Redis客户端执行一条命令分为以下四个步骤:

1.发送命令
2.命令排队
3.命令执行
4.返回结果

其中,第一步+第四步称为Round Trip Time(RTT,往返时间).

Redis提供了批量操作命令(例如mget,mset等),有效的节约RTT.但大部分命令是不支持批量操作的,例如要执行nhgetall命令,并没有mhgetall存在,需要消耗nRTT.Redis的客户端和服务端可能不是在不同的机器上.例如客户端在北京,Redis服务端在上海,两地直线距离为1300公里,那么1次RTT时间=1300×2/(300000×2/3)=13毫秒(光在真空中传输速度为每秒30万公里,这里假设光纤的速度为光速的2/3),那么客户端在1秒内大约只能执行80次左右的命令,这个和Redis的高并发高吞吐背道而驰.

Pipeline(流水线)机制能改善上面这类问题,它能将一组Redis命令进行组装,通过一次RTT传输给Redis,再将这组Redis命令按照顺序执行并装填结果返回给客户端.图1.1中未使用Pipeline执行了n次命令,整个过程需要n个RTT.

Pipeline并不是什么新的技术和机制,很多技术上都使用过.而且RTT在不同网络环境下会有不同,例如同机房和同机器会比较快,跨机房跨地区会比较慢.Redis命令真正执行的时间通常在微秒级别,所以才会有Redis性能瓶颈是网络这样的说法.

2. 原生批量命令与Pipeline对比

可以使用Pipeline模拟出批量操作的效果,但是在使用时需要质疑它与原生批量命令的区别,具体包含几点:

  • 原生批量命令是原子性,Pipeline是非原子性的.
  • 原生批量命令是一个命令对应多个key,Pipeline支持多个命令.
  • 原生批量命令是Redis服务端支持实现的,而Pipeline需要服务端与客户端的共同实现.

3. Pipeline总结

Pipeline虽然好用,但是每次Pipeline组装的命令个数不能没有节制,否则一次组装Pipeline数据量过大,一方面会增加客户端的等待时机,另一方面会造成一定的网络阻塞,可以将一次包含大量命令的Pipeline拆分成多次较小的Pipeline来完成.

Pipeline只能操作一个Redis实例,但即使在分布式Redis场景中,也可以作为批量操作的重要优化方法.

事务

为了保证多条命令组合的原子性,Redis提供了简单的事务以及集成Lua脚本来解决这个问题.

熟悉关系型数据库的开发者应该对事务比较了解,简单地说,事务表示一组动作,要么全部成功,要不全部不成功.例如在在电商网站中用户购买商品A那么需要将商品A的库存-1,并创建一个订单.这两个操作要么远不执行成功,要么全部执行不成功,否则会出现数据不一致的情况.

Redis提供了简单的功能,将一组需要一起执行的命令放到multiexec两个命令之间.multi命令代表事务的开始,exec命令代表事务结束,他们之间的命令是原子顺序执行的.
例如上述的用户购买商品问题:

    127.0.0.1:6379> multi
OK
127.0.0.1:6379> hincrby commodity:a:detail stock -1
QUEUE
127.0.0.1:6379> rpush user:1:orders {"commodity":'a',..}
QUEUE

可以看到数据操作命令返回的结果是QUEUE,代表命令并没有真正执行,而是暂时保存在Redis中.如果此时另一个客户端执行llen user:1:orders返回结果为0.

    127.0.0.1:6379> llen user:1:orders
(integer) 0

只有当exec执行后,用户购买商品的行为才算完成,如下两个结果对应hincrbyrpush命令.

    127.0.0.1:6379> exec
1) (integer) 4 # 商品原库存为5
2) (integer) 1
127.0.0.1:6379> llen user:1:orders
(integer) 1

如果要停止事务的执行,可以使用discard命令替代exec命令即可.

    127.0.0.1:6379> discard
OK
127.0.0.1:6379> llen user:1:orders
(integer) 0

如果事务中的命令出现错误,Redis的处理机制也不尽相同.

1.命令错误
例如下面操作错将set写成了sett,属于语法错误,会造成整个事务无法执行,keycounter的值未发生变化:

    127.0.0.1:6379> mget key counter
1) "hello"
2) "100"
127.0.0.1:6379> multi
OK
127.0.0.1:6379> sett key world
(error) ERR unknown command 'sett'
127.0.0.1:6379> incr counter
QUEUE
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> mget key counter
1) "hello"
2) "100"

2.运行时错误
例如用户购买商品,误把rpush写成了zadd

    127.0.0.1:6379> multi
OK
127.0.0.1:6379> hincrby commodity:a:detail stock -1
QUEUED
127.0.0.1:6379> zadd user:1:orders {"commodity":'a',..}
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value.
127.0.0.1:6379> hget commodity:a:detail stack
(integer) 3

可以看到Redis并不支持回滚功能,hincrby commodity:a:detail stock -1命令已经执行成功,开发者需要自己修改这类问题.

redis学习笔记 - Pipeline与事务的更多相关文章

  1. Redis学习笔记7--Redis管道(pipeline)

    redis是一个cs模式的tcp server,使用和http类似的请求响应协议.一个client可以通过一个socket连接发起多个请求命令.每个请求命令发出后client通常会阻塞并等待redis ...

  2. redis 学习笔记(6)-cluster集群搭建

    上次写redis的学习笔记还是2014年,一转眼已经快2年过去了,在段时间里,redis最大的变化之一就是cluster功能的正式发布,以前要搞redis集群,得借助一致性hash来自己搞shardi ...

  3. Redis学习笔记~目录

    回到占占推荐博客索引 百度百科 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合). ...

  4. Redis学习笔记之ABC

    Redis学习笔记之ABC Redis命令速查 官方帮助文档 中文版本1 中文版本2(反应速度比较慢) 基本操作 字符串操作 set key value get key 哈希 HMSET user:1 ...

  5. (转)redis 学习笔记(1)-编译、启动、停止

    redis 学习笔记(1)-编译.启动.停止   一.下载.编译 redis是以源码方式发行的,先下载源码,然后在linux下编译 1.1 http://www.redis.io/download 先 ...

  6. Redis 学习笔记4: Redis 3.2.1 集群搭建

    在CenOS 6.7 linux环境下搭建Redis 集群环境 1.下载最新的Redis版本 本人下载的Redis版本是3.2.1版本,下载之后,解压,编译(make): 具体操作可以参考我的博文:R ...

  7. Redis学习笔记(1)——Redis简介

    一.Redis是什么? Remote Dictionary Server(Redis) 是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value ...

  8. redis学习笔记(3)

    redis学习笔记第三部分 --redis持久化介绍,事务,主从复制 三,redis的持久化 RDB(Redis DataBase)AOF(Append Only File) RDB:在指定的时间间隔 ...

  9. redis 学习笔记-cluster集群搭建

    一.下载最新版redis 编译 目前最新版是3.0.7,下载地址:http://www.redis.io/download 编译很简单,一个make命令即可,不清楚的同学,可参考我之前的笔记: red ...

随机推荐

  1. How to Check some table was locked

    select * from sys.sysprocesses where blocked<>0  看看waittime是不是很大  kill spid

  2. PHP结巴程序实现

    <?php $str="我...我要要要...学学学..编编程"; $str=preg_replace('/\./','',$str);//我我要要要学学学编编程 $str= ...

  3. VM里面的桥接

      今天我们谈一谈桥接模式,一般的时候,我用的是NAT模式,需要设置另一个虚拟网卡的IP地址,而不是借助本机的物理网卡.   编辑---虚拟网络编辑器 有些时候直接设置桥接到某个网卡可能会不成功,我们 ...

  4. SQL优化的一些总结 SQL编写一般要求

    SQL编写一般要求---SQL语句尽可能简单---分解联接保证高并发---同数据类型的列值比较---不在索引列做运算---禁止使用SELECT *---避免负向查询和%前缀模糊查询---保持事务(连接 ...

  5. Mysql查询结果只有一条的情况下把值赋值给变量,再用if else 流程判断

    BEGIN set @n=(SELECT count(day) from log where day=CURDATE()); THEN call m_LogInsert(); ELSE call m_ ...

  6. The return types for the following stored procedures could not be detected

    1.使用dbml映射数据库,添加存储过程到dbml文件时报错. 2.原因:存储过程中使用了临时表 3.解决方案 3.1 通过自定义表值变量实现 Ex: DECLARE @TempTable TABLE ...

  7. 【整理】mysql中information_schema.tables字段说明

    [整理]mysql中information_schema.tables字段说明 2016-05-04 16:47:50|  分类: 默认分类|举报|字号 订阅     下载LOFTER我的照片书  | ...

  8. shell去掉后缀方法

    #!/bin/bash olddir=/home/img/luimg newdir=/home/img/luimg/thumb while read line do if [ -f $olddir${ ...

  9. px值转rem值的Sublime Text 3自己主动完毕插件

    一个CSS的px值转rem值的Sublime Text 3自己主动完毕插件. 插件效果例如以下: 安装 克隆项目   https://github.com/hyb628/cssrem.git 进入pa ...

  10. servlet文件下载2(单文件下载和批量下载)

    使用servlet完毕单文件下载和批量文件下载.批量下载的原理是先将文件打包成zip , 然后再下载. 之前也转载过一篇文件下载的博客,地址:http://blog.csdn.net/ch717828 ...