Redis事务

事务

  • 特点

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

    # 开启事务
    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  # 命令先不执行,直到EXEC
    1) (integer) 1
    2) (integer) 1
    
    DISCARD # 取消事务,清空命令队列
    
  • 为什么redis不支持回滚?
    单进程单线程,极致的追求速度。支持回滚的情况,需要记录存储之前的命令记录。

pipeline 流水线

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

  • 避免大量重复创建,造成资源损耗,先攒一波命令,打包发送服务。

  • 注意:此为客户端技术。

  • python 操作 redis事务

    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() # [True, 51, 151]
    
    # with上下文管理器,结束后可直接关闭
    # transaction是否开启事务,默认True,开启
    with r.pipeline(transaction=true) as pipe
        pipe.multi() # 默认可省略
        pipe.incr("books")
        pipe.incr("books")
        values = pipe.execute()
    

watch - 乐观锁

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

  • 解决资源竞争。

  • 悲观锁:直接上锁,其他人不可修改。

    > watch books
    OK
    > incr books  # 被修改了
    (integer) 1
    > multi
    OK
    > incr books
    QUEUED
    > exec  # 事务执行失败
    (nil)
    
  • python 操作 watch

    #同时对一个账户进行操作, 当前余额 * 2
    import redis
    import time
    
    pool = redis.ConnectionPool(host='127.0.0.1', db=0, port=6379)
    r = redis.Redis(connection_pool=pool)
    
    def get_cache_key(user_id):
    	return 'account_%s' % (user_id)
    
    def double_account(user_id):
        # 信用卡额度
        key = get_cache_key(user_id)
        with r.pipeline() as pipe:
            while True:
                try:
            		pipe.watch(key)
            		value = int(r.get(key))
            		value *= 2
            		print(value)
            		time.sleep(10)
            		pipe.multi()
            		pipe.set(key, value)
            		pipe.execute()
            	except redis.WatchError:
            		print('--watch error--')
            		continue
        		break
        return int(r.get(key))
    
    if __name__ == '__main__':
        user_id = 'Tom'
        r.set(get_cache_key(user_id), 5)
        print(double_account(user_id))
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值