Redis事务、乐观锁和悲观锁

本文详细介绍了Redis的事务特性,包括原子性、隔离性、持久性和一致性,并演示了基本的事务操作。同时,讲解了Redis的乐观锁和悲观锁的实现及应用场景,如在秒杀场景中的应用。最后提到了非事务管道的使用,以提高批量操作的效率。
摘要由CSDN通过智能技术生成

1、Redis事务(ACID)

1、原子性:不支持
不会回滚并且继续执行
2、隔离性:支持
事务中命令顺序执行, 并且不会被其他客户端打断 (先EXEC的先执行)
单机redis读写操作使用 单进程单线程
3、持久性:支持, 但相比Mysql, redis数据易丢失
4、一致性:不支持

基本语法

MULTI
开启事务, 后续的命令会被加入到同一个事务中
事务中的操作会发给服务端, 但是不会立即执行, 而是放到了该事务的对应的一个队列中, 服务端返回QUEUED
EXEC
执行EXEC后, 事务中的命令才会被执行
事务中的命令出现错误时, 不会回滚也不会停止事务, 而是继续执行
DISCARD
取消事务, 事务队列会清空, 客户端退出事务状态

2、Redis乐观锁

应用场景:避免并发引起的资源抢夺问题

基本语法
watch
redis实现的乐观锁
机制:
事务开启前, 设置对数据的监听, EXEC时, 如果发现数据发生过修改, 事务会自动取消(DISCARD)
事务EXEC后, 无论成败, 监听会被移除

WATCH mykey  # 监视mykey的值
MULTI  # 开启事务
SET mykey 10  
EXEC  # 如果mykey的值在执行exec之前发生过改变, 则该事务会取消(客户端可以在发生碰撞后不断重试)

代码实现:


# 需求: 使用redis实现秒杀功能 (防止超卖)
from redis import StrictRedis, WatchError

# 1.创建客户端
redis_client = StrictRedis(host='192.168.234.128', port=6381, decode_responses=True)

# 2.创建管道对象
pipe = redis_client.pipeline()

while True:
    try:

        # 3.监听数据  如果开启监听, 则不会开启默认的事务, 后续的pipe操作会立即执行
        pipe.watch('count')

        # 4.读取库存数量
        count = pipe.get('count')

        # 判断库存数量
        if int(count) > 0:  # 有库存, 库存-1
            # 一旦使用watch函数事务不会自动开启
            # 手动开启事务
            pipe.multi()

            # 库存减一
            pipe.decr('count')

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

        else:  # 无库存
            print('商品已售罄')
            # 将监听移除
            pipe.reset()

        break

    except WatchError:  # 捕获到该异常, 说明监听的数据被其他客户端修改, 此时应该重试/取消操作
        print('数据被修改, 重试')
        continue

3、Redis悲观锁

基本语法

SETNX命令
键不存在才会设置成功
多个客户端抢夺, 只有一个可以设置成功(获取锁, 获取操作数据的权限)

from redis import StrictRedis

# 1.创建redis客户端对象
redis_cli = StrictRedis(decode_responses=True)

# 2.构建锁的键
key = "order:lock"

while True:
    # 3.争夺锁资源
    # 争夺到锁资源返回True 否则返回False,参数1是任意值
    lock = redis_cli.setnx(key, 1)

    # 防止忘记删除锁资源,给锁资源添加过期时长 --防止出现死锁
    redis_cli.expire(key, 5)

    # 4.获取库存
    count = redis_cli.get("count")

    # 5.争夺到锁资源的允许操作redis客户端对象进行数据库增删改查
    if lock:
        if int(count) > 0:
            # 减库存
            redis_cli.decr("count")
            print("下单成功")
        else:
            print("库存不足")
            break

        # 6.删除锁--防止死锁
        redis_cli.delete(key)

4、Redis非事务管道

from redis import StrictRedis

# 1.创建redis、客户端对象
redis_cli = StrictRedis(decode_responses=True)

# 2.创建redis管道对象【非事务型管道对象】
# 好处:当需要执行的命令特别多的情况下,使用非事务管道,能够提高执行效率
pipeline = redis_cli.pipeline(transaction=False)

# 3.通过管道对象操作数据库[增删改查]
a = pipeline.set("name3", "小明")
b = pipeline.get("name3")

# 4.执行管道中的命令
c = pipeline.execute()

print(a, b, c)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值