事务处理介绍
目前软件具备的基本功能, 主要是兼容memcache的指令集, 增加了部分指令, 增加了日志功能, 支持BGSAVE, 保存数据不影响正在进行的任何操作.
现已完成了一个简单的类似redis的事务处理机制, 支持MULTI, EXEC, DISCARD,WATCH,UNWATCH这5条指令, 实现有限度的简单事务. 在这周已经完成.
一、事务处理概念
1.事务定义
事务,一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。 数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。
事务提供了一种“将多个命令打包, 然后一次性、按顺序地执行”的机制, 并且事务在执行的期间不会主动中断 —— 服务器在执行完事务中的所有命令之后, 才会继续处理其他客户端的其他命令。
MULTI 命令的执行标记着事务的开始,这个命令唯一做的就是, 将客户端的 MULTI
选项打开, 让客户端从非事务状态切换到事务状态;
当客户端进入事务状态之后, 服务器在收到来自客户端的命令时, 不会立即执行命令, 而是将这些命令全部放进一个事务队列里, 然后返回 QUEUED
, 表示命令已入队.
如果客户端正处于事务状态, 那么当 EXEC 命令执行时, 服务器根据客户端所保存的事务队列, 以先进先出(FIFO)的方式执行事务队列中的命令: 最先入队的命令最先执行, 而最后入队的命令最后执行。
当事务队列里的所有命令被执行完之后, EXEC 命令会将回复队列作为自己的执行结果返回给客户端, 客户端从事务状态返回到非事务状态, 至此, 事务执行完毕。
DISCARD 命令用于取消一个事务, 它清空客户端的整个事务队列, 然后将客户端从事务状态调整回非事务状态, 最后返回字符串 OK
给客户端, 说明事务已被取消。
WATCH 命令用于在事务开始之前监视任意数量的键: 当调用 EXEC 命令执行事务时, 如果任意一个被监视的键已经被其他客户端修改了, 那么整个事务不再执行, 直接返回失败。
除了 EXEC 之外, 服务器在客户端处于事务状态时, 不加入到事务队列而直接执行的另外三个命令是 DISCARD 、 MULTI 和 WATCH 。
当客户端已经处于事务状态, 而客户端又再向服务器发送 MULTI 时, 服务器只是简单地向客户端发送一个错误, 然后继续等待其他命令的入队。 MULTI 命令的发送不会造成整个事务失败, 也不会修改事务队列中已有的数据。
WATCH 只能在客户端进入事务状态之前执行, 在事务状态下发送 WATCH 命令会引发一个错误, 但它不会造成整个事务失败, 也不会修改事务队列中已有的数据(和前面处理 MULTI 的情况一样)。
2.事务工作要点
针对数据的操作,例如插入、删除和修改,这是典型的事务操作,这些操作的对象是大量的数据。
二.事务处理命令介绍
MULTI:将缓冲此命令后的所有正确格式命令,直到命令 discard/exec 输入为止.
EXEC:将加锁执行已经缓存的多条指令,并且依次返回执行结果.
DISCARD:将丢弃缓存的从最近的'multi'命令之后的多条指令.
WATCH:将记录当前数据表中的一个或多个key对应的版本号. 在执行exec前检查如果发现观察版本号有变,取消执行并返回错误.
UNWATCH:将取消所有watch设置的对key的监控.
.数据的读一致性
读一致性可确保所有用户看到的数据视图始终是一致的,读取者看不到正在被更改的数据,保证写入者对数据库的更改是在一致的方式下完成的,一个写入者所做的更改不会中断另一个写入者正在进行的更改,也不会与之相冲突。
三、事务处理的优点
1.单查询语句并发
采用单语句查询并发的模式,数据库中的每个表都被分成256个组,当进行全表扫描时,若有8个CPU,则可以同时并发,同时扫描256个组,充分利用CPU,大大降低扫描时间,提高了性能。
2.单机容易扩展到多机
在任务队列中,传送命令时,它的思想与分布式多机并发的思想一样,因此可以从单机很容易的扩展到多机。
3.避免死锁
不会存在两个对象拥有一把锁的现象,而是一个对象分配一把锁,来一个分配一个,永远不会发生死锁。
根据操作系统中的定义:死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站用不会释放的资源而处于的一种永久等待状态。
四. 小结
-
事务提供了一种将多个命令打包,然后一次性、有序地执行的机制。
-
事务在执行过程中不会被中断,所有事务命令执行完之后,事务才能结束。
-
多个命令会被入队到事务队列中,然后按先进先出(FIFO)的顺序执行。