Redis事务简介
Redis通过multi、exec、watch等命令来实现事务功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行的期间,服务器不会中断事务而改去执行其他客户端命令的请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求。
示例
事务的实现
事务开始
multi命令的执行标志着事务的开始。
multi命令可以将执行该命令的客户端从非实物状态切换至事务状态,这一切换是通过在客户端状态的flags属性中打开REDIS_MULTI标识来完成的。
命令入队
当一个客户端处于非事务状态时,这个客户端发送的命令会立即被服务器执行
与此不同的是,当一个客户端切换到事务状态后,服务器会根据这个客户端发来的不同命令执行不同的操作:
- 如果客户端发送的命令为exec、discard、watch、multi四个命令中的其中一个,那么服务器会立即执行这个命令
- 如果客户端发送的是其他的命令,那么这些命令不会被立即执行,而是被放到一个事务队列中,然后向客户端发送queued回复。
事务执行
当一个处于事务状态的客户端向服务器发送exec命令时,这个命令将被服务器立即执行。服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令所得的结果全部返回给客户端。
Watch命令实现
watch命令是一个乐观锁,他可以在exec命令执行之前,监视任意数量的数据库键,并在exec命令执行时,检查被监视的键是否至少有一个已经被修改了,如果是的话,服务器将拒绝执行事务,并向客户端返回代表事务执行失败的空回复。
watch原理
每个redis数据库都保存着一个watched_keys字典,这个字典的键是某个被watch命令监视的数据库键,而字典的值则是一个链表,链表中记录了所有监视相应数据库的客户端。
所有对数据库进行修改的命令,比如set、lpush、sadd、zrem、del、flushdb等等,在执行之后都会对watched_keys字典进行检查,查看是否有客户端正在监视被修改的键,如果有的话,就修改对应客户端的redis_dirty_cas标识,值为true,表示该客户端的事务安全性已经被破坏。
当服务器接收到一个客户端发来的exec命令时,服务器会根据这个客户端是否打开redis_dirty_cas标识来决定是否执行事务。