事务

  1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
  2. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

事务命令

1、MULTI  # 开启事务          mysql   begin
2、命令1  # 执行命令          
3、命令2 ... ...
4、EXEC  # 提交到数据库执行    mysql   commit
4、DISCARD # 取消事务         mysql  'rollback'

使用步骤

# 开启事务
127.0.0.1:6379> MULTI
OK
# 命令1入队列
127.0.0.1:6379> INCR n1
QUEUED
# 命令2入队列
127.0.0.1:6379> INCR n2
QUEUED
# 提交到数据库执行
127.0.0.1:6379> EXEC
1) (integer) 1
2) (integer) 1

事务中命令错误处理

  1. 命令语法错误,命令入队失败,直接自动discard退出这个事务
  • 这个在命令在执行调用之前会发生错误。例如,这个命令可能有语法错误(错误的参数数量,错误的命令名)
  • 处理方案:语法错误则自动执行discard
127.0.0.1:6379[7]> MULTI
OK
127.0.0.1:6379[7]> get a
QUEUED
127.0.0.1:6379[7]> getsss a
(error) ERR unknown command 'getsss'
127.0.0.1:6379[7]> 
127.0.0.1:6379[7]> 
127.0.0.1:6379[7]> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
  1. 命令语法没错,但类型操作有误,则事务执行调用之后失败,无法进行事务回滚
  • 我们执行了一个由于错误的value的key操作(例如对着String类型的value施行了List命令操作)
  • 处理方案:发生在EXEC之后的是没有特殊方式去处理的:即使某些命令在事务中失败,其他命令都将会被执行
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set num 10
QUEUED
127.0.0.1:6379> LPOP num
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> get num
"10"
127.0.0.1:6379> 

pipeline 流水线

批量执行redis命令,减少通信io

import redis
# 创建连接池并连接到redis
pool = redis.ConnectionPool(host = '127.0.0.1',db=0,port=6379)
r = redis.Redis(connection_pool=pool)

pipe = r.pipeline()
pipe.set('fans',50)
pipe.incr('fans')
pipe.incrby('fans',100)
pipe.execute()
  • 性能对比
# 创建连接池并连接到redis
pool = redis.ConnectionPool(host = '127.0.0.1',db=0,port=6379)
r = redis.Redis(connection_pool=pool)

def withpipeline(r):
    p = r.pipeline()
    for i in range(1000):
        key = 'test1' + str(i)
        value = i+1
        p.set(key, value)
    p.execute()

def withoutpipeline(r):
    for i in range(1000):
        key = 'test2' + str(i)
        value = i+1
        r.set(key, value)
  • python操作redis事务
with r.pipeline(transaction=true) as pipe
    pipe.multi()
    pipe.incr("books")
    pipe.incr("books")
    values = pipe.execute()

watch乐观锁

事务过程中,可对指定key进行监听,命令提交时,若被监听key对应的值未被修改时,事务方可提交成功,否则失败

> watch books
OK
> multi
OK
> incr books
QUEUED
> exec  # 事务执行失败
(nil)


watch之后,再开一个终端进入redis
> incr books  # 修改book值
(integer) 1