事务
- 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
- 不保证原子性: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
事务中命令错误处理
- 命令语法错误,命令入队失败,直接自动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.
- 命令语法没错,但类型操作有误,则事务执行调用之后失败,无法进行事务回滚
- 我们执行了一个由于错误的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
最后一次更新于2023-03-10 16:28
0 条评论