1. 事务描述
(1)什么是事务
事务,就是把一堆事情绑在一起,按顺序的执行,都成功了才算完成,否则恢复之前的样子
事务必须服从ACID原则,ACID原则分别是原子性(atomicity)、一致性(consistency)、隔离性(isolation)和持久性(durability)
原子性:操作这些指令时,要么全部执行成功,要么全部不执行。只要其中一个指令执行失败,所有的指令都执行失败,数据进行回滚,回到执行指令前的数据状态
一致性:事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定
隔离性:在该事务执行的过程中,无论发生的任何数据的改变都应该只存在于该事务之中,对外界不存在影响,只有在事务确认提交之后们才会显示该事务对数据的改变,其他事务才能获取到这些改变后的数据
持久性:当事务正确完成后,它对于数据的改变是永久性的
(2)什么是事务
第一类丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖
脏读:一个事务读取到另一个事务未提交的更新数据
幻读:一个事务执行两次查询,第二次结果集包含第一次中没有或某些行已经被删除的数据,造成两次结果不一致,只是另一个事务在这两次查询中间插入或删除了数据造成的
不可重复读:一个事务两次读取同一行的数据,结果得到不同状态的结果,中间正好另一个事务更新了该数据,两次结果相异,不可被信任
第二类丢失更新:是不可重复读的特殊情况。如果两个事物都读取同一行,然后两个都进行写操作,并提交,第一个事物所做的改变就会丢失
2. redis事务特征
1、 在事务中的所有命令都将会被串行化的顺序执行,事务执行期间,Redis不会再为其它客户端的请求提供任何服务,从而保证了事物中的所有命令被原子的执行
2、 和关系型数据库中的事务相比,在Redis事务中如果有某一条命令执行失败,其后的命令仍然会被继续执行。
3、 我们可以通过MULTI命令开启一个事务,有关系型数据库开发经验的人可以将其理解为"BEGIN TRANSACTION"语句。在该语句之后执行的命令都将被视为事务之内的操作,最后我们可以通过执行EXEC/DISCARD命令来提交/回滚该事务内的所有操作。这两个Redis命令可被视为等同于关系型数据库中的COMMIT/ROLLBACK语句。
4、 在事务开启之前,如果客户端与服务器之间出现通讯故障并导致网络断开,其后所有待执行的语句都将不会被服务器执行。然而如果网络中断事件是发生在客户端执行EXEC命令之后,那么该事务中的所有命令都会被服务器执行。
5、 当使用Append-Only模式时,Redis会通过调用系统函数write将该事务内的所有写操作在本次调用中全部写入磁盘。然而如果在写入的过程中出现系统崩溃,如电源故障导致的宕机,那么此时也许只有部分数据被写入到磁盘,而另外一部分数据却已经丢失。Redis服务器会在重新启动时执行一系列必要的一致性检测,一旦发现类似问题,就会立即退出并给出相应的错误提示。此时,我们就要充分利用Redis工具包中提供的redis-check-aof工具,该工具可以帮助我们定位到数据不一致的错误,并将已经写入的部分数据进行回滚。修复之后我们就可以再次重新启动Redis服务器了。
3. redis事务处理
redis事务通过MULTI、WATCH、UNWAYCH、EXEC、DISCARD五个命令实现
multi、watch、unwaych、exec、discard、
MUTIL命令:用于开启一个事务,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行,它总是返回OK
WATCH命令:对键进行监视,直到用户执行EXEC命令的这段时间里面,如果其他客户端抢先对任何被监视的键进行了替换、更新或删除等操作,那么当用户舱室执行EXEC命令的时候,事务将失败并返回一个错误(之后用户可以选择重试或者放弃事务)
UNWATCH命令:在WATCH命令执行之后,EXEC命令执行之前对链接进行重置
EXEC命令:执行事务命令
DISCARD命令:客户端可以取消WATCH命令名清空所有已入队命令
4. 持久化(RDB,AOF)
\1. 为什么要持久化:
Redis是内存数据库。他将自己的数据库存储状态存储在内存中,如果不想方法把数据库状态保存到磁盘中,一旦服务进程退出,服务器中的数据库状态也将消失不见。
\2. 解决方法:redis提供了RDB持久化功能,这个功能将redis内存中的数据库状态保存到磁盘中,避免数据意外丢失。
\3. RDB持久化:
RDB持久化功能产生一个RDB文件(经过压缩的二进制文件)可还原成数据库状态。
保存在硬盘里,存在即可还原。
RDB文件的创建与载入:
两个redis命令用于生成RDB文件:SAVE ,BGSAVE。
Save命令:会阻塞redis服务进程,直到RDB文件创建完成。服务器阻塞期间,服务器不能处理任何命令请求。
redis> SAVE //等待生成RDB文件
ok
BGSAVE命令会派生一个子进程,然后由子进程负责创建RDB文件,服务父进程继续处理命令。
保存条件
[redis]$ more /usr/local/redis/conf/redis.conf
save 900 1 #服务器900秒内,对数据库至少修改一次
save 300 10 #服务器300秒内,对数据库至少10次修改
save 60 10000 #服务器60秒内,对数据库至少10000次修改
dbfilename “dump.rdb” #持久化文件名称
dir "/data/dbs/redis/ #持久化数据文件存放的路径
满足任意三个条件之一,bgsave就会执行。
4.AOF持久化
RDB持久化是通过保存数据库中的键值对来记录数据的状态不同,AOF持久化是通过保存redis服务器所执行的写命令来记录数据库状态的。
例子:
redis> set msg “hello”
ok
redis> sadd fruits “apple” “banana” “cherry”
(integer) 3
redis>rpush numbers 128 256 512
(interger) 3
AOF持久化的方法是将服务器执行的set ,sadd,rpush三个命令保存到AOF文件中
而,RDB持久化是将msg,fruits,numbers三个键的键值对保存到RDB文件。
5.2AOF载入:
服务器启动时通过载入和执行AOF文件中的命令还原数据库状态。
5.3AOF持久化的实现:
1.命令追加 2.文件写入3.文件同步 三个步骤
命令追加:
当AOF持久化功能处于打开状态时,服务器在执行一个写命令之后,会以协议格式将被执行的写命令追加到服务器的aof_buf缓存区的末尾:
例子:
redis>set key value
ok
服务器在执行完整个set命令之后会将以下协议内容追加到aof_buf缓冲区末尾:
*3\e\n$3…\r\n
然后执行:
redis>rpush numbers one two three
(integer ) 3
那么服务器在执行rpush命令之后将以下协议内容追加到aof_buf缓冲区末尾:
*5\r\n$3…\r\n
文件写入与同步:
Redis的服务器进程就是一个事件循环(loop),这个循环中的文件事件负责接收客户端的命令请求,以及向客户端发送命令回复,而时间事件是负责执行定时运行函数(serverContron)。
因为服务器处理文件事件会执行写命令,使一些内容追加到aof_buf缓冲区里,所以服务器每次在结束一个事件循环之前,都会调用flushAppendOnlyFile函数,考虑是否将aof_buf缓冲区的内容写入和保存到Aof文件里。
AOF文件的载入与数据还原:
5.面试题:简单介绍AOF持久化和AOF文件与RDB持久化的区别.:
因为AOF文件的更新频率比RDB文件的更新频率高,所以:
1.如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态。
2.只有在AOF持久化功能处于关闭状态的时候,服务器才会使用RDB文件来还原数据库状态。