Redis事务没有事务隔离的级别。
但是Redis事务的本质是:将一组操作放入队列(先进先出)中,批量执行。
关系型数据库的事务是:将事务操作(DML)语句写入日志。
事务相关的命令
- Multi:开启事务
- Exec:执行事务
- Discard:终止事务
说明:Exec之前的事务操作可以被discard终止 但是一旦exec 本次事务就会执行!
如果一次事务操作的组队过程中出现的错误(如 正确命令是set money 100 你写成了 sett money 100),本次事务的所有命令都不会执行!!
Redis不保证原子性,Exec程序执行过程,某命令出错(比如数据库只允许存入数字,但你插入了字符),错误代码不执行,其余的正常代码依旧可以正常执行!
Redis 如何实现事务呢?
- 开启一个队列
- 让命令进入队列
- 执行事务
# 1 开启事务
multi
# 2 输入命令
set k1 v1
set k2 v2
get k2
set k2 v3
get k2
# 3 执行/放弃事务 (如果任何命令输错了,所有命令就不会执行,并且放弃事务!)
exec 或者 discard
Redis 悲观锁
效率低,所有悲观锁都不建议使用
悲观锁:每次都会操作都会上锁,执行完毕就会释放锁,别人才可以获得锁。这样会导致效率低下,降低并发量。
Redis CAS乐观锁 watch操作
乐观锁,任何人操作都不上锁,但是真实操作时,如果这个key发现version变动了,本次修改的相关事务操作不会执行!所有人都可以拿到锁,就可以提高系统吞吐量
Redis 乐观锁的使用场景是:电影院购票,比如C1这个作为有多人同时去抢,这张票只能被一个人抢成功。使用Redis乐观锁的好处是。抢的时候,先锁一下这个C1座位,等于被我预定了,如果发现C1被别人抢走了,本次事务将不会执行。
代码语言:javascript复制# 先创建一个key money = 100
set money 100
# watch 就是乐观锁 注意 watch一定要在一个线程的事务之前!!!
watch 需要锁Key名
# 线程1 操作:开启事务,并设置money为80 但不执行事务
multi
set money 80 或者 decrby money 20
# 线程2 操作:读取money 设置money 为120
get money
set money 120 或者 incrby money 20
# 线程1 执行事务
exec
# 一个线程 watch 并执行事务 失败时,一定要unwatch
unwatch
最后的结果是nil ,说明乐观锁生效了!
原理分析:
一个事务占着一个A线程执行操作时:发现被另一个B线程修改了相关的内容,就会导致乐观锁执行!导致事务A操作不会执行。
特殊说明: 解决问题的光鲜,藏着磕Bug的痛苦。 万物皆入轮回,谁也躲不掉! 以上文章,均是我实际操作,写出来的笔记资料,不会出现全文盗用别人文章!烦请各位,请勿直接盗用!