Redis 事务
redis 事务可以一次执行多个命令,并带有三个保证
- exec命令执行前,多个命令被放入队列缓存
- exec命令执行后,缓存队列中的命令顺序执行,一旦有一个有误,不影响其它命令的执行
- 在事务执行过程中,其它客户端提交的命令请求不会插入到当前的缓存命令队列
redis事务执行的三个阶段
- 开启事务(multi)
- 命令入队(queue)
- 执行事务(exec)
redis事务和mysql事务是有区别的
- redis 事务并不具有原子性,一旦事务中(命令队列中)有一命令执行失败,并不影响整个事务的执行
但是redis单条命令具有原子性
- mysql事务具有原子性,在一个事务中,多条命令,一旦有一条执行失败,其它全部失败
实例:
redis事务
1、编译时异常 ,在redis事务中,编译时语法错误,会导致整个事务都不能执行
3、运行时异常 ,在redis事务中,运行时异常,运行时报错,但整体事务依旧能正常执行
事务的ACID原则
事务具有4个特征,分别是原子性、一致性、隔离性和持久性,简称事务的ACID特性;
一、原子性(atomicity)
一个事务要么全部提交成功,要么全部失败回滚,不能只执行其中的一部分操作,这就是事务的原子性
二、一致性(consistency)
事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。
如果数据库系统在运行过程中发生故障,有些事务尚未完成就被迫中断,这些未完成的事务对数据库所作的修改有一部分已写入物理数据库,这是数据库就处于一种不正确的状态,也就是不一致的状态
三、隔离性(isolation)
事务的隔离性是指在并发环境中,并发的事务时相互隔离的,一个事务的执行不能不被其他事务干扰。不同的事务并发操作相同的数据时,每个事务都有各自完成的数据空间,即一个事务内部的操作及使用的数据对其他并发事务时隔离的,并发执行的各个事务之间不能相互干扰。
在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同,分别是:未授权读取,授权读取,可重复读取和串行化
1、读未提交(Read Uncommited),该隔离级别允许脏读取,其隔离级别最低;比如事务A和事务B同时进行,事务A在整个执行阶段,会将某数据的值从1开始一直加到10,然后进行事务提交,此时,事务B能够看到这个数据项在事务A操作过程中的所有中间值(如1变成2,2变成3等),而对这一系列的中间值的读取就是未授权读取
2、授权读取也称为已提交读(Read Commited),授权读取只允许获取已经提交的数据。比如事务A和事务B同时进行,事务A进行+1操作,此时,事务B无法看到这个数据项在事务A操作过程中的所有中间值,只能看到最终的10。另外,如果说有一个事务C,和事务A进行非常类似的操作,只是事务C是将数据项从10加到20,此时事务B也同样可以读取到20,即授权读取允许不可重复读取。
3、可重复读(Repeatable Read)
就是保证在事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻是一致的,因此该事务级别禁止不可重复读取和脏读取,但是有可能出现幻影数据。所谓幻影数据,就是指同样的事务操作,在前后两个时间段内执行对同一个数据项的读取,可能出现不一致的结果。在上面的例子中,可重复读取隔离级别能够保证事务B在第一次事务操作过程中,始终对数据项读取到1,但是在下一次事务操作中,即使事务B(注意,事务名字虽然相同,但是指的是另一个事务操作)采用同样的查询方式,就可能读取到10或20;
4、串行化
是最严格的事务隔离级别,它要求所有事务被串行执行,即事务只能一个接一个的进行处理,不能并发执行。
四、持久性(durability)
一旦事务提交,那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中。--即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束的状态
14、锁 (redis 实现悲观锁和乐观锁)
1、 什么是悲观锁和乐观锁?
- 悲观锁:见名知意,很悲观,担心数据会被修改,对读写操作都上锁,自己用完数据后,就会进行解锁。那么其它线程进行操作时必须等待,效率相对较低。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁、表锁、读锁、写锁等。都是在操作之前先上锁让别人无法操作该数据。
- 乐观锁:顾名思义,很乐观,每次取数据的时候并不担心自己的数据会被修改。数据库实现乐观锁,通常使用的是version(数据版本),来表示数据的。每次取数据的时候,连同数据版本version一起取出。当读取出数据,对数据进行更改时,会将数版本version 加一,然后提交到数据库,此时比较数据版本version,如果提交的数据版本version大于当前数据库对应记录的数据版本version,那么提交成功。否则小于等于都会提交失败。需要重新从数据库取数据。
2、 乐观锁 和悲观锁的 应用场景
- 乐观锁适用于 频繁读取数据的场景,因为读取数据并不会上锁。但是当有大量数据写入的时候,会频繁的提交不成功,会重新读取数据,再提交。
- 悲观锁适用于 频繁写入数据的场景,因为不管是读还是写 都会上锁,如果大量写入数据,为了数据安全上锁是有必要的,相反乐观锁就会大量的读取提交操作。但是当有大量数据读出的时候,效率低下。
3、 redis 实现乐观锁
- redis通过watch实现乐观锁,当对一个key进行监控的时候,客户端A一个事务正在修改key,客户端B已经修改完了key。那么客户端A的当前事务,全部执行失败。因为在事务过程中,key的值已经被修改,当前事务discard(失败),如果新开一个事务是在对key进行操作是没有问题的,并且不开启事务直接执行命令也是没有问题的,因为redis单条命令具有原子性
客户端A
客户端B
一旦监控的key的数据被另一客户端修改,当前客户端 对key的事务操作全部执行失败。