redis 事务(悲观锁和乐观锁)

MULTI

  开启事务,后续的命令会被加入到同一个事务中

  事务中的操作会发送给客服端,但是不会立即执行,而是将操作放到了该事务对应的一个队列中,服务端返回QUEQUD

EXEC

  执行EXEC后,事务中的命令才会执行

  事务中的命令出错时,不会回滚也不会停止,而是继续执行下一步操作

DISCARD

  取消事务,事务队列会被清空

原子性:不支持,不会回滚且继续执行,

隔离性:支持,事务中的命令顺序,不会被打断,先EXEC先执行,单机redis读写操作使用单进程单线程

持久性:不支持,redis 数据容易丢失

一致性:不支持,要求通过乐观锁watch来实现

redis 非 事务型管道:

from redis import StrictRedis

# 创建redis客户端 decode_response = true 从redis中获取的数据会进行decorade,不会是byse类型
redis_client = StrictRedis(host='127.0.0.1',port=6379,db=0,decode_response=True)

# 创建管道  默认就会开启事务,(设置参数,transaction=False,则不会开启事务,只会开启管道)
pipe = redis_client.pipeline(transaction=False)

# 使用管道对象进行的操作
a = pipe.set('name', 'zhangsan')
b = pipe.get('name')

# 不会提交事务  只是将管道打包提交给redis服务器
c = pipe.execute()

print(a, b, c)

 事务型管道:

#创建客服端
redis_client = StrictRedis()

#创建管道,默认会开启事务
pipe = redis_client.pipeline()

#使用管道对象进行操作,都会放入事务中
a = pipe.set('name':'zs')
b = pipe.get('name')

#提交事务,提交事务后才会执行
c = pipe.execute()
print(a,b,c)

乐观锁:watch

  redis实现乐观锁机制

  机制:开启事务前,设置对数据的监听,EXEC时,如果发生数据发生过修改,事务会自动取消(DISCARD)

  事务EXEC后,无论成败,监听会被移除

redis 乐观锁代码:

from redis import StrictRedis, WatchError

# 创建客户端
redis_client = StrictRedis(host='127.0.0.1',port=6379,db=0,)
# 创建管道
pipe = redis_client.pipeline()


while True:
    try:
        # 开启数据的监听  一旦调用watch, 后续操作会立即执行(后续操作不会添加到事务中)
        pipe.watch('reserve_count')

        # 获取库存数量
        count = pipe.get('reserve_count')
        # 判断是否有库存
        if int(count) > 0: # 有库存, 让库存 -1

            # 手动开启事务
            pipe.multi()

            # 库存-1
            pipe.decr('reserve_count')

            # 提交事务
            pipe.execute()
            print('已下单')

        else:  # 没有库存
            print('已售罄')
            # 移除监听
            pipe.reset()

        break

    except WatchError as e:  # 出现该异常, 说明监听的数据被修改了, 重试/取消
        print('重试')

悲观锁: setnx 建不存在才会设置成功

setnx和redis 悲观锁代码   

from redis import StrictRedis

# 创建redis连接
redis_client = StrictRedis(decode_responses=True)

# 设计redis悲观锁 处理秒杀超卖问题

# 先获取锁
while True:
    order_lock = redis_client.setnx('lock:order', 1)
redis_client.expire(
'lock:order', 2) # 给锁设置过期时间, 避免锁释放失败导致死锁现象 if order_lock: reserve_count = redis_client.get('reserve_count') if int(reserve_count) > 0: redis_client.decr('reserve_count') print("生成订单") else: print("已售罄") # 完成处理, 移除锁 redis_client.delete('lock:order') break
原文地址:https://www.cnblogs.com/wjun0/p/11884240.html