redis事务详解

事务是逻辑上对数据的一组操作,这操作要么一次全部成功或者这操作全部失败,是不可分割的单位

四大特性

原子性,一致性,隔离性,持久性(ACID)

redis的事务

redis是弱事务型数据库,并不具备ACID的全部特性

redis具备隔离性:事务中的所有命令会被序列化,按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断

不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制

事务命令

1,MULTI 开启事务   mysql begin

2,命令1   执行

3,命令2 .。。。。

4-1,EXEC 提交到数据库执行 mysql commit

4-2,DISCARD 取消事务  mysql 'rollback'

开启事务-命令入队列-提交到数据库执行

特殊事务情况-命令语法错误

命令入队失败,直接自动discard退出这个事务

这个命令在执行调用之前会发生错误。例如,这个命令可能有语法错误(错误的参数数量,错误的命令名)

处理方案:语法错误则自动执行discard

命令语法没错,但是类型操作有误,则事务执行调用之后失败,无法进行事务回滚

当我们执行了一个由于错误的value的key操作会出现该现象(例如对着string类型的 value施行list命令操作)

处理方案:发生在EXEC之后的是没有特殊方式去处理的:即使某些命令在事务中失败,其他命令都将会被执行。

 

 

PIPELINE流水线

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

原理:效仿redis的事务,客户端将多个命令打包,一次通信发给redis,可明显降低redis服务的请求数

注意:

1,此为客户端技术

2,如果一组命令中,一个目录需要上一个命令执行结果才可以执行则无法使用该技术

创建redis连接池

import 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()

watch-乐观锁

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

解决资源竞争的一种方式

watch books

multi

incr books

exec

提交失败

watch之后,再开一个终端进入redis

incr books  #修改book值

import redis
pool = redis.ConnectionPool(host = '127.0.0.1',db=0,port=6379)
r = redis.Redis(connection_pool=pool)

#python 操作事务需要依赖流水线技术
with r.pipeline(transaction=True) as pipe:
    pipe.multi()
    pipe.incr('books')
    pipe.incr('books')
    values = pipe.execute()

例子

import redis
pool = redis.ConnectionPool(host = '127.0.0.1',db=0,port=6379)
r = redis.Redis(connection_pool=pool)

def double_account(user_id):

    key = f'account_{user_id}'
    with r.pipeline(transaction=True) as pipe:
        while True:
            try:
                pipe.watch(key)
                value=int(r.get(key))
                value*=2
                pipe.multi()
                pipe.set(key,value)
                pipe.execute()
            except redis.WatchError:
                print('---key changed')
                continue
    return  int(r.get(key))

if __name__ == '__main__':
    print(double_account('xxxx'))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值