事务
-
特点
- 单独的隔离操作:事务中的所有命令会被序列化、按顺序执行,在执行的过程中不会被其他客户端发送来的命令打断。
- 不保证原子性:redis中的一个事务中如果存在命令执行失败,那么其他命令依然会被执行,没有回滚机制。
-
事务命令
# 开启事务 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 # 命令先不执行,直到EXEC 1) (integer) 1 2) (integer) 1 DISCARD # 取消事务,清空命令队列
-
为什么redis不支持回滚?
单进程单线程,极致的追求速度。支持回滚的情况,需要记录存储之前的命令记录。
pipeline 流水线
-
批量执行redis命令,减少io通信。
-
避免大量重复创建,造成资源损耗,先攒一波命令,打包发送服务。
-
注意:此为客户端技术。
-
python 操作 redis事务
import redis # 创建连接池并连接到redis pool = redis.ConnectionPool(host = '127.0.0.1',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() # [True, 51, 151] # with上下文管理器,结束后可直接关闭 # transaction是否开启事务,默认True,开启 with r.pipeline(transaction=true) as pipe pipe.multi() # 默认可省略 pipe.incr("books") pipe.incr("books") values = pipe.execute()
watch - 乐观锁
-
作用:事务过程中,可对指定key进行监听,命令提交时,若被监听key对应的值未被修改时,事务方可提交成功,否则失败。
-
解决资源竞争。
-
悲观锁:直接上锁,其他人不可修改。
> watch books OK > incr books # 被修改了 (integer) 1 > multi OK > incr books QUEUED > exec # 事务执行失败 (nil)
-
python 操作 watch
#同时对一个账户进行操作, 当前余额 * 2 import redis import time pool = redis.ConnectionPool(host='127.0.0.1', db=0, port=6379) r = redis.Redis(connection_pool=pool) def get_cache_key(user_id): return 'account_%s' % (user_id) def double_account(user_id): # 信用卡额度 key = get_cache_key(user_id) with r.pipeline() as pipe: while True: try: pipe.watch(key) value = int(r.get(key)) value *= 2 print(value) time.sleep(10) pipe.multi() pipe.set(key, value) pipe.execute() except redis.WatchError: print('--watch error--') continue break return int(r.get(key)) if __name__ == '__main__': user_id = 'Tom' r.set(get_cache_key(user_id), 5) print(double_account(user_id))