分布式锁
一、高并发产生的问题?
1、购票: 多个用户抢到同一张票?
2、购物: 库存只剩1个,被多个用户成功买到?
... ...
二、怎么办
在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段
三、原理
1、多个客户端先到redis数据库中获取一把锁,得到锁的用户才可以操作数据库
2、此用户操作完成后释放锁,下一个成功获取锁的用户再继续操作数据库
四、实现
set key value nx ex 3
Redis事务
一特点
1. 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断
2. 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制
二事务命令
1、MULTI # 开启事务
2、命令1 # 执行命令
3、命令2 ... ...
4、EXEC # 提交到数据库执行
4、DISCARD # 取消事务
三使用步骤
# 开启事务 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
四事务中命令错误处理
# 1、命令语法错误,命令入队失败,直接自动discard退出这个事务 这个在命令在执行调用之前会发生错误。例如,这个命令可能有语法错误(错误的参数数量,错误的命令名) 处理方案:客户端发生了第一个错误情况,在exec执行之前发生的。通过检查队列命令返回值:如果这个命令回答这个队列的命令是正确的,否则redis会返回一个错误。如果那里发生了一个队列命令错误,大部分客户端将会退出并丢弃这个事务 # 2、命令语法没错,但类型操作有误,则事务执行调用之后失败,无法进行事务回滚 从我们施行了一个由于错误的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>
五为什么redis不支持事务回滚
1、Redis的内部极其简单和快速,来源于它不需要回滚功能
2、在生产环境中,通常回滚并不能解决来自编程的错误。举个例子,你本来想+1,却+2了,又或者+在错误的类型上,回滚并不能解决。由于无法提供一个避免程序员自己的错误,而这种错误在产品中并不会出现,所以选择一个简单和快速的方法去支持事务
import redis # 创建连接池并连接到redis pool = redis.ConnectionPool(host = '192.168.153.130',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() # 第二组 pipe.get('fans') pipe.get('pwd') # [b'151', b'123'] result = pipe.execute() print(result)