事务
pipeline和串行化模式在多个客户端存在的情况下,不同客户端的命令可能会交替执行。
这样情况下,一个客户端无法实现批量执行的命令原子化执行,因此需要redis事务实现原子化。
概念:客户端一次事务希望命令可以原子化执行,没有其他命令掺入。
实现:客户端开启事务命令后,发送的命令暂存在服务端的队列中,当所有命令发送完成后,再批量执行。由于redis单线程执行命令,因此可以确保不会执行其他客户端的命令。
事务中读写命令的区分及造成的问题:
客户端应该在入队列时确定每个写命令的值,即不能依赖其他命令执行结果。而事务操作需要只读操作判断写入的值。但是队列中要批量执行的只有写入操作,因为批量执行只读操作没有意义。需要客户端先执行读取命令,判断要写入的值,再加事务去执行。但这之间存在其他客户端更改之前读过的记录的可能。
redis实现乐观锁解决这一问题:
1、将事务涉及的key加入观察者模式watch
2、执行只读操作
3、客户端根据只读操作,设置写操作的值
4、发送写命令入队列
5、批量提交。此时如果之前被watch的key被修改,则exec失败,拒绝执行。
注:
redis事务无法实现严格一致性:当事务中的命令开始exec执行时,若执行出现错误,后续命令继续执行,只会在返回时标记出错的命令和结果,由客户端决定如何恢复。redis自身并不支持回滚,因此无需引入版本机制。