事务transition
Redis事务的本质是一组命令的集合,一次执行多个指令,事务中所有命令都被序列化,其他客户端提交的命令请求不会插入到事务执行命令序列中,简单来说:要不全执行,要不全不执行。Redis中提供了简单的事务功能,需要multi和exec两个命令实现。
事务执行流程:
- 开启事务(multi)
- 命令入队(…)
- 执行事务(exec)| 取消事务(discard)
在Redis的事务中的命令出现不同错误时,处理机制也会有所差异:
编译型异常(命令错误),事务中所有命令都不会执行,因为Redis没有隔离级别的概念,队列中的命令没有提交之前都不会实际的被执行:
运行时异常(1/0),如果事务队列中存在语法性错误,那么执行命令的时候,其它命令是可以正常执行的,错误命令抛出异常,由此看出Redis的单条命令保证原子性,但是事务并不保证原子性,不支持回滚功能。
锁
在有些应用场景需要在事务之前,确保事务中的key没有被其它客户端修改过,才执行事务,否则不执行,着类似于乐观锁的概念,在Redis中也提供了相关实现方法:
- 监视、加锁(watch)
- 取消监视、解锁(unwatch)
乐观锁:
假设数据一般情况不会造成冲突(很乐观,认为什么时候都不会出问题),在数据提交更新时正式对数据的冲突与否进行检测,发现了冲突,发出错误信息,让用户决定如何处理,适用于读操作多的场景,可以提高程序的吞吐量。
为了避免数据库的幻读,业务处理时间过长,乐观锁不会刻意使用数据库本身的锁机制,而是依据数据本身来保证数据的正确性
实现方法:
当有多个线程在操控redis的时候,被watch监视的key值如果发生改变,正在进行的事务将会失败,每次加锁后都要进行解锁,再加锁去重新获取最新的值
正常流程:
出现线程问题: