事务定义
逻辑上的一组操作,要么全部执行,要么全部不执行,不可能只执行其中的一部分,从而保证数据的完整性,一致性。
事务特性
A 原子性,事务里的操作必须作为一个整体来执行
C 一致性,事务完成后,数据必须满足一致性
I 隔离性,多个事务同时执行,互不干扰
D 永久性,事务一旦完成,对数据的更改是永久性的
事务的隔离级别
- 读未提交
- 读已提交
- 重复读
- 串行化
redis的事务
redis-cli -h localhost -p 6379
>ping
#开启事务
>multi
#发送命令
>set name jack
>zadd z1 3 a 4 b 2 c
>keys *
>...
以上命令发送给服务器,暂存在服务队列中
>exec/discard #执行所有命令/取消所有命令
常见问题
- 在开启事务后,向服务器发送命令时,若输入错误的命令,则服务器强制discard,取消所有命令
- 在开启事务后,若发送的命令操作了错误的数据类型,则会有中间状态
如:
>multi
>set a 10
>lpush a 100 #操作错误的数据类型
>exec
>get a #会得到10,这里是中间状态
pipeline流水线
仿照redis事务,在客户端将多个命令打包,一次通信发给服务端,减少redis服务的请求数。一种客户端技术
import redis
#创建连接池
pool=redis.ConnectionPool(host="localhost",port=6379,db=0)
#创建连接,并放入连接池
r=redis.Redis(connection_pool=pool)
#创建流水线
pipe=r.pipeline()
#打包命令
pipe.set("age",23)
pipe.lpush("l1","tom","jack","lili")
#发送命令到redis服务,并返回结果
pipe.execute()
Python 操作redis事务
import redis
pool=redis.ConnectionPool(host="localhost",port=6379,db=0)
r=redis.Redis(connection_pool=pool)
with r.pipeline(transaction=True) as pipe:
pipe.multi()
pipe.set("age",23)
pipe.lpush("l1","a","b")
...
pipe.execute()
watch乐观锁
它是解决资源竞争的一种方式,当前进程使用的数据,其他进程也可以访问。
redis事务中,可以监听某个key,操作命令提交到服务队列中,在执行前,若当前的key被其他进程修改,则队列中的命令,在exec时失败(都不执行)。
>set age 10
>watch age
>multi
>set name jack
>set age 20
#在exec之前,另开一个进程,将age的值改位30
>exec #此时,执行失败,返回nil
悲观锁则相反,一个进程在访问的数据,其他进程不能再访问
例子
如一个账户account:“500”,多个人可以对其修改,若A将account改为增加1000–>1500,则B在修改时,需在1500的基础上继续修改。
import redis
pool=reids.ConnectionPool(host="localhost",port=6379,db=0)
r=redis.Redis(connection_pool=pool)
with r.pipeline(transaction=True) as pipe:
while True:
try:
pipe.watch("account")
time.sleep(50)
value=int(r.get("account"))
value+=1000
pipe.multi()
pipe.set("account",value)
pipe.execute()
break
except WatchError:
print("account 已更改")
continue