分布式锁和Redis事务

分布式锁

一、高并发产生的问题?

  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了,又或者+在错误的类型上,回滚并不能解决。由于无法提供一个避免程序员自己的错误,而这种错误在产品中并不会出现,所以选择一个简单和快速的方法去支持事务

pipeline补充

python使用pipeline()与execute()批量进行批量操

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)

 

posted @ 2019-08-07 17:23  maplethefox  阅读(276)  评论(0编辑  收藏  举报