【Redis】Redis事务详解
文章目录一.认识Redis的事务二.Redis事务的意义三.Redis事务的应用场景四.事务的相关命令一.认识Redis的事务MySQL的事务原子性 将多个操作打包成一个整体一致性事务执行前后数据是符合预期的持久性事务的修改都要进行落盘隔离性处理并发问题1.Redis既可以说有原子性也可以说没有原子性(推荐)原子性最初的含义是将多个操作进行打包要么全部执行要么都不执行这也是Redis所谓的原子性但是MySQL中的原子性还保证了这些操作要么全部执行成功要么都不执行即MySQL提高了原子性的门槛使得别人谈到原子性都会想到的是这种带有回滚的原子性2.Redis没有一致性 其没有约束没有回滚机制事务执行时如果出现修改操作失败则可能产生不一致的问题3.Redis没有持久性因为Redis是内存数据库数据存储在内存中虽然其有持久化机制但这和事务是没有关系的4.Redis没有隔离性Redis是一个单线程模型的服务器程序所有的请求/事务都是串行执行的二.Redis事务的意义Redis事务存在的意义为了进行打包避免其他客户端命令进行插队这里的意思是有些操作是一起的但服务器并不一定能一起处理他们可能被其他客户端进行插队因此引入事务让这些操作打包每次一起进行处理Redis在每个客户端都引入了一个队列开启事务时客户端输入的命令都会发送给服务器并进入该队列中(不是立即执行)该队列是在服务器上的每个客户端和服务器的连接都有这样的队列。客户端发的请求会缓存在该队列中 可以视作客户端和服务器建立了TCP连接通过连接管理管理这个队列当遇到了“执行事务”命令时此时就会把队列中的任务都按照顺序依次执行(由主线程完成主线程完成事务的操作后再处理其他客户端)问题一Redis事务为什么设计的如此简单为什么不像MySQL一样MySQL的事务在背后付出了很多的代价– 空间上要花费更多的空间存储更多的数据(索引日志。。。。。。)– 时间上存在更大的执行开销(持久化锁引起的阻塞等)三.Redis事务的应用场景假设现在有一个付费场景限量5000人之外的人无法下单如何设计(秒杀)//经典写法intn剩余商品的个数if(n0){下单;剩余商品--;}如上的写法显然存在线程安全问题使用事务可以很好的解决如上问题开启事务后每个客户端的这些操作发给服务器都不会立即执行而是先让入队列中当收到执行事务的命令后才执行这些命令且是一次性完成后才会去处理其他请求》如上未通过加锁就解决了超卖问题Redis的事务实际的应用场景并不如MySQL那样多(甚至有点鸡肋)问题一虽然维护了队列但是服务器怎么知道这些命令是我这个客户端的呢Redis和客户端建立了诸如TCP连接通过连接管理就可以知道哪些数据属于谁四.事务的相关命令MySQL事务相关指令主要如下开启事务 multi执行事务 exec放弃当前事务 discardwatch命令监控某个key看其是否在执行前(multi和exec之间)发生了改变watch的实现原理watch的实现类似于乐观锁或者悲观锁(不是真锁只是锁的特性)Redis的watch相当于基于版本号这样的机制实现了乐观锁当事务执行exec时会对版本号进行判定判断当前的版本号和最初watch的版本号是否一致– 如果一致说明key在事务开启到执行过程中没有其他客户端对该key进行修改执行– 如果不一致说明key在该事务期间被其他客户端进行了修改则放弃事务中的操作.exec返回nil类似于CAS的ABA问题Redis中支持lua脚本可以起到类似于事务的效果事务的任何效果都可以用lua脚本替代